Compare commits

..

5 Commits

Author SHA1 Message Date
Mario Fetka 3200be221c Import release 2.0.6 2011-02-08 19:31:37 +00:00
Mario Fetka 452059cb18 Import release 2.0.5 2010-10-25 23:41:51 +00:00
Mario Fetka c84d96043e Import release 2.0.4 2010-07-26 08:45:10 +00:00
Mario Fetka 3179f447ce Import release 2.0.3 2010-03-10 13:51:09 +00:00
Mario Fetka 9c0c6480e3 Import release 2.0.2 2009-12-04 22:51:32 +00:00
282 changed files with 58122 additions and 23395 deletions
-43
View File
@@ -1,43 +0,0 @@
[Buildset]
Number of Builditems=1
[Buildset][Builditem0]
Itemname=KMess
Itempath=./
Projectname=KMess
[CMake]
BuildDirs=./build
CMakeDir=/usr/share/cmake/Modules
Current CMake binary=cmake
CurrentBuildDir=./build
CurrentInstallDir=
ProjectRootRelative=./
[Chat Window debug-Run Options]
Arguments=--runtest chatwindow
Executable=./build/src/kmess
Working Directory=./build/src/
[Contact List debug-Run Options]
Arguments=--runtest contactlist
Executable=./build/src/kmess
Working Directory=./build/src/
[Debug-Run Options]
Executable=./build/src/kmess
[MakeBuilder]
Abort on First Error=false
Number Of Jobs=3
Run Multiple Jobs=true
[Project]
VersionControlSupport=kdevsubversion
[Run Options]
Run Targets=Chat Window debug,Contact List debug,Debug
[Veritas]
executables=
framework=QTest
+28 -2
View File
@@ -28,7 +28,7 @@
Mauricio Rother <mauricio@digicomm.com.br>
Leonel Freire <leonelfreire@gmail.com>
Sergio Rafael Lemke <bedi.com@gmail.com>
Maurício Arozi Moraes
Morris Arozi Moraes
Catalan:
@@ -58,7 +58,7 @@
Jaap Woldringh <jjh.woldringh@planet.nl>
Elve <elve@savage-elve.net>
Sander Pientka <cumulus0007@gmail.com>
Heimen Stoffels <djmusic121@gmail.com>
Heimen Stoffels <vistausss@gmail.com>
Estonian:
@@ -66,6 +66,7 @@
Lauri Võsandi <v6sa@hotmail.com>
Mihkel Tõnnov <mihhkel@gmail.com>
Rivo Laks <rivolaks@hot.ee>
Timo Tambet <ttambet@gmail.com>
Finnish:
@@ -82,6 +83,12 @@
Andrea Blankenstijn <darkan9el@gmail.com>
Barthe Guillaume <gu_barthe@yahoo.fr>
Scias <shining.scias@gmail.com>
Grégory Bellier <gregory.bellier@gmail.com>
Anthony Rey <gnuk@mailoo.org>
Galician:
Indalecio Freiría Santos <ifreiria@gmail.com>
German:
@@ -118,6 +125,14 @@
Øyvind Sæther <oyvind@sather.tk>
Portuguese:
Bruno Almeida <bruno.r.almeida@gmail.com>
Russian:
Dmitriy Simbiriatin <slpiv@mail.ru>
Serbian:
Zoran Milovanović <provalisam@gmail.com>
@@ -229,6 +244,17 @@
- Emoticon preview in settings page
- Clickable contact properties dialog text
Marco Mentasti <marcomentasti@gmail.com>
- Internationalization fixes
- Drag'n'drop of images into display pictures
Francesco Nwokeka
- Now Listening toggle button above the contact list.
Timo Tambet <ttambet@gmail.com>
- Contact Changed and Group Changed notifications.
- Contact added user dialog tabbing
KMerlin <http://kmerlin.olsd.de/>
- Inspiration and assorted code
+76 -60
View File
@@ -13,59 +13,63 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.4.5 )
# Check for KDE 4
FIND_PACKAGE( KDE4 REQUIRED )
INCLUDE( KDE4Defaults )
# Make sure the rest still works
IF( NOT KDE4_FOUND )
# The macro's MACRO_LOG_FEATURE, MACRO_OPTIONAL_FIND_PACKAGE, MACRO_BOOL_TO_01
# are part of the KDE cmake modules, so these can't be used now.
MESSAGE( FATAL_ERROR "\n"
" The KDE Development Platform was not found.\n"
" \n"
" You will need this package and the matching development package.\n"
" Usually the package names for this library are:\n"
" on Debian and Ubuntu: 'kdebase-runtime' and 'kdelibs5-dev'\n"
" on openSUSE: 'kdebase4-runtime' and 'libkde4-devel'\n"
" \n"
" Please refer to the KMess board for more info,\n"
" and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ENDIF( NOT KDE4_FOUND )
# Check for libxml2
FIND_PACKAGE( LibXml2 )
MACRO_LOG_FEATURE( LIBXML2_FOUND "LibXML2" "Libraries used to develop XML-aware applications" "http://www.xmlsoft.org/" TRUE ""
" Required for the chat styles system.
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
* Usually the package names for this library are:
on Ubuntu: 'libxml2' and 'libxml2-dev'
on openSUSE: 'libxml2' and 'libxml2-devel'
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
"Required for the chat styles system.
* You will need this package and the matching development package: for example, 'libxml2' and 'libxml2-dev' or 'libxml2-devel'.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libxml2' and 'libxml2-dev'
on openSUSE: 'libxml2' and 'libxml2-devel'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
# Check for libxslt
FIND_PACKAGE( LibXslt )
MACRO_LOG_FEATURE( LIBXSLT_FOUND "LibXSLT" "A library to transform XML into other formats" "http://www.xmlsoft.org/XSLT" TRUE ""
" Required for the chat styles system.
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
* Usually the package names for this library are:
on Ubuntu: 'libxslt' and 'libxslt-dev'
on openSUSE: 'libxslt' and 'libxslt-devel'
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
"Required for the chat styles system.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libxslt' and 'libxslt1-dev'
on openSUSE: 'libxslt' and 'libxslt-devel'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
# Check for qca2
FIND_PACKAGE( QCA2 )
MACRO_LOG_FEATURE( QCA2_FOUND "QCA 2" "A cryptographic library written in Qt to access various encryption methods" "http://delta.affinix.com/qca/" TRUE ""
" Required for the Windows Live Messenger login process.
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
* Usually the package names for this library are:
on Ubuntu: 'libqca2', 'libqca2-dev' and 'libqca2-plugin-ossl'
on openSUSE: 'libqca2' and 'libqca2-devel'
on Fedora: 'qca2' and 'qca2-devel'
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
# Add cmake directory to the MODULE_PATH, so cmake can find GCrypt
SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} $ENV{CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake )
# As far as I know, it is impossible to find out if the required QCA plugin for OpenSSL is installed:
# so we need to ask QCA itself it it's got such a plugin. Pretty darned unportable stuff.
IF( QCA2_FOUND )
IF( UNIX )
EXECUTE_PROCESS( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/check-qca2-ossl.sh OUTPUT_VARIABLE HAS_QCA2_OSSL_PLUGIN )
IF( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
SET( QCA2_OSSL_PLUGIN_FOUND TRUE )
ELSE( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
SET( QCA2_OSSL_PLUGIN_FOUND FALSE )
ENDIF( HAS_QCA2_OSSL_PLUGIN EQUAL 1 )
MACRO_LOG_FEATURE( QCA2_OSSL_PLUGIN_FOUND "QCA 2 - OpenSSL Plugin" "OpenSSL interaction library for QCA2" "http://delta.affinix.com/qca/" TRUE ""
" Required for the Windows Live Messenger login process.
* This package should have been installed along QCA2: if you have QCA2 installed
but still see this message, your distribution probably packages it separately.
Ubuntu does this, the package name is 'libqca2-plugin-ossl'.
* Please refer to the KMess forum for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ELSE( UNIX )
# TODO: Find another *portable* way to detect the OSSL plugin.
MESSAGE( STATUS "NOTE: The qca2 OpenSSL can't be detected on this platform yet. Make sure you have it installed." )
ENDIF( UNIX )
ENDIF( QCA2_FOUND )
# Check for GCrypt
FIND_PACKAGE( GCrypt )
IF( NOT GCRYPT_FOUND )
MACRO_LOG_FEATURE( GCRYPT_FOUND "GCrypt" "A library to encrypt messages with various cyphers" "http://www.gnupg.org/" TRUE ""
"It is required for the Live Messenger login process.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libgcrypt' and 'libgcrypt11-dev'
on openSUSE: 'libgcrypt' and 'libgcrypt-devel'
on Fedora: 'gcrypt' and 'gcrypt-devel'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ELSE()
MESSAGE( STATUS "Looking for GCrypt - found" )
ENDIF()
# Check for XScreenSaver extension
OPTION( WANT_XSCREENSAVER "Build with X11 screensaver auto-away support" ON )
@@ -74,11 +78,12 @@ IF( WANT_XSCREENSAVER )
MACRO_OPTIONAL_FIND_PACKAGE(X11)
IF( X11_FOUND )
MACRO_LOG_FEATURE( X11_Xscreensaver_FOUND "XScreenSaver" "X11 extension used to check idle state" "" FALSE ""
" Required for the auto-away feature.
* Usually the package names for this library are:
on Ubuntu: 'libxss-dev'
on openSUSE: 'xorg-x11-libs'
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
"Required for the auto-away feature.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libxss-dev'
on openSUSE: 'xorg-x11-libs'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
ELSE( X11_FOUND )
MESSAGE( STATUS "NOTE: The auto-away feature is not supported on this platform yet." )
ENDIF( X11_FOUND )
@@ -89,21 +94,32 @@ ENDIF( WANT_XSCREENSAVER )
# (for an optional feature, we don't want that to be fatal)
MACRO_OPTIONAL_FIND_PACKAGE( LibKonq QUIET )
MACRO_LOG_FEATURE( LIBKONQ_FOUND "LibKonq" "Integration with Konqueror context menu" "http://www.kde.org/" FALSE ""
" Optional context menu integration with Konqueror.
* You will need this package and the matching development package: for example, 'kmess' and 'kmess-dev' or 'kmess-devel'.
* Usually the package names for this library are:
on Ubuntu: 'libkonq5' and 'libkonq5-dev'
on openSUSE: 'libkonq5' and 'libkonq-devel'
* Please refer to the KMess board for more info, and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
"This is an optional feature.
* Usually the package names for this library are:
on Debian and Ubuntu: 'libkonq5' and 'libkonq5-dev'
on openSUSE: 'libkonq5' and 'libkonq-devel'
* Please refer to the KMess board for more info,
and specially to this guide: http://trac.kmess.org/wiki/Compiling%20KMess" )
# Check for libisf-qt
MACRO_OPTIONAL_FIND_PACKAGE( IsfQt QUIET )
MACRO_LOG_FEATURE( ISFQT_FOUND "LibISF-Qt" "Library to manage Microsoft's Mobile Ink" "http://www.kmess.org/" FALSE ""
" Support to send handwriting messages in a format compatible with Windows Live Messenger.
In absence of an installed isf-qt version, the bundled version will be compiled.")
"Support to send handwriting messages in a format compatible with Windows Live Messenger.
In absence of an installed isf-qt version, the bundled version will be compiled.")
MACRO_BOOL_TO_01( ISFQT_FOUND HAVE_LIBISFQT ) # For config-kmess.h.in
# Check for KNotificationItem. KDE 4.3.1 and later have it integrated in kdelibs/experimental.
# It will be available by default in 4.4.
IF( ${KDE_VERSION} VERSION_LESS 4.3.70 ) # KDE trunk has a higher version number than this.
MACRO_OPTIONAL_FIND_PACKAGE(LibKNotificationItem-1)
MACRO_LOG_FEATURE( LIBKNOTIFICATIONITEM-1_FOUND "LibKNotificationItem-1" "The experimental new KDE systray library" "http://www.kde.org" FALSE ""
"LibKNotificationItem-1 is the experimental new KDE systray library. It will be included
by default in KDE 4.4 and is available for use in KDE 4.3.1 and above." )
MACRO_BOOL_TO_01( LIBKNOTIFICATIONITEM-1_FOUND HAVE_NEW_TRAY )
ELSE()
SET( HAVE_NEW_TRAY 1 )
ENDIF()
# Display the dependency collection results
MACRO_DISPLAY_FEATURE_LOG()
@@ -133,8 +149,8 @@ INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${LIBXM
#### Define the app version number ####
# Switch between the following two commands to force using a predefined version number
# EXECUTE_PROCESS( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/get-svn-version.sh OUTPUT_VARIABLE KMESS_VERSION )
SET( KMESS_VERSION "2.0.1" )
# EXECUTE_PROCESS( COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cmake/get-git-version.sh OUTPUT_VARIABLE KMESS_VERSION )
SET( KMESS_VERSION "2.0.6" )
#### Define compiler flags ####
@@ -162,7 +178,7 @@ ENDIF( CMAKE_COMPILER_IS_GNUCXX )
# - relwithdebinfo (release with debug info)
# - minsizerel (minsize release)
# Uncomment the next line to always force building in full debug mode
# SET( CMAKE_BUILD_TYPE debugfull )
SET( CMAKE_BUILD_TYPE debugfull )
# Enable the KMess debug output when compiling a debug build
IF( CMAKE_BUILD_TYPE STREQUAL debugfull OR KMESS_DEBUG_OUTPUT EQUAL 1 )
+165
View File
@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
+444 -3
View File
@@ -1,4 +1,445 @@
--- 2.0.6 released ---
2011-01-13 (Adam)
* Fix bug where KMess couldn't login due to badly formed URL commands.
2011-01-08 (Valerio)
* Fixed crash when taking any action in the Contact Added User dialog.
Also removed an unnecessary signal-bouncing slot.
* Fixed a dangling pointer issue when the Contact Added User dialog was
shown, closed and shown again.
2011-01-05 (Adam)
* Add new widget, FaderWidget, which smoothly fades between the initial view
and the contact list. Disable by setting NoFadeEffect to true under the
MainWindow section of kmessrc.
2011-01-02 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
* Merged an updated Spanish translation by Daniel E. Moctezuma.
* Merged an updated German translation.
2010-12-24 (Adam)
* Fix retrieval of roaming display picture.
2010-12-23 (Adam)
* Fix a problem where roaming service profile data was invalid.
2010-12-13 (Valerio)
* Fixed "Visit Link" context-menu icon in chat. Thanks to IRC's agostino for the
heads-up.
2010-11-16 (Adam)
* (Finally) merged in a modified patch by Timo Tambet that groups all
"contact added user" windows as tabs under a single dialog.
--- 2.0.5 released ---
2010-10-23 (Valerio)
* Added new chats to the log records, no need to logout to see the chat logs of
the current session anymore.
* Made the HTTP connection timer fix from yesterday to compile with Qt < 4.7.
* Fixed building with certain compiler configurations.
2010-10-22 (Valerio)
* Show user's display picture in chat by default.
* Fixed HTTP connection timers, now midnight and clock skews don't cause any
more the HTTP rate limiter to fail.
2010-10-16 (Valerio)
* Integrated Chat History with the Chat Window:
- added a menu item and toolbar action, showing a menu containing the current
tab's contacts;
- added a context menu entry in the Contacts Panel.
* Removed some unused code in ContactFrame.
* Fixed logging in with long passwords (17+ characters). The Live servers don't
accept those, hehehe.
2010-10-16 (Adam)
* Fix the parsing of offline IM messages.
2010-09-19 (Adam)
* Fix a signal issue in MsnNotificationConnection, thanks Timo Tambet
2010-09-10 (Pano)
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
2010-09-03 (Adam)
* Fix a crash caused when the contacts widget was deleted twice in a chat window.
2010-09-02 (Sjors)
* Add <html> tag to status notification messages so HTML is stripped correctly
by knotify.
2010-08-13 (Pano)
* Merged an updated Estonian translation by Timo Tambet.
2010-08-13 (Pano)
* Merged an updated Hungarian translation by József Makay.
2010-08-11 (Adam)
* Merge modified patch by Timo Tambet that gives notifications for address
book changes (contact and group changes).
2010-08-05 (Adam)
* Bump version number to 2.0.5dev
2010-08-05 (Sjors)
* Made the SOAP request waiter its own object instead of a QTimer::singleShot
because now it can be stopped if logging in fails, fixing a crash.
2010-08-04 (Pano)
* Merged an updated French translation by Anthony Rey.
--- 2.0.4 released ---
2010-07-25 (Adam)
* Fix ticket #524, thanks to Timo Tambet
2010-07-24 (Adam)
* Properly handle non-messenger Hotmail contacts that appear on our address book.
They need to be marked as Messenger users once we add them to our contact list.
2010-07-23 (Adam)
* Add get-git-version.sh script to return the HEAD revision KMess was built with.
Removed get-svn-version.sh accordingly.
* When adding a contact, the contact type should be "Regular" AFAIK.
* Add AddressBookService::removePending to remove a handle from the Pending list.
* AddressBookService::getMembershipListUpdate now calls the correct method when
deleting a membership.
2010-07-22 (Valerio)
* Fixed the conditions to enable the "Save chat" and "Clear chat" options in the chat view's context menu.
2010-07-21 (Valerio)
* Fixed contact frame tooltips, there were HTML entities exposed.
2010-07-20 (Pano)
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
2010-07-17 (Adam)
* Improve the handling of contacts that are on the address book and
the pending list at the same time (shouldn't happen, but it does).
* If a user is already on the friend list, don't allow the "add" option
to be chosen in ContactAddedUserDialog.
* Index all contacts by lower case handle to avoid any casing issues on retrieval.
2010-07-17 (Adam)
* Attempt to solve some of the memory issues on KDE 4.5.
2010-07-12 (Adam)
* Fix contact list background issues on KDE 4.5
2010-07-10 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
2010-07-06 (Pano)
* Merged an updated French translation by Grégory Bellier.
* Merged an updated German translation.
2010-07-06 (Valerio)
* Fixed sending messages only containing whitespace.
2010-07-05 (Valerio)
* Fixed pressing Enter to send a drawing worked even when nothing was in the drawing.
2010-07-04 (Valerio)
* Fixed the ability to drag'n'drop into the message editor a received Ink drawing, and an issue with
the Ink editor button when doing so.
2010-06-29 (Valerio)
* Added a class to autonomously manage the chat logs retrieval.
* Rewritten the Chat History dialog, now using a calendar to list dates with available chat logs.
2010-06-27 (Pano)
* Merged an updated Traditional Chinese translation by the Tryneeds-Chinese Translation Platform.
2010-06-27 (Valerio)
* Made immutable the display picture size in the contacts dock, to avoid weird picture resizes.
* Made the chat history box to respect the "Show the emails of contacts instead of the friendly name" option.
* Merged patch by dah_, changing the contact list to be sorted by status, then alphabetically.
2010-06-27 (Adam)
* Add a check to ABService to prevent it recognising memberships for
non-passport members. Otherwise when we try to manipulate the memberships
for non-passport members we'll get errors since we're not handling them
correctly.
* Only pop up the "Contact Added User" dialog if a user is on the Pending list.
* Fix comments in kmess.notifyrc
2010-06-26 (Valerio)
* Fixed wrong URL when retrieving a display picture from the server.
* Changed X11 libraries inclusion to fix building KMess from Fedora 13.
2010-06-24 (Pano)
* Merged an updated Dutch translation by Heimen Stoffels.
2010-06-20 (Adam)
* Fix a i18n bug in the system tray code.
2010-06-19 (Valerio)
* Added support for a new ISF-Qt feature, PNG fortification. This allows users
to drag and drop their and their contacts' drawings into the message editor
to be edited.
2010-06-19 (Adam)
* Backported the new KDE4 system tray spec. Remains optional for people who
are using KDE < 4.3.
2010-06-13 (Sjors)
* Workarounded a documented limitation in KDE4_ADD_APP_ICON() to show the
KMess icon correctly.
2010-06-13 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2010-06-07 (Sjors) (noknotify branch)
* Fixed a crash because QSystemTrayIcon was constructed statically before
main().
* Taught MacNotification class how to play sounds.
* Made MacNotification class take some predefined actions on receiving
certain events.
2010-06-03 (Sjors) (noknotify branch)
* Added MacNotification class, which currently makes the KMess icon in the
Dock 'jump' when its method is called.
* Made the NotificationManager use MacNotification instead when doing
notifications on the Mac.
* Added support to MacNotification class to display Growl messages through
QSystemTrayIcon.
* Added support to MacNotification for stripping HTML off messages, so they
display correctly in Growl.
2010-05-31 (Adam)
* Fix bug in chatwindow.ui: use the global include for IsfInkCanvas.
2010-05-29 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2010-05-25 (Pano)
* Merged an updated Catalan translation by Adrià Arrufat.
2010-05-13 (Valerio)
* Fixed bug which made login to fail when the roaming service gives us a changed display
picture before setting the initial status.
2010-05-08 (Pano)
* Merged an updated Dutch translation by Heimen Stoffels.
2010-05-08 (sifcenter)
* Fixed bug on show listening music when the user is busy (maybe also with other states): the bit operation doesn't work
if the flags (STATUS_*) have more "1" bits set.
2010-05-03 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2010-04-25 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2010-04-15 (Pano)
* Merged an updated German translation.
2010-04-02 (Pano)
* Merged an updated Dutch translation by Heimen Stoffels.
2010-04-01 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2010-03-30 (Adam)
* Add Francesco Nwokeka to the credits dialog for the Now Playing toggle button.
* Workaround a Qt 4.6.1/4.6.2 bug which was causing multiple copies of a single DP to appear in the "set previous
display picture" dialog and the contact properties dialog.
2010-03-28 (Adam)
* Bug fix on MPRIS querying - the Identity method is located on the root interface, not the /Player interface.
* Reduce the number of debug messages coming out of NowListeningClient. Emits a debug message only when the song changes.
* Remove "contact does not have you on their contact list" text from the tool tips.
2010-03-27 (Adam)
* Merge a modified patch by z3r0 from the boards; adds a toggle button for "now listening" to the contact list.
* Display the currently playing song above the CL even while appearing offline.
* Make the size of the CL DP depend on whether or not music is playing.
* Adjust font size of now listening label to match personal message.
2010-03-17 (Adam)
* Fix bug where account properties were not properly updated in some cases.
* Fix bug where "Log in Automatically" was not obeyed and saved if it was unchecked after being enabled.
* When removing a contact that is already blocked, do not add them to the allow list.
2010-03-16 (Pano)
* Added a Galician translation by Indalecio Freiría Santos.
2010-03-13 (Adam)
* Fix bug where the status was set to "Idle" upon waking up from sleep.
* Fix bug where IDL status was kept after disconnection.
--- 2.0.3 released ---
2010-03-09 (Pano)
* Merged a Russian translation by Dmitriy Simbiriatin.
2010-03-05 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
* Merged an updated Slovak translation by Rastislav Krupanský.
2010-03-02 (Pano)
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
2010-03-01 (Pano)
* Merged an updated Spanish translation by Mauricio Muñoz Lucero.
* Merged an updated Turkish translation by Uğur Çetin.
* Merged an updated Portuguese translation by Bruno Almeida.
* Merged an updated Estonian translation by Rivo Laks.
2010-02-28 (Pano)
* Merged an updated Greek translation by Dimitrios Glentadakis.
2010-02-27 (Pano)
* Merged an updated German translation.
* Merged an updated Catalan translation by Adrià Arrufat.
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
* Merged an updated Dutch translation by Heimen Stoffels.
2010-02-26 (Pano)
* Merged an updated French translation by Grégory Bellier.
2010-02-25 (Pano)
* Merged an updated Hungarian translation by Pauli Henrik.
2010-02-22 (Pano)
* Added a Portuguese translation by Bruno Almeida.
2010-02-21 (Adam)
* Bug fix: ink editor was greyed out when changing tabs.
2010-02-20 (Ruben)
* Added DBus methods to get and set a personal message.
2010-02-20 (Adam)
* Backport: fix "contact added user" dialog appearing on next logon after deleting a contact.
2010-02-19 (Adam)
* Disable the reverse list colouring of the CL until we sort out the updating of membership lists.
2010-02-18 (Adam)
* Re-enable the password edit field in AccountSettingsDialog.
* Format times in text log files according to KLocale.
2010-02-16 (Adam)
* Fix a bug where the window size was not saved/reloaded properly on chat window close. See the comments
in chatwindow.cpp, line 1395 however.
2010-01-13 (Adam)
* Backport: properly update UI when choosing to connect with a different account whilst connection is in progress.
2010-01-29 (Ruben)
* Trunk backport: Added workaround where "last seen" and/or "last message" are in the year 2106.
2010-01-28 (Pano)
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
* Merged an updated Dutch translation by Sjors Gielen.
2010-01-24 (Adam)
* New feature: if proxy connection fails, remove proxy details and try again.
2010-01-24 (Pano)
* Added a Russian translation by Dmitriy Simbiriatin.
2010-01-21 (Ruben)
* Improved layout flexibility of the contact properties dialog. (Trunk backport)
2010-01-20 (Pano)
* Merged an updated Brazilian Portuguese translation by Morris Arozi Moraes.
2010-01-19 (Adam)
* Bump copyright years.
* Bug fix: correctly parse MSN color information in chat messages.
* Bump version to 2.0.3dev.
2010-01-17 (Adam)
* Bug fix: friendly names weren't shown in Ink error messages.
* Bug fix: Ink validation failed if there were trailing \r\n characters; trim them out first.
* Bug fix: fixed long standing crash that occurred with InvitedContacts and restarted chats.
Reported by Ralesk.
2010-01-16 (Pano)
* Merged an updated Greek translation by Dimitrios Glentadakis.
2010-01-15 (Ruben)
* Merged improved patch by Mamadou Gueye, to show email count in systray tooltip.
2010-01-09 (Pano)
* Updated message catalogs (POT and PO files)
2010-01-08 (sifcenter)
* Use the SOAP reply into QDocDocument to indent and print it.
* Added a small tooltip for the image in contact properties dialog.
2010-01-08 (Valerio)
* Improved the sizes of the friendly name and personal message labels on the
Contact List.
* Added a workaround to a KDE bug, requiring the spell checker to be set twice
when switching between tabs.
2010-01-06 (Pano)
* Merged an updated French translation by Grégory Bellier.
2010-01-02 (Valerio)
* Merged patch by Mentos, fixing emoticon encoding issues in chat logs.
* Merged patch by Mentos, fixing a bug when setting a custom display picture
to a contact.
* Merged patch by Mentos, which enables dragging and dropping of images
into display picture frames.
* Fixed issue with empty personal messages on login showing an empty message
instead of the default message.
2009-12-31 (Valerio)
* Replaced the contact list friendlyname and PM labels with new labels
editable inline by clicking.
2009-12-29 (Valerio)
* Removed code to change the size of the displayed picture in chat.
* Merged patch by Mentos, fixing emoticon encoding issues.
* Merged patch by ipereira, adding translator details in the pot files.
2009-12-23 (Adam)
* After discussion with Sjors reverted QtWebKit commit. Will be moved into a branch
where it can be stabilised before being moved back into trunk or 2.0.x.
2009-12-23 (Sjors)
* Replaced QCA with GCrypt. This makes Mac and Windows builds much, much
easier and removes the support hell QCA used to be, because it required
OpenSSL plugins and that stuff.
2009-12-19 (Sjors)
* Removed KHTML in favor of QtWebKit. This will help us make Qt-only builds for Windows and Mac.
* Also removed KUrl in favor of QUrl, since they are almost the same anyway.
2009-12-15 (Valerio)
* Fixed a meaningless error dialog when logging in with accounts which have
added the Messenger official email address to the contact list.
2009-12-08 (Valerio)
* Fixed a crash which occurred when trying to login with the wrong password.
2009-12-05 (Adam)
* Fix a crash bug that can occur when we receive a CHG earlier than we should.
--- 2.0.2 released ---
2009-12-04 (Pano)
* Merged an updated Japanese translation by Daniel E. Moctezuma.
2009-12-03 (Sjors)
* Fixed a bug introduced just before 2.0.1 release, making it impossible to
log in twice in the same KMess run.
2009-12-02 (Pano)
* Merged an updated Brazilian Portuguese translation by Maurício Arozi Moraes.
* Merged an updated Traditional Chinese translation by Yen-chou Chen.
--- 2.0.1 released ---
2009-11-30 (Sjors)
@@ -69,7 +510,7 @@
2009-11-02 (Adam)
* Ensure the height of items in the contact list is sufficient to fully
display the contact name and PSM (strings got cut off when people used large
display the contact name and PSM (strings got cut off when people used large
KDE font sizes).
* Increase the notification unlock timeout to 10 seconds after the last ILN.
* Allow the download/upload buttons in the transfer window to expand to show their
@@ -106,14 +547,14 @@
* Store display name on roaming service but do not use it for display (in line with WLM).
* Remove duplicate "Show Statusbar" from the list of shortcuts.
* Fix updating of display picture with the roaming service.
* Change keystrokes for scrolling in chat message view - pgdn/pgup = scroll, alt+pgdn/pgup = fast scroll.
* Change keystrokes for scrolling in chat message view - pgdn/pgup = scroll, alt+pgdn/pgup = fast scroll.
Fixes a clash with the text editor which caused the view to scroll when shift+pg selecting text in the editor.
2009-10-22 (Adam)
* Fix build error introduced in r5567. My bad.
* Fix a crash bug that was introduced with a previous fix. Previous fix has been reverted pending better solution.
* Improve fix for KDE bug #209960.
* Stop writing bad "last seen date" and "last message date" values when saving contact list.
* Stop writing bad "last seen date" and "last message date" values when saving contact list.
2009-10-21 (Adam)
* Cache last display names of contacts; works around an issue where the AddressBook service
+1 -1
View File
@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = KMess
PROJECT_NUMBER = 2.0.1
PROJECT_NUMBER = 2.0.6
OUTPUT_DIRECTORY = ./apidocs
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
+9 -1
View File
@@ -1,5 +1,13 @@
KMess Feature list
========================
- 2.0.3 -
Setting your friendly name and personal message by clicking on their labels in the contact list.
A display of the unread email count in the system tray tooltip.
Ability to change personal message using DBus.
- 2.0.2 -
Enabled drag-and-drop of images into display picture frames.
- 2.0.1 -
Synchronization of friendly names, personal messages and display pictures with Messenger.
Support to send screenshots by dragging and dropping them to a chat.
@@ -103,4 +111,4 @@ Chats can be configured to show timestamps when contacts send messages.
A "compact" chat format can be used to remove extraneous line breaks and reduce the size of the chat.
The chat window caption in the taskbar alternates between lower and upper case to inform the user of a received message when the window is not on top.
Internationalization support, with translations in: English, Dutch, German, Italian, Portuguese, Spanish, Turkish, Chinese, French, Catalan, Arabic, Korean, Norsk, Thai, Danish, and Estonian
There is now a method, though not absolute, to tell if a contact is blocking you. If a chat is started with a contact that appears offline, you will be informed if the contact is offline or online and blocking you.
There is now a method, though not absolute, to tell if a contact is blocking you. If a chat is started with a contact that appears offline, you will be informed if the contact is offline or online and blocking you.
+110 -3
View File
@@ -1,8 +1,115 @@
Changes between KMess Git and 2.0.6:
--------------------------------------
- None yet.
Changes between KMess 2.0.6 and 2.0.5:
--------------------------------------
- fix bug where KMess couldn't login due to badly formed URL commands.
- fixed crash when taking any action in the Contact Added User dialog.
- fixed a possible crash when using the Contact Added User dialog.
- Added a fading effect when switching between the initial view
and the contact list.
- fixed retrieval of display pictures from online MSN storage.
- fixed a problem where roaming service profile data was invalid.
- fixed "Visit Link" context-menu icon in chat. Thanks to IRC's agostino.
- improved Contact Added User dialog with tabs. Thanks ti Timo Tambet.
- updated Japanese translation by Daniel E. Moctezuma.
- updated Spanish translation by Daniel E. Moctezuma.
- updated German translation.
Changes between KMess 2.0.5 and 2.0.4:
--------------------------------------
- added Chat History integration with the Chat Window, with a menu item, toolbar
action, and a context menu item.
- added KDE notifications for contact and group changes (Patch by Timo Tambet).
- fixed a crash due to changes by Microsoft in how Offline Messages are sent.
- fixed a possible crash during login.
- fixed a crash when closing a chat window.
- fixed logging in with long passwords (17+ characters). MSN cuts them to 16, hehehe.
- removed all HTML from KDE notifications to fix weird text cutting problems.
- updated French translation by Anthony Rey.
- updated Estonian translation by Timo Tambet.
- updated Hungarian translation by József Makay.
- updated Traditional Chinese translation by Yen-chou Chen.
Changes between KMess 2.0.4 and 2.0.3:
--------------------------------------
- added a tip text on the contact list's search bar (Patch by Timo Tambet).
- added support for a new ISF-Qt feature, PNG fortification, allowing to drag
and drop handwriting drawings into the message editor to be edited.
- added support for notifications on the Mac.
- added a toggle button for Now Listening to the contact list (Patch by Francesco Nwokeka).
- added Galician translation by Indalecio Freiría Santos.
- fixed invalid characters in contact frame tooltips.
- fixed "Contact Added User" dialog pop-ups, appearing for already added contacts.
- fixed the application icon resolution.
- fixed log in failure, due to a mismanaged remote display picture reception.
- fixed URL when retrieving display pictures from MSN.
- fixed saving account properties.
- fixed removal and blocking of contacts.
- fixed saving the automatic login option.
- fixed status changing bugs when disconnecting or waking up from sleep.
- improved compatibility with KDE 4.5.
- improved the Chat History dialog, now using a calendar to list dates with available chat logs.
- improved contact list sorting, now done by status, then alphabetically (Patch by dah_ at the boards).
- improved management of unknown contacts.
- improved widget sizes and behavior on the contact list.
- updated the system tray widget to the new KDE 4.3+ one.
- updated Japanese translation by Daniel E. Moctezuma.
- updated Dutch translation by Heimen Stoffels.
- updated German translation by Panagiotis Papadopoulos.
- updated Catalan translation by Adrià Arrufat.
- updated Traditional Chinese translation by the Tryneeds-Chinese Translation Platform.
- updated French translation by Grégory Bellier.
- updated Brazilian Portuguese translation by Morris Arozi Moraes.
- updated Traditional Chinese translation by Yen-chou Chen.
Changes between KMess 2.0.3 and 2.0.2:
--------------------------------------
- added ability to drag-and-drop images into display picture frames.
- added setting friendly name and personal message by clicking on their labels in the contact list.
- added Russian translation by Dmitriy Simbiriatin.
- added Portuguese translation by Bruno Almeida.
- added showing unread email count in the system tray tooltip.
- added setting personal message using DBus.
- fixed crash when logging in with the wrong password.
- fixed bug causing the "Contact Added User" dialog to appear after deleting contacts.
- fixed bug causing the chat window size to not be saved under KDE 4.4.
- improved performance when drawing complex ink messages.
- improved proxy support.
- updated French translation by Grégory Bellier.
- updated Catalan translation by Adrià Arrufat.
- updated German translation by Panagiotis Papadopoulos.
- updated Greek translation by Dimitrios Glentadakis.
- updated Brazilian Portuguese translation by Morris Arozi Moraes.
- updated Traditional Chinese translation by Yen-chou Chen.
- updated Dutch translation by Sjors Gielen.
- updated Dutch translation by Heimen Stoffels.
- updated Hungarian translation by Pauli Henrik.
- updated Spanish translation by Mauricio Muñoz Lucero.
- updated Turkish translation by Uğur Çetin.
- updated Estonian translation by Rivo Laks.
- updated Traditional Chinese translation by Yen-chou Chen.
- updated Japanese translation by Daniel E. Moctezuma.
- updated Slovak translation by Rastislav Krupanský.
Changes between KMess 2.0.2 and 2.0.1:
--------------------------------------
- fixed a bug that was introduced just before the release of KMess 2.0.1,
making it impossible to login twice in the same KMess session.
- updated Japanese translation by Daniel E. Moctezuma.
- updated Brazilian Portuguese translation by Maurício Arozi Moraes.
Changes between KMess 2.0.1 and 2.0:
--------------------------------------
- added a "Log in automatically" checkbox to the initial view (patch by Camille Begue).
- added ability to open the chat history dialog when not connected
(patch by Camille Begue).
- added ability to open the chat history dialog when not connected (patch by Camille Begue).
- added Test Server support.
- added shortcut checking of added/edited emoticons for invalid characters.
- added usage of smooth pixmap scaling for display pictures in the contact list.
@@ -40,7 +147,7 @@ Changes between KMess 2.0.1 and 2.0:
- updated Brazilian Portuguese translation by Maurício Arozi Moraes.
- updated Catalan translation by Adrià Arrufat.
- updated Dutch translation by Sjors Gielen.
- updated Estonian translation by Lauri Võsandi, Mihkel Tõnnov and Rivo Laks.
- updated Estonian translation by Lauri Võsandi, Mihkel Tõnnov and Rivo Laks.
- updated Finnish translation by Marko Mäkilä.
- updated French translation by Émeric Dupont.
- updated German translation by Panagiotis Papadopoulos.
+11
View File
@@ -63,6 +63,17 @@ To build a TGZ package for Slackware, run:
Licensing
=========
We provide along with KMess some Oxygen icons which are usually bundled with Kopete.
They are released under LGPL 3.0 (see http://www.oxygen-icons.org/).
See COPYING_ICONS for full license text.
The remainder of KMess is released under the GPL2+ . See COPYING for full license text.
More Information
================
+22
View File
@@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+82
View File
@@ -0,0 +1,82 @@
# - Try to find GCrypt
# Once done this will define
#
# GCRYPT_FOUND - system has GCrypt
# GCRYPT_INCLUDE_DIRS - the GCrypt include directory
# GCRYPT_LIBRARIES - Link these to use GCrypt
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
#
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# Imported into KMess, monday october 19, 2009 by Sjors
# reference URL:
# http://dev.libssh.org/export/27d25752e93c19d3e6584915bd64b72e43f3afc0/ \
# cmake/Modules/FindGCrypt.cmake
#
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
# in cache already
set(GCRYPT_FOUND TRUE)
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
find_path(GCRYPT_INCLUDE_DIR
NAMES
gcrypt.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
mark_as_advanced(GCRYPT_INCLUDE_DIR)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(GCRYPT_LIBRARY)
if (GCRYPT_LIBRARY)
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
endif (GCRYPT_LIBRARY)
set(GCRYPT_INCLUDE_DIRS
${GCRYPT_INCLUDE_DIR}
)
if (GCRYPT_FOUND)
set(GCRYPT_LIBRARIES
${GCRYPT_LIBRARIES}
${GCRYPT_LIBRARY}
)
endif (GCRYPT_FOUND)
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
set(GCRYPT_FOUND TRUE)
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
if (GCRYPT_FOUND)
if (NOT GCrypt_FIND_QUIETLY)
message(STATUS "Found GCrypt: ${GCRYPT_LIBRARIES}")
endif (NOT GCrypt_FIND_QUIETLY)
else (GCRYPT_FOUND)
if (GCrypt_FIND_REQUIRED)
message(FATAL_ERROR "Could not find GCrypt")
endif (GCrypt_FIND_REQUIRED)
endif (GCRYPT_FOUND)
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
+3
View File
@@ -22,3 +22,6 @@
/* Define whether Ink support is enabled */
#define KMESS_ENABLE_INK ${HAVE_LIBISFQT}
/* Define whether we have the new system tray */
#cmakedefine HAVE_NEW_TRAY
@@ -7,22 +7,23 @@ appver="`egrep 'SET.*KMESS_VERSION' CMakeLists.txt | sed -e 's/.*"\([^"]*\)".*/\
date="`date +%Y%m%d`"
# Make sure we have the right repository
if [ ! -f kmess.kdevelop ]; then
/bin/echo -n "svn (unknown)"
if [ ! -f kmess.kdev4 ]; then
/bin/echo -n "git (unknown)"
exit
fi
# Display normal version if subversion is not installed
if [ ! -x `which svnversion 2>/dev/null` ]; then
# Display normal version if git is not installed
if [ ! -x `which git 2>/dev/null` ]; then
/bin/echo -n "$appver"
exit
fi
# Display subversion version if this is a working copy
svnver=`LANG=C svnversion`
gitname=`LANG=C git describe --all HEAD 2>/dev/null | sed -e 's:^heads/::g'`
gitver=`LANG=C git rev-parse --short HEAD 2>/dev/null`
# see if this is not a repository.
if [ "$svnver" = "exported" ]; then
if [ -z "$gitver" ]; then
if [ -z "$KMESS_VER" ]; then
/bin/echo -n "$appver";
else
@@ -32,4 +33,4 @@ if [ "$svnver" = "exported" ]; then
fi
# display subversion version and date
/bin/echo -n "$appver-svn (`svnversion` >= $date)"
/bin/echo -n "$appver-git ($gitname@$gitver >= $date)"
Vendored
+1 -1
View File
@@ -54,7 +54,7 @@ DEBUG=0
# Globals
cd `dirname $0`
SRC_DIR="$PWD"
KMESS_VER="`./cmake/get-svn-version.sh`"
KMESS_VER="`./cmake/get-git-version.sh`"
+47 -17
View File
@@ -4,27 +4,42 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6 )
#### Main switches ####
# Define the default build type
# Possible values:
# - none
# - release
# - debug
# - debugfull (even fewer optimisations)
# - relwithdebinfo (release with debug info)
# - minsizerel (minimum size release)
# Uncomment the next line to force building in full debug mode
SET( CMAKE_BUILD_TYPE debugfull )
# Bundled mode: you can add Isf-Qt as a subdirectory
# of your CMake-based prjoect easily. Just use:
# SET( USE_BUNDLED_LIBRARIES ISFQT )
# and Isf-Qt will be built and statically linked in your
# application, without installing anything
IF( ISFQT_IS_BUNDLED OR USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
SET( ISFQT_IS_BUNDLED TRUE )
MESSAGE( "-- Will build Isf-Qt in bundled mode." )
ELSE()
SET( ISFQT_IS_BUNDLED FALSE )
ENDIF()
# Only set the build type if we're not being bundled: if we are, we'll
# use the build type specified by the parent project
IF( NOT ISFQT_IS_BUNDLED )
# Define the default build type
# Possible values:
# - none
# - release
# - debug
# - debugfull (even fewer optimisations)
# - relwithdebinfo (release with debug info)
# - minsizerel (minimum size release)
# Uncomment the next line to force building in full debug mode
SET( CMAKE_BUILD_TYPE debugfull )
ENDIF()
# Define the library version number
SET( ISFQT_VERSION "0.9" )
SET( ISFQT_VERSION "1.0dev" )
#### Inclusions ####
FIND_PACKAGE( Qt4 REQUIRED )
ENABLE_TESTING()
OPTION( WANT_GIF "Enable support for reading and writing Fortified-GIF images" ON )
IF( WANT_GIF )
MESSAGE( "-- Looking for GifLib" )
@@ -68,13 +83,27 @@ IF( CMAKE_COMPILER_IS_GNUCXX )
"-O0 -g3 -fno-inline -Wall -Woverloaded-virtual -Wsign-compare -Wundef -fvisibility=default" )
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
IF( NOT ISFQT_DEBUG_OUTPUT STREQUAL "1" AND NOT ISFQT_DEBUG_OUTPUT STREQUAL "0" )
IF( CMAKE_BUILD_TYPE MATCHES debug )
SET( ISFQT_DEBUG_OUTPUT 1 )
ELSE()
SET( ISFQT_DEBUG_OUTPUT 0 )
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} src include )
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/isfqtconfig.h.in
${CMAKE_CURRENT_BINARY_DIR}/isfqtconfig.h )
ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( tests )
IF( NOT ISFQT_IS_BUNDLED )
ENABLE_TESTING()
ADD_SUBDIRECTORY( tests )
ENDIF()
#### Project CMake configuration files creation ####
@@ -87,16 +116,17 @@ SET( LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib"
SET( SHARED_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share"
CACHE STRING "Directory where the shared data will be installed" )
# Prepare the IsfQtConfig.cmake file, which allows other projects to find us
# Prepare thej IsfQtConfig.cmake file, which allows other projects to find us
CONFIGURE_FILE( cmake/IsfQtConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/IsfQtConfig.cmake" @ONLY )
#### Installation ####
# Do not install the resources if we're bundling it in KMess
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
# Do not install the resources if we're bundling it into an application
IF( NOT ISFQT_IS_BUNDLED )
INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/IsfQtConfig.cmake
DESTINATION ${LIB_INSTALL_DIR}/isfqt )
INSTALL( FILES cmake/FindIsfQt.cmake
DESTINATION ${CMAKE_ROOT}/Modules )
ENDIF()
+37
View File
@@ -1,3 +1,40 @@
2010-07-23 (Valerio)
* Fixed the copy constructor in Stroke, it was not copying all the necessary properties.
* Fixed some compiler warnings.
* Improved bundled compilation mode.
2010-07-22 (Valerio)
* Improved the InkEdit text - added a checkbox to show the usage of Canvas::isEmpty() and a label
to show usage of the Canvas::inkChanged() signal.
* Fixed inkChanged() signal emission in Canvas: it was emitted too early, when the drawing was not
updated yet: slots connected to inkChanged() could then call isEmpty() and get a true return value,
even if the drawing wasn't empty.
2010-06-27 (Adam)
* Use Q_ASSERT_X instead of qWarning where appropriate.
2010-06-19 (Valerio)
* Changed the default behavior of InkCanvas::pixmap(), now paints on a transparent
background, instead of a white one.
2010-06-19 (Valerio)
* Added support for PNG fortification. Like GIF fortification, this feature allows to
write a PNG containing the full ISF drawing inside itself. Of course, it's now also
possible to read a PNG containing ISF data and retrieve the actual drawing.
2010-03-20 (Adam)
* Slight optimisation to painting - we no longer draw the background color, Qt does it for us.
Also, only render the parts of the buffer that have changed.
2010-03-13 (Adam)
* Add a bezier curve smoothing algorithm. Strokes with the FitToCurve flag set are
rendered with an approximate bezier curve. Gives much smoother looking strokes.
2010-02-21 (Adam)
* Optimise the painting of strokes. Cache logic added to IsfQtDrawing and only
strokes that have been added are painted. Also, no longer do a full bounding rect
recalculation when a stroke is added.
2009-10-03 (Adam)
* Remove unused HIMETRIC conversion methods.
+20 -3
View File
@@ -5,9 +5,16 @@ About LibISF-Qt:
LibISF-Qt is a Qt4 library made to encode and decode Microsoft's
Ink Serialized Format (ISF) files.
Q. What the hell is this?
A. It's a library, written in C++/Qt4, to read and write ISF
image files.
Q. What is ISF?
A. Ink Serialized Format is an open specification initially
made by Microsoft, and then freed up with their "Open
Specification Promise" initiative. ISF is a file format
made to store handwriting very efficiently: an ISF file
with a somewhat complex handwritten drawing takes less than
1000 bytes. ISF supports metrics to adapt drawings to
different form factors, bezier smoothing of drawn strokes,
coloring, stroke size varying by pen pressure, linking
in static data, and more.
Q. How does this library differ from aMSN's or Emesene's?
A. It's written with Qt, which makes it easily portable on
@@ -42,6 +49,16 @@ If everything went right again, install it:
$ make install
Aaand now you're set. :)
LibISF-Qt natively supports being bundled into other applications.
Bundling means that the library does not get installed system-wide
along with your application, but instead it gets statically linked
into the application.
The idea is that you copy the Isf-Qt source tree (with an SVN export
or a Git submodule) into your project's tree, and then set up your
CMake listfile to add this library as a subdirectory:
> SET( ISFQT_IS_BUNDLED TRUE )
> ADD_SUBDIRECTORY( contrib/isf-qt )
And again, you're done!
Documentation:
+2 -1
View File
@@ -14,7 +14,7 @@ OUTSTANDING
- Read and write user-defined custom tags
- Interpret, use and write pressure information
- Associating text recognized by OCR to the drawn strokes
- Modify strokes
- Alter stroke points
DONE
----
@@ -38,4 +38,5 @@ DONE
- Add new strokes to an IsfDrawing
- Stroke attributes: width, colour, pressure
- Export IsfDrawing to raw-isf, isf-base64 and fortified-gif
- Export IsfDrawing to PNG
- Delete strokes
+3 -1
View File
@@ -8,7 +8,9 @@
#define ISFQT_VERSION "${ISFQT_VERSION}"
// Define if debug output should be enabled
#define ISFQT_DEBUG ${ISFQT_DEBUG_OUTPUT}
#if ${ISFQT_DEBUG_OUTPUT}
#define ISFQT_DEBUG
#endif
// Define if fortified-GIF support is enabled
#define ISFQT_GIF_ENABLED ${GIF_ENABLED}
+1
View File
@@ -0,0 +1 @@
#include "isfqtstroke.h"
+22 -24
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -42,7 +40,7 @@ namespace Isf
* @class InkCanvas
* @brief This is a control designed for the drawing and display of Ink.
*
* InkCanvas is used for drawing and displaying Ink. The currently displayed Ink drawing can be retrieved
* InkCanvas is used for drawing and displaying Ink. The currently displayed Ink drawing can be retrieved
* or set using the drawing() and setDrawing() methods.
*
* To set the properties of the current pen, use the setPenColor(), setPenSize() and setPenType() methods.
@@ -51,7 +49,7 @@ namespace Isf
* Example:
*
* \code
* InkCanvas *canvas = new Isf::InkCanvas( this );
* InkCanvas* canvas = new Isf::InkCanvas( this );
* canvas->setPenColor( Qt::blue );
* canvas->setPenSize( 10 );
*
@@ -62,7 +60,7 @@ namespace Isf
* // now an eraser will be used and strokes can be erased individually.
* \endcode
*
* To return the currently displayed Ink as a QImage, use image(). To return the raw ISF data, suitable
* To return the currently displayed Ink as a QImage, use image(). To return the raw ISF data, suitable
* for saving to disk or sending over a network, use bytes().
*
* To write the ISF data directly to a QIODevice, such as a file, use the save() method.
@@ -94,37 +92,37 @@ namespace Isf
};
public: // public constructors
InkCanvas( QWidget *parent = 0 );
~InkCanvas();
InkCanvas( QWidget* = 0 );
~InkCanvas();
public: // public methods
QByteArray bytes();
Isf::Drawing *drawing();
Isf::Drawing* drawing();
QImage image();
bool isEmpty();
QColor penColor();
int penSize();
PenType penType();
void save( QIODevice &device, bool base64 = false );
void setDrawing( Isf::Drawing *drawing );
void save( QIODevice&, bool = false );
void setDrawing( Isf::Drawing* );
virtual QSize sizeHint() const;
public slots:
void clear();
void setCanvasColor( QColor newColor );
void setPenColor( QColor newColor );
void setPenSize( int pixels );
void setPenType( PenType type );
void setCanvasColor( QColor );
void setPenColor( QColor );
void setPenSize( int );
void setPenType( PenType );
protected: // protected methods
void mousePressEvent( QMouseEvent *event );
void mouseMoveEvent( QMouseEvent *event );
void mouseReleaseEvent( QMouseEvent *event );
void paintEvent( QPaintEvent *event );
void resizeEvent( QResizeEvent *event );
void mousePressEvent( QMouseEvent* );
void mouseMoveEvent( QMouseEvent* );
void mouseReleaseEvent( QMouseEvent* );
void paintEvent( QPaintEvent* );
void resizeEvent( QResizeEvent* );
private: // private methods
void drawLineTo( const QPoint &endPoint );
void drawLineTo( const QPoint& );
void clearBuffer();
void updateCursor();
@@ -140,7 +138,7 @@ namespace Isf
/// It's true if the erase brush was selected
bool erasingImage_;
/// Current drawing being manipulated
Isf::Drawing *drawing_;
Isf::Drawing* drawing_;
/// Initial drawing, can be overridden with drawing_
Isf::Drawing initialDrawing_;
/// Last point where the mouse pointer was released
@@ -152,7 +150,7 @@ namespace Isf
/// Pen type
PenType penType_;
/// The current stroke being drawn
Isf::Stroke *currentStroke_;
Isf::Stroke* currentStroke_;
/// The pixmap buffer where in progress strokes are drawn
QPixmap bufferPixmap_;
/// Cache pixmap so the Ink isn't redrawn on every mouse move
@@ -161,7 +159,7 @@ namespace Isf
bool drawingDirty_;
signals:
/// Emitted when the ink representation is modified (stroke drawn,
/// Emitted when the ink representation is modified (stroke drawn,
/// stroke deleted, current drawing changed).
void inkChanged();
};
+30 -82
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -41,6 +39,7 @@ namespace Isf
{
// Forward declarations
class Drawing;
class StreamData;
@@ -137,8 +136,8 @@ namespace Isf
, IsHighlighter = 0x0100 ///< This stroke is an highlighter stroke
, IsRectangle = 0x0200 ///< Meaning unknown
};
Q_DECLARE_FLAGS( StrokeFlags, StrokeFlag )
Q_DECLARE_OPERATORS_FOR_FLAGS( StrokeFlags )
Q_DECLARE_FLAGS( StrokeFlags, StrokeFlag );
Q_DECLARE_OPERATORS_FOR_FLAGS( StrokeFlags );
@@ -183,6 +182,14 @@ namespace Isf
, resolution( vResolution )
{
}
/// Quick comparison operator
bool operator ==( const Metric& other )
{
return min == other.min
&& max == other.max
&& units == other.units
&& resolution == other.resolution;
}
/// Minimum value
qint64 min;
@@ -232,52 +239,6 @@ namespace Isf
/**
* Drawing attributes for points.
*/
struct AttributeSet
{
/// Constructor
AttributeSet()
: color( Qt::black )
, flags( 0x10 ) // Meaning unknown
, penSize( 8.f, 8.f ) // Default pen is 8.0 pixels wide
{
}
/// The stroke color, optionally with alpha channel
QColor color;
/// Mask of StrokeFlags, @see StrokeFlags
StrokeFlags flags;
/// Dimensions of the pencil in pixels
QSizeF penSize;
};
/**
* Drawing attributes for strokes.
*/
struct StrokeInfo
{
/// Constructor
StrokeInfo()
: hasPressureData( false )
, hasXData( true )
, hasYData( true )
{
}
/// Whether the stroke contains pressure info or not
bool hasPressureData;
/// Whether the stroke contains X coordinates or not
bool hasXData;
/// Whether the stroke contains Y coordinates or not
bool hasYData;
};
/**
* A single point within a stroke.
*/
@@ -290,17 +251,23 @@ namespace Isf
{
}
/// Constructor with point only
Point( const QPoint &point )
Point( const QPoint& point )
: position( point )
, pressureLevel( 0 )
{
}
/// Constructor with point and pressure
Point( const QPoint &point, const qint64 pressure )
Point( const QPoint& point, const qint64 pressure )
: position( point )
, pressureLevel( pressure )
{
}
/// Quick comparison operator
bool operator ==( const Point& other )
{
return position == other.position
&& pressureLevel == other.pressureLevel;
}
/// coordinates
QPoint position;
@@ -311,32 +278,9 @@ namespace Isf
/**
* A pen stroke.
* A list of Point items.
*/
struct Stroke
{
/// Constructor
Stroke()
: attributes( 0 )
, info( 0 )
, metrics( 0 )
, transform( 0 )
{
}
/// Bounding rectangle of this stroke
QRect boundingRect;
/// Link to the attributes of this stroke's points, if any
AttributeSet *attributes;
/// Link to this stroke's attributes, if any
StrokeInfo *info;
/// Link to this stroke's metrics, if any
Metrics *metrics;
/// List of points
QList<Point> points;
/// Link to this stroke's transformation, if any
QMatrix *transform;
};
typedef QList<Point> PointList;
@@ -359,12 +303,16 @@ namespace Isf
public: // Public static methods
static Drawing &reader( const QByteArray &isfData, bool decodeFromBase64 = false );
static Drawing &readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64 = false );
static Drawing &reader( const QByteArray&, bool = false );
static Drawing &readerGif( const QByteArray&, bool = false );
static Drawing &readerPng( const QByteArray&, bool = false );
static bool supportsGif();
static QByteArray writer( const Drawing &drawing, bool encodeToBase64 = false );
static QByteArray writerGif( const Drawing &drawing, bool encodeToBase64 = false );
static QByteArray writer( const Drawing&, bool = false );
static QByteArray writerGif( const Drawing&, bool = false );
static QByteArray writerPng( const Drawing&, bool = false );
private: // Private static properties
static StreamData* streamData_;
};
}
+29 -48
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -27,16 +25,20 @@
#define ISFQTDRAWING_H
#include <IsfQt>
#include <IsfQtStroke>
#include <QMap>
#include <QMatrix>
#include <QPaintDevice>
#include <QUuid>
#include <QPixmap>
// Forward declarations
class QByteArray;
class AttributeSet;
namespace Isf
@@ -64,58 +66,45 @@ namespace Isf
public: // public constructors
Drawing();
Drawing( const Drawing &other );
Drawing( const Drawing& );
~Drawing();
public: // public state retrieval methods
AttributeSet *attributeSet( quint32 index );
const QList<AttributeSet*> attributeSets();
QRect boundingRect();
QRect boundingRect() const;
void clear();
IsfError error() const;
qint32 indexOfStroke( const Stroke* ) const;
bool isEmpty() const;
bool isNull() const;
QPixmap pixmap( const QColor backgroundColor = Qt::white );
QSize size();
Stroke *stroke( quint32 index );
Stroke *strokeAtPoint( const QPoint &point );
QPixmap pixmap( const QColor = Qt::transparent );
void setBoundingRect( QRect );
QSize size() const;
Stroke* stroke( quint32 );
Stroke* strokeAtPoint( const QPoint& );
const QList<Stroke*> strokes();
QMatrix *transform( quint32 index );
const QList<QMatrix*> transforms();
public: // public manipulation methods
qint32 addAttributeSet( AttributeSet *newAttributeSet );
qint32 addStroke( Stroke *newStroke );
qint32 addTransform( QMatrix *newTransform );
bool deleteAttributeSet( quint32 index );
bool deleteStroke( quint32 index );
bool deleteStroke( Stroke *stroke ) ;
bool deleteTransform( quint32 index );
bool setCurrentAttributeSet( AttributeSet *attributeSet );
bool setCurrentTransform( QMatrix *transform );
qint32 addStroke( Stroke* );
qint32 addStroke( PointList = PointList() );
bool deleteStroke( quint32 );
bool deleteStroke( Stroke* );
private:
void updateBoundingRect();
private: // Private properties
/// List of attributes of the points in the drawing
QList<AttributeSet*> attributeSets_;
/// Bounding rectangle of the drawing
QRect boundingRect_;
/// Cached bounding rectangle
QRect cacheRect_;
/// The cached pixmap
QPixmap cachePixmap_;
/// Virtual drawing canvas dimensions
QRect canvas_;
/// Link to the currently used metric data
Metrics *currentMetrics_;
/// Link to the currently used point info data
AttributeSet *currentAttributeSet_;
/// Link to the currently used stroke info data
StrokeInfo *currentStrokeInfo_;
/// Link to the currently used transformation
QMatrix *currentTransform_;
/// Link to the default metric data
Metrics defaultMetrics_;
/// Link to the default point info data
AttributeSet defaultAttributeSet_;
/// Link to the default stroke info data
StrokeInfo defaultStrokeInfo_;
/// Link to the default transformation
QMatrix defaultTransform_;
/// A list of strokes that need to be repainted.
QList<Stroke*> changedStrokes_;
/// Is the drawing dirty? i.e, requires repainting?
bool dirty_;
/// Last parsing error (if there is one)
IsfError error_;
/// List of registered GUIDs
@@ -130,16 +119,8 @@ namespace Isf
quint64 maxGuid_;
/// Maximum thickness of the strokes
QSizeF maxPenSize_;
/// List of metrics used in the drawing
QList<Metrics*> metrics_;
/// Pixel size of the drawing
QSize size_;
/// List of information about the drawing's strokes
QList<StrokeInfo*> strokeInfo_;
/// List of strokes composing this drawing
QList<Stroke*> strokes_;
/// Transformation matrices
QList<QMatrix*> transforms_;
};
+117
View File
@@ -0,0 +1,117 @@
/***************************************************************************
* Copyright (C) 2010 by Valerio Pilo *
* valerio@kmess.org *
* *
* Copyright (C) 2010 by Adam Goossens *
* adam@kmess.org *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef ISFQTSTROKE_H
#define ISFQTSTROKE_H
#include <IsfQt>
#include <QColor>
#include <QList>
#include <QMatrix>
#include <QRect>
#include <QSizeF>
// Forward declarations
class QPainterPath;
namespace Isf
{
// Forward declarations
class AttributeSet;
/**
* A pen stroke.
*/
class Stroke
{
public:
Stroke();
Stroke( const Stroke& );
~Stroke();
void addPoint( Point );
void addPoints( PointList );
QRect boundingRect() const;
QColor color() const;
void finalize();
StrokeFlags flags() const;
bool hasPressureData() const;
Metrics* metrics();
QPainterPath painterPath();
QSizeF penSize() const;
PointList& points();
void setColor( QColor );
void setFlag( StrokeFlag, bool = true );
void setFlags( StrokeFlags );
void setMetrics( Metrics* );
void setPenSize( QSizeF );
void setTransform( QMatrix* );
QMatrix* transform();
private:
void bezierCalculateControlPoints();
void bezierGetFirstControlPoints( double[], double*, int );
private:
/// Bezier data
QList<QPointF> bezierControlPoints1_;
QList<QPointF> bezierControlPoints2_;
QList<QPointF> bezierKnots_;
/// Bounding rectangle of this stroke
QRect boundingRect_;
/// The stroke color, optionally with alpha channel
QColor color_;
/// Whether the stroke data needs to be analyzed or not
bool finalized_;
/// Mask of StrokeFlags, @see StrokeFlags
StrokeFlags flags_;
/// Whether the stroke contains pressure information or not
bool hasPressureData_;
/// Link to this stroke's metrics, if any
Metrics* metrics_;
/// Dimensions of the pencil in pixels
QSizeF penSize_;
/// List of points
PointList points_;
/// Link to this stroke's transformation, if any
QMatrix* transform_;
};
}; // namespace Isf
#endif // ISFQTSTROKE_H
+9 -6
View File
@@ -14,15 +14,18 @@ SET( ISFQT_SOURCES
tagswriter.cpp
isfqt.cpp
isfinkcanvas.cpp
isfqtstroke.cpp
)
SET( ISFQT_PUBLIC_HEADERS
../include/isfqt.h
../include/isfqtdrawing.h
../include/isfinkcanvas.h
../include/IsfQt
../include/isfqtstroke.h
../include/IsfQtDrawing
../include/IsfInkCanvas
../include/IsfQtStroke
../include/IsfQt
)
SET( ISFQT_LIBS
@@ -48,11 +51,11 @@ QT4_ADD_RESOURCES( ISFQT_RCC_SRCS ${ISFQT_RCCS} )
INCLUDE_DIRECTORIES( ${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} )
# Do not install the library if we're bundling it in KMess
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
ADD_LIBRARY( isf-qt SHARED ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
ELSE()
# Do not install the library if we're bundling it into an application
IF( ISFQT_IS_BUNDLED )
ADD_LIBRARY( isf-qt STATIC ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
ELSE()
ADD_LIBRARY( isf-qt SHARED ${ISFQT_SOURCES} ${MOC_SRCS} ${ISFQT_RCC_SRCS} )
ENDIF()
TARGET_LINK_LIBRARIES( isf-qt ${ISFQT_LIBS} )
@@ -64,7 +67,7 @@ SET_TARGET_PROPERTIES( isf-qt PROPERTIES
#### Installation ####
# Do not install the library if we're bundling it in KMess
IF( NOT USE_BUNDLED_LIBRARIES MATCHES "ISFQT" )
IF( NOT ISFQT_IS_BUNDLED )
INSTALL( TARGETS isf-qt LIBRARY
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" )
INSTALL( FILES ${ISFQT_PUBLIC_HEADERS}
@@ -36,7 +36,7 @@ using namespace Isf::Compress;
* @param data Data to analyze
* @return Block size
*/
quint8 BitPackingAlgorithm::blockSize( const QList<qint64> &data )
quint8 BitPackingAlgorithm::blockSize( const QList<qint64>& data )
{
quint8 blockSize = 0;
qint64 num;
@@ -78,7 +78,7 @@ quint8 BitPackingAlgorithm::blockSize( const QList<qint64> &data )
* @param source List of values to compress
* @return bool
*/
bool BitPackingAlgorithm::deflate( QByteArray &encodedData, quint8 blockSize, const QList<qint64> &source )
bool BitPackingAlgorithm::deflate( QByteArray& encodedData, quint8 blockSize, const QList<qint64>& source )
{
if( blockSize > 64 )
{
@@ -158,7 +158,7 @@ bool BitPackingAlgorithm::deflate( QByteArray &encodedData, quint8 blockSize, co
* @param decodedData List where to place decompressed values
* @return bool
*/
bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 blockSize, QList<qint64> &decodedData )
bool BitPackingAlgorithm::inflate( DataSource* source, quint64 length, quint8 blockSize, QList<qint64>& decodedData )
{
if( blockSize > 64 )
{
@@ -166,7 +166,7 @@ bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 bl
blockSize = 64; // Fuck it :P
}
if( source.atEnd() )
if( source->atEnd() )
{
qWarning() << "Cannot inflate: no more bits available!";
return true;
@@ -178,7 +178,7 @@ bool BitPackingAlgorithm::inflate( DataSource &source, quint64 length, quint8 bl
while( index++ < length )
{
value = source.getBits( blockSize );
value = source->getBits( blockSize );
// If the mask matches, the sign bit is set, so ORing value and mask will
// set all leftmost bits to 1, making it a real 64bit signed integer
@@ -32,9 +32,9 @@ namespace Isf
namespace BitPackingAlgorithm
{
quint8 blockSize( const QList<qint64> &data );
bool deflate( QByteArray &encodedData, quint8 blockSize, const QList<qint64> &source );
bool inflate( DataSource &source, quint64 length, quint8 blockSize, QList<qint64> &decodedData );
quint8 blockSize( const QList<qint64>& data );
bool deflate( QByteArray& encodedData, quint8 blockSize, const QList<qint64>& source );
bool inflate( DataSource* source, quint64 length, quint8 blockSize, QList<qint64>& decodedData );
}
}
@@ -33,7 +33,7 @@ using namespace Isf::Compress;
* @param data Data to analyze
* @return Index value
*/
quint8 BitPackingByteAlgorithm::index( const QList<qint64> &data )
quint8 BitPackingByteAlgorithm::index( const QList<qint64>& data )
{
Q_UNUSED( data );
@@ -78,7 +78,7 @@ quint8 BitPackingByteAlgorithm::index( const QList<qint64> &data )
* @param source List of values to compress
* @return bool
*/
bool BitPackingByteAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source )
bool BitPackingByteAlgorithm::deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source )
{
Q_UNUSED( encodedData );
Q_UNUSED( index );
@@ -163,7 +163,7 @@ bool BitPackingByteAlgorithm::deflate( QByteArray &encodedData, quint8 index, co
* @param decodedData List where to place decompressed values
* @return bool
*/
bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData )
bool BitPackingByteAlgorithm::inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData )
{
if( index > 24 )
{
@@ -171,7 +171,7 @@ bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint
index = 24; // Fuck it :P
}
if( source.atEnd() )
if( source->atEnd() )
{
qWarning() << "Cannot inflate: no more bits available!";
return true;
@@ -185,7 +185,7 @@ bool BitPackingByteAlgorithm::inflate( DataSource &source, quint64 length, quint
quint64 pos = 0;
while( pos++ < count )
{
quint8 byte = source.getBits( cBits, &ok );
quint8 byte = source->getBits( cBits, &ok );
if( ! ok )
{
@@ -32,9 +32,9 @@ namespace Isf
namespace BitPackingByteAlgorithm
{
quint8 index( const QList<qint64> &data );
bool deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source );
bool inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData );
quint8 index( const QList<qint64>& data );
bool deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source );
bool inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData );
}
}
@@ -31,7 +31,7 @@ using namespace Isf::Compress;
* @param data Data to transform - the list will be modified.
* @return bool
*/
bool Delta::transform( QList<qint64> &data )
bool Delta::transform( QList<qint64>& data )
{
qint64 currentDelta = 0;
qint64 previousDelta = 0;
@@ -57,7 +57,7 @@ bool Delta::transform( QList<qint64> &data )
* @param data Data to transform - the list will be modified.
* @return bool
*/
bool Delta::inverseTransform( QList<qint64> &data )
bool Delta::inverseTransform( QList<qint64>& data )
{
qint64 currentDelta = 0;
qint64 previousDelta = 0;
@@ -31,8 +31,8 @@ namespace Isf
namespace Delta
{
bool transform( QList<qint64> &data );
bool inverseTransform( QList<qint64> &data );
bool transform( QList<qint64>& data );
bool inverseTransform( QList<qint64>& data );
}
}
@@ -67,7 +67,7 @@ const int huffmanBases_[HUFFMAN_BASES_NUM][HUFFMAN_BASE_SIZE] =
* @param data Data to analyze
* @return index value
*/
quint8 HuffmanAlgorithm::index( const QList<qint64> &data )
quint8 HuffmanAlgorithm::index( const QList<qint64>& data )
{
quint8 index = 0;
@@ -88,14 +88,14 @@ quint8 HuffmanAlgorithm::index( const QList<qint64> &data )
* @param source List of values to compress
* @return bool
*/
bool HuffmanAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source )
bool HuffmanAlgorithm::deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source )
{
DataSource output( encodedData );
output.skipToNextByte();
foreach( quint64 value, source )
{
if( ! deflateValue( output, index, value ) )
if( ! deflateValue( &output, index, value ) )
{
#ifdef ISFQT_DEBUG
qDebug() << "Deflating failure for value:" << value;
@@ -121,7 +121,7 @@ bool HuffmanAlgorithm::deflate( QByteArray &encodedData, quint8 index, const QLi
* @param value Value to compress
* @return bool
*/
bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 value )
bool HuffmanAlgorithm::deflateValue( DataSource* output, quint8 index, qint64 value )
{
qint64 temp = value;
quint8 requiredBits = 0;
@@ -182,8 +182,8 @@ bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 va
}
// Add the bits to the data source
output.append( bits );
output.append( valueBits );
output->append( bits );
output->append( valueBits );
return true;
}
@@ -199,7 +199,7 @@ bool HuffmanAlgorithm::deflateValue( DataSource &output, quint8 index, qint64 va
* @param decodedData List where to place decompressed values
* @return bool
*/
bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData )
bool HuffmanAlgorithm::inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData )
{
QVector<int> huffmanBases;
QVector<int> bitAmounts( HUFFMAN_BASE_SIZE );
@@ -238,7 +238,7 @@ bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index
while( (uint)decodedData.length() < length )
{
bit = source.getBit();
bit = source->getBit();
if( bit )
{
@@ -252,7 +252,7 @@ bool HuffmanAlgorithm::inflate( DataSource &source, quint64 length, quint8 index
}
else if( count < (uint)bitAmounts.size() )
{
quint64 offset = source.getBits( bitAmounts[ count ] );
quint64 offset = source->getBits( bitAmounts[ count ] );
bool sign = offset & 0x1;
offset /= 2;
value = huffmanBases[ count ] + offset;
+4 -4
View File
@@ -32,13 +32,13 @@ namespace Isf
namespace HuffmanAlgorithm
{
bool deflate( QByteArray &encodedData, quint8 index, const QList<qint64> &source );
bool inflate( DataSource &source, quint64 length, quint8 index, QList<qint64> &decodedData );
quint8 index( const QList<qint64> &data );
bool deflate( QByteArray& encodedData, quint8 index, const QList<qint64>& source );
bool inflate( DataSource* source, quint64 length, quint8 index, QList<qint64>& decodedData );
quint8 index( const QList<qint64>& data );
// Internal use methods
bool deflateValue( DataSource &output, quint8 index, qint64 value );
bool deflateValue( DataSource* output, quint8 index, qint64 value );
}
}
+17 -17
View File
@@ -42,9 +42,9 @@ using namespace Isf;
* @param decodedData List where to store the decoded values
* @return bool
*/
bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint64> &decodedData )
bool Compress::inflatePacketData( DataSource* source, quint64 length, QList<qint64>& decodedData )
{
if( source.atEnd() )
if( source->atEnd() )
{
#ifdef ISFQT_DEBUG
qWarning() << "Source was at end!";
@@ -52,8 +52,8 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
return false;
}
bool result;
uchar byte = source.getByte();
bool result = false;
uchar byte = source->getByte();
qint16 algorithm = ( byte & AlgorithmMask );
quint8 algorithmData = 0;
@@ -68,7 +68,7 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
* We need an ISF stream with such a characteristic to be sure.
*/
qWarning() << "Unknown decompression method!";
qDebug() << "[Information - type: best, byte:" << QString::number( source.getByte(), 16 ) << "hex]";
qDebug() << "[Information - type: best, byte:" << QString::number( source->getByte(), 16 ) << "hex]";
return false;
}
// Use the "default compression" algorithm, which is Huffman
@@ -137,15 +137,15 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
qDebug() << "[Information - type: unknown, byte:" << QString::number( byte, 16 ) << "hex]";
// Go back to the previous read position
source.seekRelative( -1 );
source->seekRelative( -1 );
break;
}
// Discard any partially read bytes
if( ! source.atEnd() )
if( ! source->atEnd() )
{
source.skipToNextByte();
source->skipToNextByte();
}
return result;
@@ -163,7 +163,7 @@ bool Compress::inflatePacketData( DataSource &source, quint64 length, QList<qint
* @param source List of values to compress
* @return bool
*/
bool Compress::deflatePacketData( QByteArray &encodedData, const QList<qint64> &source )
bool Compress::deflatePacketData( QByteArray& encodedData, const QList<qint64>& source )
{
bool result;
@@ -244,9 +244,9 @@ bool Compress::deflatePacketData( QByteArray &encodedData, const QList<qint64> &
* @param decodedData List where to store the decoded values
* @return bool
*/
bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qint64> &decodedData )
bool Compress::inflatePropertyData( DataSource* source, quint64 length, QList<qint64>& decodedData )
{
if( source.atEnd() )
if( source->atEnd() )
{
#ifdef ISFQT_DEBUG
qWarning() << "Source was at end!";
@@ -255,7 +255,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
}
bool result;
quint8 byte = source.getByte();
quint8 byte = source->getByte();
qint16 algorithm = ( byte & AlgorithmMask );
quint8 algorithmData = 0;
@@ -270,7 +270,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
* We need an ISF stream with such a characteristic to be sure.
*/
qWarning() << "Unknown decompression method!";
qDebug() << "[Information - type: default, byte:" << QString::number( source.getByte(), 16 ) << "hex]";
qDebug() << "[Information - type: default, byte:" << QString::number( source->getByte(), 16 ) << "hex]";
return false;
}
// Use the "best compression" algorithm, which is Huffman
@@ -379,15 +379,15 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
qDebug() << "[Information - type: unknown, byte:" << QString::number( byte, 16 ) << "hex]";
// Go back to the previous read position
source.seekRelative( -1 );
source->seekRelative( -1 );
break;
}
// Discard any partially read bytes
if( ! source.atEnd() )
if( ! source->atEnd() )
{
source.skipToNextByte();
source->skipToNextByte();
}
return result;
@@ -406,7 +406,7 @@ bool Compress::inflatePropertyData( DataSource &source, quint64 length, QList<qi
* @param source List of values to compress
* @return bool
*/
bool Compress::deflatePropertyData( QByteArray &encodedData, const QList<qint64> &source )
bool Compress::deflatePropertyData( QByteArray& encodedData, const QList<qint64>& source )
{
Q_UNUSED( encodedData );
Q_UNUSED( source );
+4 -4
View File
@@ -112,11 +112,11 @@ namespace Isf
};
bool inflatePacketData( DataSource &source, quint64 length, QList<qint64> &decodedData );
bool deflatePacketData( QByteArray &destination, const QList<qint64> &decodedData );
bool inflatePacketData( DataSource* source, quint64 length, QList<qint64>& decodedData );
bool deflatePacketData( QByteArray& destination, const QList<qint64>& decodedData );
bool inflatePropertyData( DataSource &source, quint64 length, QList<qint64> &decodedData );
bool deflatePropertyData( QByteArray &destination, const QList<qint64> &decodedData );
bool inflatePropertyData( DataSource* source, quint64 length, QList<qint64>& decodedData );
bool deflatePropertyData( QByteArray& destination, const QList<qint64>& decodedData );
}
}
+12 -14
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -29,7 +27,7 @@
using namespace Isf;
using namespace Compress;
using namespace Isf::Compress;
@@ -51,7 +49,7 @@ DataSource::DataSource()
*
* @param data Byte array to copy and use as data source
*/
DataSource::DataSource( const QByteArray &data )
DataSource::DataSource( const QByteArray& data )
: currentBitIndex_( 8 )
{
buffer_.setData( data );
@@ -109,7 +107,7 @@ void DataSource::append( char byte )
*
* @param constBits The list of bits to append
*/
void DataSource::append( const QBitArray &constBits )
void DataSource::append( const QBitArray& constBits )
{
if( constBits.size() == 0 )
{
@@ -202,7 +200,7 @@ void DataSource::append( const QBitArray &constBits )
*
* @param bytes The bytes to append
*/
void DataSource::append( const QByteArray &bytes )
void DataSource::append( const QByteArray& bytes )
{
bool wasEmpty = ( buffer_.size() == 0 );
@@ -274,7 +272,7 @@ void DataSource::clear()
*
* @return byte array
*/
const QByteArray &DataSource::data() const
const QByteArray& DataSource::data() const
{
return buffer_.data();
}
@@ -328,7 +326,7 @@ quint8 DataSource::getBitIndex()
* @param ok If set, it will contain whether the call was successful or not.
* @return bool
*/
bool DataSource::getBit( bool *ok )
bool DataSource::getBit( bool* ok )
{
if( currentBitIndex_ >= 8 )
{
@@ -367,7 +365,7 @@ bool DataSource::getBit( bool *ok )
* @param ok If set, it will contain whether the call was successful or not.
* @return quint64 with the set of read bits
*/
quint64 DataSource::getBits( quint8 amount, bool *ok )
quint64 DataSource::getBits( quint8 amount, bool* ok )
{
if( amount > 64 )
{
@@ -436,7 +434,7 @@ quint64 DataSource::getBits( quint8 amount, bool *ok )
* @param ok If set, it will contain whether the call was successful or not.
* @return char
*/
char DataSource::getByte( bool *ok )
char DataSource::getByte( bool* ok )
{
bool gotBitOk;
quint8 pos = 0;
@@ -480,7 +478,7 @@ char DataSource::getByte( bool *ok )
* @param ok If set, it will contain whether the call was successful or not.
* @return byte array of read bytes
*/
QByteArray DataSource::getBytes( quint8 amount, bool *ok )
QByteArray DataSource::getBytes( quint8 amount, bool* ok )
{
QByteArray bytes;
bool gotByteOk;
@@ -600,7 +598,7 @@ void DataSource::prepend( char byte )
*
* @param bytes Bytes to add
*/
void DataSource::prepend( const QByteArray &bytes )
void DataSource::prepend( const QByteArray& bytes )
{
buffer_.buffer().prepend( bytes );
@@ -663,7 +661,7 @@ void DataSource::seekRelative( int pos )
*
* @param data New array to copy and use as the data source
*/
void DataSource::setData( const QByteArray &data )
void DataSource::setData( const QByteArray& data )
{
buffer_.close();
buffer_.setData( data );
+11 -13
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -49,30 +47,30 @@ namespace Isf
public: // Public constructors
DataSource();
DataSource( const QByteArray &data );
DataSource( const QByteArray& data );
~DataSource();
public: // Public status retrieval methods
bool atEnd( bool considerBits = false ) const;
const QByteArray &data() const;
const QByteArray& data() const;
qint64 pos() const;
qint64 size() const;
public: // Public data manipulation methods
void append( char byte );
void append( const QBitArray &bits );
void append( const QByteArray &bytes );
void append( const QBitArray& bits );
void append( const QByteArray& bytes );
void clear();
void flush();
bool getBit( bool *ok = 0 );
quint64 getBits( quint8 amount, bool *ok = 0 );
bool getBit( bool* ok = 0 );
quint64 getBits( quint8 amount, bool* ok = 0 );
quint8 getBitIndex();
char getByte( bool *ok = 0 );
QByteArray getBytes( quint8 amount, bool *ok = 0 );
char getByte( bool* ok = 0 );
QByteArray getBytes( quint8 amount, bool* ok = 0 );
void prepend( char byte );
void prepend( const QByteArray &bytes );
void prepend( const QByteArray& bytes );
void reset();
void setData( const QByteArray &data );
void setData( const QByteArray& data );
void seekRelative( int pos );
void skipToNextByte();
void skipToPrevByte();
+16 -18
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -40,7 +38,7 @@ using namespace Isf;
* @param source Data Source where to read bytes from
* @return quint64
*/
quint64 Compress::decodeUInt( DataSource &source )
quint64 Compress::decodeUInt( DataSource* source )
{
quint8 byte; // Current byte
quint8 flag; // Used to find out if there are more bytes to convert
@@ -49,7 +47,7 @@ quint64 Compress::decodeUInt( DataSource &source )
do
{
byte = source.getByte();
byte = source->getByte();
flag = byte & 0x80;
value |= (byte & 0x7F) << count;
count += 7;
@@ -67,7 +65,7 @@ quint64 Compress::decodeUInt( DataSource &source )
* @param source Data Source where to read bytes from
* @return qint64
*/
qint64 Compress::decodeInt( DataSource &source )
qint64 Compress::decodeInt( DataSource* source )
{
bool isNegative = false;
qint64 value = decodeUInt( source );
@@ -98,7 +96,7 @@ qint64 Compress::decodeInt( DataSource &source )
* @param source Data Source where to read bytes from
* @return float
*/
float Compress::decodeFloat( DataSource &source )
float Compress::decodeFloat( DataSource* source )
{
qint8 index;
@@ -113,14 +111,14 @@ float Compress::decodeFloat( DataSource &source )
index = 3;
do
{
data.bytes[ index-- ] = source.getByte();
data.bytes[ index-- ] = source->getByte();
}
while( index >= 0 );
#else
index = 0;
do
{
data.bytes[ index++ ] = source.getByte();
data.bytes[ index++ ] = source->getByte();
}
while( index <= 3 );
#endif
@@ -170,17 +168,17 @@ QByteArray Compress::encodeUInt( quint64 value )
* @param prepend False (default value) to append the encoded value to the existing data
* True to prepend the new value to the existing data
*/
void Compress::encodeUInt( DataSource &source, quint64 value, bool prepend )
void Compress::encodeUInt( DataSource* source, quint64 value, bool prepend )
{
QByteArray result( encodeUInt( value ) );
if( prepend )
{
source.prepend( result );
source->prepend( result );
}
else
{
source.append( result );
source->append( result );
}
}
@@ -226,17 +224,17 @@ QByteArray Compress::encodeInt( qint64 value )
* @param prepend False (default value) to append the encoded value to the existing data
* True to prepend the new value to the existing data
*/
void Compress::encodeInt( DataSource &source, qint64 value, bool prepend )
void Compress::encodeInt( DataSource* source, qint64 value, bool prepend )
{
QByteArray result( encodeInt( value ) );
if( prepend )
{
source.prepend( result );
source->prepend( result );
}
else
{
source.append( result );
source->append( result );
}
}
@@ -291,17 +289,17 @@ QByteArray Compress::encodeFloat( float value )
* @param prepend False (default value) to append the encoded value to the existing data
* True to prepend the new value to the existing data
*/
void Compress::encodeFloat( DataSource &source, float value, bool prepend )
void Compress::encodeFloat( DataSource* source, float value, bool prepend )
{
QByteArray result( encodeFloat( value ) );
if( prepend )
{
source.prepend( result );
source->prepend( result );
}
else
{
source.append( result );
source->append( result );
}
}
+7 -9
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -37,18 +35,18 @@ namespace Isf
namespace Compress
{
quint64 decodeUInt( DataSource &source );
qint64 decodeInt( DataSource &source );
float decodeFloat( DataSource &source );
quint64 decodeUInt( DataSource* source );
qint64 decodeInt( DataSource* source );
float decodeFloat( DataSource* source );
QByteArray encodeUInt( quint64 value );
void encodeUInt( DataSource &source, quint64 value, bool prepend = false );
void encodeUInt( DataSource* source, quint64 value, bool prepend = false );
QByteArray encodeInt( qint64 value );
void encodeInt( DataSource &source, qint64 value, bool prepend = false );
void encodeInt( DataSource* source, qint64 value, bool prepend = false );
QByteArray encodeFloat( float value );
void encodeFloat( DataSource &source, float value, bool prepend = false );
void encodeFloat( DataSource* source, float value, bool prepend = false );
quint8 getMultiByteSize( quint64 value );
quint8 getMultiByteSize( qint64 value );
+4 -4
View File
@@ -28,18 +28,18 @@
// Internal helper function to read GIF data from a byte array
int GifReadFromByteArray( GifFileType *gif, GifByteType* bytes, int size )
int GifReadFromByteArray( GifFileType* gif, GifByteType* bytes, int size )
{
QBuffer *buffer = (QBuffer*) gif->UserData;
QBuffer* buffer = (QBuffer*) gif->UserData;
return buffer->read( (char*)bytes, size );
}
// Internal helper function to write GIF data into a byte array
int GifWriteToByteArray( GifFileType *gif, const GifByteType* bytes, int size )
int GifWriteToByteArray( GifFileType* gif, const GifByteType* bytes, int size )
{
QBuffer *buffer = (QBuffer*) gif->UserData;
QBuffer* buffer = (QBuffer*) gif->UserData;
return buffer->write( (char*)bytes, size );
}
+220 -276
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -43,7 +41,7 @@ using namespace Isf;
*
* @param parent The parent widget.
*/
InkCanvas:: InkCanvas( QWidget *parent )
InkCanvas:: InkCanvas( QWidget* parent )
: QWidget( parent )
, erasingImage_( false )
, drawing_( 0 )
@@ -59,6 +57,10 @@ InkCanvas:: InkCanvas( QWidget *parent )
setPenColor( Qt::black );
setPenSize( 4 );
setAttribute( Qt::WA_StaticContents, true ); // only give us paint events for the parts of us that become visible on resize.
setAutoFillBackground( true );
clear();
// prepare the buffer
@@ -69,8 +71,6 @@ InkCanvas:: InkCanvas( QWidget *parent )
// start with a drawing pen by default.
setPenType( DrawingPen );
setAttribute( Qt::WA_StaticContents );
}
@@ -90,62 +90,13 @@ InkCanvas::~InkCanvas()
/**
* Creates a QCursor displayed when the mouse pointer moves over the widget.
* Returns the drawing's ISF representation.
*
* The cursor becomes a point, drawn with the current stroke colour and pen size.
* @return A QByteArray filled with ISF data.
*/
void InkCanvas::updateCursor()
QByteArray InkCanvas::bytes()
{
if ( cursorPixmap_.isNull() )
{
cursorPixmap_ = QPixmap( QSize( 32, 32 ) );
}
if ( penType_ == EraserPen )
{
cursorPixmap_ = QPixmap( ":pics/draw-eraser.png" );
cursor_ = QCursor( cursorPixmap_, 0, cursorPixmap_.height() );
}
else
{
cursorPixmap_.fill( Qt::transparent );
QPainter painter( &cursorPixmap_ );
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
painter.setPen( QPen( color_, penSize_, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin ) );
// now draw a point.
painter.drawPoint( QPoint( cursorPixmap_.size().width() / 2, cursorPixmap_.size().height() / 2 ) );
cursor_ = QCursor( cursorPixmap_ );
}
// create our cursor.
setCursor( cursor_ );
}
/**
* Return the suggested size for the canvas.
*
* The actual size hint will depend on the size of the drawing on the canvas. By default,
* the size hint is 300x300 pixels.
*/
QSize InkCanvas::sizeHint() const
{
if ( drawing_->isNull() )
{
return QSize( 300, 300 );
}
else
{
QRect boundingRect = drawing_->boundingRect();
boundingRect.setTopLeft( QPoint( 0, 0 ) );
return boundingRect.size();
}
return Isf::Stream::writer( *drawing_ );
}
@@ -174,58 +125,47 @@ void InkCanvas::clear()
/**
* Change the color of the pen used to draw on the Ink canvas.
* Clear the internal pixmap buffer.
*
* @param newColor The new color for the pen.
* The buffer used to quickly render on the widget painting area
* the new and old strokes: every new stroke is saved here.
* This allows to avoid repainting all strokes at every paint event.
*/
void InkCanvas::setPenColor( QColor newColor )
void InkCanvas::clearBuffer()
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen color:" << newColor.name();
#endif
color_ = newColor;
updateCursor();
bufferPixmap_ = QPixmap( size() );
bufferPixmap_.fill( Qt::transparent );
}
/**
* Change the size of the pen. This value is in pixels.
* Retrieve the Isf::Drawing instance that the canvas is currently manipulating.
*
* @param pixels The size of the pen, in pixels
* Beware: if you have not set your own Isf::Drawing instance via setDrawing(), you must not delete
* the object that this method returns. In this case this method returns a pointer to an internal
* Isf::Drawing instance that must not be deleted. If you have previously used setDrawing() then you
* are free to do whatever you like with this pointer.
*
* \code
* InkCanvas* canvas = new InkCanvas( this );
*
* Isf::Drawing* drawing = canvas->drawing();
* delete drawing; // bad! deleting an object internal to InkCanvas.
*
* canvas->setDrawing( existingIsfDrawingInstance );
*
* drawing = canvas->drawing();
* delete drawing; // good - drawing points to existingIsfDrawingInstance.
* \endcode
*
*
* @see setDrawing()
* @return The current Isf::Drawing instance.
*/
void InkCanvas::setPenSize( int pixels )
Isf::Drawing* InkCanvas::drawing()
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen size:" << pixels;
#endif
penSize_ = pixels;
updateCursor();
}
/**
* Change the pen type.
*
* Currently, only PenType::EraserPen and PenType::DrawingPen are supported. See the PenType
* enum for more information.
*
* @see PenType
* @param type The new pen type
*/
void InkCanvas::setPenType( PenType type )
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen type:" << type;
#endif
penType_ = type;
updateCursor();
return drawing_;
}
@@ -239,16 +179,12 @@ void InkCanvas::setPenType( PenType type )
* @see mousePressEvent()
* @param endPoint Final point of the line
*/
void InkCanvas::drawLineTo( const QPoint &endPoint )
void InkCanvas::drawLineTo( const QPoint& endPoint )
{
if( drawing_ == 0 )
{
qWarning() << "Uninitialized usage of InkCanvas!";
return;
}
Q_ASSERT_X( drawing_, "drawLineTo", "Drawing is null" );
// draw the "in progress" strokes on the buffer.
QPainter painter( &(bufferPixmap_) );
QPainter painter( &bufferPixmap_ );
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
QColor color = color_;
@@ -282,6 +218,18 @@ void InkCanvas::drawLineTo( const QPoint &endPoint )
/**
* Renders the ink drawing to a QImage and returns it.
*
* @return A QImage containing the rendered Ink.
*/
QImage InkCanvas::image()
{
return drawing_->pixmap( Qt::white ).toImage();
}
/**
* Get whether the drawing is empty (i.e., contains no strokes).
*
@@ -306,13 +254,9 @@ bool InkCanvas::isEmpty()
* @see mouseReleaseEvent()
* @param event The mouse button press event
*/
void InkCanvas::mousePressEvent( QMouseEvent *event )
void InkCanvas::mousePressEvent( QMouseEvent* event )
{
if( drawing_ == 0 )
{
qWarning() << "Uninitialized usage of InkCanvas!";
return;
}
Q_ASSERT_X( drawing_, "mousePressEvent", "Drawing is null" );
if( event->button() != Qt::LeftButton )
{
@@ -325,7 +269,7 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
{
// is there a stroke here?
QPoint point = event->pos();
Stroke *s = drawing_->strokeAtPoint( point );
Stroke* s = drawing_->strokeAtPoint( point );
if ( s != 0 )
{
drawing_->deleteStroke( s );
@@ -338,47 +282,19 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
lastPoint_ = event->pos();
// Search if there already is an attributes set compatible with the current one
Isf::AttributeSet *reusableAttributeSet = 0;
foreach( Isf::AttributeSet *set, drawing_->attributeSets() )
{
if( abs( (qreal)penSize_ - set->penSize.width() ) < 1.0f
&& color_ == set->color )
{
reusableAttributeSet = set;
#ifdef ISFQT_DEBUG
qDebug() << "Found an usable ISF attribute set";
#endif
break;
}
}
// If none is found, create a new one
if( ! reusableAttributeSet )
{
#ifdef ISFQT_DEBUG
qDebug() << "Creating new attribute set";
#endif
reusableAttributeSet = new Isf::AttributeSet;
reusableAttributeSet->color = color_;
reusableAttributeSet->penSize.setWidth ( (qreal)penSize_ );
reusableAttributeSet->penSize.setHeight( (qreal)penSize_ );
drawing_->addAttributeSet( reusableAttributeSet );
}
// Use it for the next strokes
drawing_->setCurrentAttributeSet( reusableAttributeSet );
// If there already is a stroke, add it
if( currentStroke_ )
{
currentStroke_->finalize();
drawing_->addStroke( currentStroke_ );
currentStroke_ = 0;
}
currentStroke_ = new Isf::Stroke;
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
currentStroke_ = new Isf::Stroke();
currentStroke_->addPoint( lastPoint_ );
currentStroke_->setColor( color_ );
currentStroke_->setPenSize( QSizeF( (qreal)penSize_, (qreal)penSize_ ) );
currentStroke_->setFlag( FitToCurve, true );
// Draw the initial point
drawLineTo( lastPoint_ );
@@ -390,7 +306,7 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
* Continue drawing the current stroke.
*
* As the cursor moves across the canvas we continue drawing the stroke started in
* mousePressEvent(). A line is drawn between the last point and the current point
* mousePressEvent(). A line is drawn between the last point and the current point
* as given by QMouseEvent::pos().
*
* Once the mouse button is released, drawing ends.
@@ -399,18 +315,20 @@ void InkCanvas::mousePressEvent( QMouseEvent *event )
* @see mouseReleaseEvent()
* @param event The mouse move event
*/
void InkCanvas::mouseMoveEvent( QMouseEvent *event )
void InkCanvas::mouseMoveEvent( QMouseEvent* event )
{
if( ! ( event->buttons() & Qt::LeftButton ) || ! scribbling_ )
{
return;
}
Q_ASSERT_X( drawing_, "mouseMoveEvent", "Drawing is null" );
if ( penType_ == EraserPen )
{
// is there a stroke here?
QPoint point = event->pos();
Stroke *s = drawing_->strokeAtPoint( point );
Stroke* s = drawing_->strokeAtPoint( point );
if ( s != 0 )
{
drawing_->deleteStroke( s );
@@ -421,12 +339,6 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
return;
}
if( drawing_ == 0 )
{
qWarning() << "Uninitialized usage of InkCanvas!";
return;
}
QPoint position( event->pos() );
// Don't add duplicate points. Mainly useful when drawing dots.
@@ -437,16 +349,10 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
drawLineTo( position );
if( currentStroke_ == 0 )
{
#ifdef KMESSDEBUG_INKEDIT_GENERAL
qWarning() << "The stroke isn't ready!";
#endif
return;
}
Q_ASSERT_X( currentStroke_, "mouseMoveEvent", "currentStroke_ is null" );
// Add the new point to the stroke
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
currentStroke_->addPoint( lastPoint_ );
}
@@ -460,13 +366,9 @@ void InkCanvas::mouseMoveEvent( QMouseEvent *event )
* @see mouseMoveEvent()
* @param event The mouse release event
*/
void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
void InkCanvas::mouseReleaseEvent( QMouseEvent* event )
{
if( drawing_ == 0 )
{
qWarning() << "Uninitialized usage of InkCanvas!";
return;
}
Q_ASSERT_X( drawing_, "mouseReleaseEvent", "Drawing is null" );
if( event->button() != Qt::LeftButton || ! scribbling_ )
{
@@ -486,16 +388,7 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
drawLineTo( position );
}
scribbling_ = false;
emit inkChanged();
if( ! currentStroke_ )
{
#ifdef KMESSDEBUG_INKEDIT_GENERAL
qWarning() << "The stroke isn't ready!";
#endif
return;
}
Q_ASSERT_X( currentStroke_, "mouseReleaseEvent", "currentStroke_ is null" );
#ifdef KMESSDEBUG_INKEDIT_GENERAL
qDebug() << "Finishing up stroke";
@@ -504,9 +397,10 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
// Don't add duplicate points. Mainly useful when drawing dots.
if( lastPoint_ != position )
{
currentStroke_->points.append( Isf::Point( lastPoint_ ) );
currentStroke_->addPoint( lastPoint_ );
}
currentStroke_->finalize();
drawing_->addStroke( currentStroke_ );
currentStroke_ = 0;
@@ -515,21 +409,12 @@ void InkCanvas::mouseReleaseEvent( QMouseEvent *event )
// clear the buffer.
clearBuffer();
}
// update
update();
/**
* Clear the internal pixmap buffer.
*
* The buffer used to quickly render on the widget painting area
* the new and old strokes: every new stroke is saved here.
* This allows to avoid repainting all strokes at every paint event.
*/
void InkCanvas::clearBuffer()
{
bufferPixmap_ = QPixmap( size() );
bufferPixmap_.fill( Qt::transparent );
scribbling_ = false;
emit inkChanged();
}
@@ -539,28 +424,19 @@ void InkCanvas::clearBuffer()
*
* For performance reasons an internal buffer is used to ensure that
* the entire Ink drawing is not re-rendered on each paintEvent call.
* This buffer is invalidated only when a stroke is added or removed, the
* This buffer is invalidated only when a stroke is added or removed, the
* drawing is changed or the canvas cleared.
*
*
* @param event The paint event from Qt.
*/
void InkCanvas::paintEvent( QPaintEvent *event )
void InkCanvas::paintEvent( QPaintEvent* event )
{
Q_UNUSED( event );
QPainter painter( this );
painter.save();
painter.setBrush( QBrush( canvasColor_ ) );
painter.drawRect( QRect(-1, -1, width() + 1 , height() + 1 ) );
painter.restore();
if( drawing_ == 0 )
{
qWarning() << "Uninitialized usage of InkCanvas!";
return;
}
Q_ASSERT_X( drawing_, "paintEvent", "Drawing is null" );
// draw the ISF first, then the buffer over the top.
// buffer has a transparent background.
@@ -583,42 +459,13 @@ void InkCanvas::paintEvent( QPaintEvent *event )
painter.drawPixmap( boundingRect.topLeft(), isfPixmap );
// draw the buffer from 0,0.
painter.drawPixmap( QPoint(0, 0), bufferPixmap_ );
painter.drawPixmap( event->rect(), bufferPixmap_, event->rect() );
QWidget::paintEvent( event );
}
/**
* The widget has changed size, re-draw everything.
*
* @param event The resizing event.
*/
void InkCanvas::resizeEvent( QResizeEvent *event )
{
// need to resize the buffer pixmap.
clearBuffer();
update();
QWidget::resizeEvent( event );
}
/**
* Renders the ink drawing to a QImage and returns it.
*
* @return A QImage containing the rendered Ink.
*/
QImage InkCanvas::image()
{
return drawing_->pixmap().toImage();
}
/**
* Get the current pen color.
*
@@ -659,32 +506,18 @@ InkCanvas::PenType InkCanvas::penType()
/**
* Retrieve the Isf::Drawing instance that the canvas is currently manipulating.
* The widget has changed size, re-draw everything.
*
* Beware: if you have not set your own Isf::Drawing instance via setDrawing(), you must not delete
* the object that this method returns. In this case this method returns a pointer to an internal
* Isf::Drawing instance that must not be deleted. If you have previously used setDrawing() then you
* are free to do whatever you like with this pointer.
*
* \code
* InkCanvas *canvas = new InkCanvas( this );
*
* Isf::Drawing *drawing = canvas->drawing();
* delete drawing; // bad! deleting an object internal to InkCanvas.
*
* canvas->setDrawing( existingIsfDrawingInstance );
*
* drawing = canvas->drawing();
* delete drawing; // good - drawing points to existingIsfDrawingInstance.
* \endcode
*
*
* @see setDrawing()
* @return The current Isf::Drawing instance.
* @param event The resizing event.
*/
Isf::Drawing *InkCanvas::drawing()
void InkCanvas::resizeEvent( QResizeEvent* event )
{
return drawing_;
// need to resize the buffer pixmap.
clearBuffer();
update();
QWidget::resizeEvent( event );
}
@@ -692,8 +525,8 @@ Isf::Drawing *InkCanvas::drawing()
/**
* Save the current ISF drawing to a QIODevice.
*
* If the base64 param is True, then the drawing will be written base64-encoded.
* This is helpful for transmission over mediums which are not binary-friendly.
* If the base64 param is true, then the drawing will be written base64-encoded.
* This is helpful for transmission over binary-unfriendly media.
*
* @param dev The QIODevice to save to.
* @param base64 If true, the drawing is written encoded with base64.
@@ -706,18 +539,6 @@ void InkCanvas::save( QIODevice &dev, bool base64 )
/**
* Returns the drawing's ISF representation.
*
* @return A QByteArray filled with ISF data.
*/
QByteArray InkCanvas::bytes()
{
return Isf::Stream::writer( *drawing_ );
}
/**
* Set the canvas colour (i.e., the background colour of the InkCanvas control)
*
@@ -731,6 +552,10 @@ void InkCanvas::setCanvasColor( QColor newColor )
qDebug() << "Setting new canvas color:" << newColor.name();
#endif
canvasColor_ = newColor;
QPalette p = palette();
p.setColor( QPalette::Window, newColor );
setPalette( p );
update();
}
@@ -740,11 +565,11 @@ void InkCanvas::setCanvasColor( QColor newColor )
* Changes the currently displayed Ink to the one supplied.
*
* Note: InkCanvas does not take ownership of Isf::Drawing instances supplied here.
* You are still responsible for ensuring they are deleted appropriately.
* You are still responsible of ensuring they are deleted appropriately.
*
* @param drawing The new Ink drawing to display.
*/
void InkCanvas::setDrawing( Isf::Drawing *drawing )
void InkCanvas::setDrawing( Isf::Drawing* drawing )
{
drawing_ = drawing;
@@ -757,7 +582,126 @@ void InkCanvas::setDrawing( Isf::Drawing *drawing )
drawingDirty_ = true;
updateGeometry();
update();
}
/**
* Change the color of the pen used to draw on the Ink canvas.
*
* @param newColor The new color for the pen.
*/
void InkCanvas::setPenColor( QColor newColor )
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen color:" << newColor.name();
#endif
color_ = newColor;
updateCursor();
}
/**
* Change the size of the pen. This value is in pixels.
*
* @param pixels The size of the pen, in pixels
*/
void InkCanvas::setPenSize( int pixels )
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen size:" << pixels;
#endif
penSize_ = pixels;
updateCursor();
}
/**
* Change the pen type.
*
* Currently, only PenType::EraserPen and PenType::DrawingPen are supported. See the PenType
* enum for more information.
*
* @see PenType
* @param type The new pen type
*/
void InkCanvas::setPenType( PenType type )
{
#ifdef ISFQT_DEBUG
qDebug() << "Setting new pen type:" << type;
#endif
penType_ = type;
updateCursor();
}
/**
* Return the suggested size for the canvas.
*
* The actual size hint will depend on the size of the drawing on the canvas. By default,
* the size hint is 300x300 pixels.
*/
QSize InkCanvas::sizeHint() const
{
if ( drawing_->isNull() )
{
return QSize( 300, 300 );
}
else
{
QRect boundingRect = drawing_->boundingRect();
boundingRect.setTopLeft( QPoint( 0, 0 ) );
return boundingRect.size();
}
}
/**
* Creates a QCursor displayed when the mouse pointer moves over the widget.
*
* The cursor becomes a point, drawn with the current stroke colour and pen size.
*/
void InkCanvas::updateCursor()
{
if ( cursorPixmap_.isNull() )
{
cursorPixmap_ = QPixmap( QSize( 32, 32 ) );
}
if ( penType_ == EraserPen )
{
cursorPixmap_ = QPixmap( ":pics/draw-eraser.png" );
cursor_ = QCursor( cursorPixmap_, 0, cursorPixmap_.height() );
}
else
{
cursorPixmap_.fill( Qt::transparent );
QPainter painter( &cursorPixmap_ );
painter.setRenderHints( QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true );
painter.setPen( QPen( color_, penSize_, Qt::SolidLine, Qt::RoundCap,
Qt::RoundJoin ) );
// now draw a point.
painter.drawPoint( QPoint( cursorPixmap_.size().width() / 2, cursorPixmap_.size().height() / 2 ) );
cursor_ = QCursor( cursorPixmap_ );
}
// create our cursor.
setCursor( cursor_ );
}
+105 -3
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -44,6 +42,12 @@
namespace Isf
{
// Forward declarations
class Stroke;
namespace Compress
{
class DataSource;
}
@@ -114,6 +118,104 @@ namespace Isf
/**
* Drawing attributes for points.
*/
struct AttributeSet
{
/// Constructor
AttributeSet()
: color( Qt::black )
, flags( 0x10 ) // Meaning unknown
, penSize( 8.f, 8.f ) // Default pen is 8.0 pixels wide
{
}
/// Quick comparison operator
bool operator ==( const AttributeSet& other )
{
return color == other.color
&& flags == other.flags
&& penSize == other.penSize;
}
/// Quick comparison operator
bool operator !=( const AttributeSet& other )
{
return color != other.color
|| flags != other.flags
|| penSize != other.penSize;
}
/// The stroke color, optionally with alpha channel
QColor color;
/// Mask of StrokeFlags, @see StrokeFlags
StrokeFlags flags;
/// Dimensions of the pencil in pixels
QSizeF penSize;
};
/**
* Drawing attributes for strokes.
*/
struct StrokeInfo
{
/// Constructor
StrokeInfo()
: hasPressureData( false )
, hasXData( true )
, hasYData( true )
{
}
/// Whether the stroke contains pressure info or not
bool hasPressureData;
/// Whether the stroke contains X coordinates or not
bool hasXData;
/// Whether the stroke contains Y coordinates or not
bool hasYData;
};
/**
* Internal parser data
*/
struct StreamData
{
StreamData()
: currentAttributeSetIndex( 0 )
, currentMetricsIndex( 0 )
, currentStrokeInfoIndex( 0 )
, currentTransformsIndex( 0 )
, dataSource( 0 )
{
}
/// List of attributes of the points in the drawing
QList<AttributeSet> attributeSets;
/// Drawing's bounding rectangle
QRect boundingRect;
/// Current attribute set
quint64 currentAttributeSetIndex;
/// Current metrics set
quint64 currentMetricsIndex;
/// Current stroke info
quint64 currentStrokeInfoIndex;
/// Current transform
quint64 currentTransformsIndex;
/// Raw bytes source used to read and write streams
Compress::DataSource* dataSource;
/// List of metrics used in the drawing
QList<Metrics*> metrics;
/// List of stroke info
QList<StrokeInfo*> strokeInfos;
/// Transformation matrices
QList<QMatrix*> transforms;
};
}
+163 -365
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -48,6 +46,10 @@ using namespace Compress;
#define SUPPORTED_ISF_VERSION 0
// Initialization of static properties
StreamData* Stream::streamData_( 0 );
/**
* Convert a raw ISF data stream into a drawing.
@@ -59,23 +61,26 @@ using namespace Compress;
* need to be decoded first
* @return an Isf::Drawing, with null contents on error
*/
Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
Drawing& Stream::reader( const QByteArray& rawData, bool decodeFromBase64 )
{
// Create a new drawing on the heap to ensure it will keep
// living after this method returns
Drawing *drawing = new Drawing;
DataSource isfData( decodeFromBase64
? QByteArray::fromBase64( rawData )
: rawData );
int size = isfData.size();
if( size == 0 )
{
return *drawing;
}
Drawing* drawing = new Drawing();
ParserState state = ISF_PARSER_START;
streamData_ = new StreamData();
streamData_->dataSource = new DataSource( decodeFromBase64
? QByteArray::fromBase64( rawData )
: rawData );
int size = streamData_->dataSource->size();
if( size == 0 )
{
state = ISF_PARSER_FINISH;
drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
}
while( state != ISF_PARSER_FINISH )
{
switch( state )
@@ -83,7 +88,7 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
case ISF_PARSER_START:
{
// step 1: read ISF version.
quint8 version = decodeUInt( isfData );
quint8 version = decodeUInt( streamData_->dataSource );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Version:" << version;
#endif
@@ -106,13 +111,13 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
{
// read ISF stream size.
// check it matches the length of the data array.
quint64 streamSize = decodeUInt( isfData );
quint64 streamSize = decodeUInt( streamData_->dataSource );
if ( streamSize != (quint64)( isfData.size() - isfData.pos() ) )
if ( streamSize != (quint64)( streamData_->dataSource->size() - streamData_->dataSource->pos() ) )
{
#ifdef ISFQT_DEBUG
qDebug() << "Invalid stream size" << streamSize
<< ", expected" << ( isfData.size() - isfData.pos() );
<< ", expected" << ( streamData_->dataSource->size() - streamData_->dataSource->pos() );
#endif
// streamsize is bad.
drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
@@ -126,12 +131,6 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
// Validate the drawing
drawing->isNull_ = false;
// Fill up the default properties
drawing->currentMetrics_ = &drawing->defaultMetrics_;
drawing->currentAttributeSet_ = &drawing->defaultAttributeSet_;
drawing->currentStrokeInfo_ = &drawing->defaultStrokeInfo_;
drawing->currentTransform_ = &drawing->defaultTransform_;
// start looking for ISF tags.
state = ISF_PARSER_TAG;
}
@@ -139,331 +138,16 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
break;
}
// ******************
// This is the key point of the state machine. This will continually loop looking for ISF
// tags and farming off to the appropriate method.
// *******************
case ISF_PARSER_TAG:
{
if( isfData.atEnd() )
if( streamData_->dataSource->atEnd() )
{
state = ISF_PARSER_FINISH;
break;
}
QString place( "0x" + QString::number( isfData.pos(), 16 ).toUpper() );
quint64 tagIndex = decodeUInt( isfData );
switch( tagIndex )
{
case TAG_INK_SPACE_RECT:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_INK_SPACE_RECT";
#endif
drawing->error_ = TagsParser::parseInkSpaceRectangle( isfData, *drawing );
break;
case TAG_GUID_TABLE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_GUID_TABLE";
#endif
drawing->error_ = TagsParser::parseGuidTable( isfData, *drawing );
break;
case TAG_DRAW_ATTRS_TABLE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_DRAW_ATTRS_TABLE";
#endif
drawing->error_ = TagsParser::parseAttributeTable( isfData, *drawing );
break;
case TAG_DRAW_ATTRS_BLOCK:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_DRAW_ATTRS_BLOCK";
#endif
drawing->error_ = TagsParser::parseAttributeBlock( isfData, *drawing );
break;
case TAG_STROKE_DESC_TABLE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_STROKE_DESC_TABLE";
#endif
drawing->error_ = TagsParser::parseStrokeDescTable( isfData, *drawing );
break;
case TAG_STROKE_DESC_BLOCK:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_STROKE_DESC_BLOCK";
#endif
drawing->error_ = TagsParser::parseStrokeDescBlock( isfData, *drawing );
break;
case TAG_BUTTONS:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_BUTTONS";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_BUTTONS" );
break;
case TAG_NO_X:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_NO_X";
#endif
drawing->error_ = ISF_ERROR_NONE;
drawing->hasXData_ = false;
break;
case TAG_NO_Y:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_NO_Y";
#endif
drawing->hasYData_ = false;
break;
case TAG_DIDX:
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_DIDX";
#endif
quint64 value = decodeUInt( isfData );
if( value < (uint)drawing->attributeSets_.count() )
{
drawing->currentAttributeSet_ = drawing->attributeSets_[ value ];
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Next strokes will use drawing attributes #" << value;
#endif
}
else
{
#ifdef ISFQT_DEBUG
qWarning() << "Invalid drawing attribute ID!";
#endif
}
break;
}
case TAG_STROKE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_STROKE";
#endif
drawing->error_ = TagsParser::parseStroke( isfData, *drawing );
break;
case TAG_STROKE_PROPERTY_LIST:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_STROKE_PROPERTY_LIST";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_STROKE_PROPERTY_LIST" );
break;
case TAG_POINT_PROPERTY:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_POINT_PROPERTY";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_POINT_PROPERTY" );
break;
case TAG_SIDX:
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_SIDX";
#endif
quint64 value = decodeUInt( isfData );
if( value < (uint)drawing->strokeInfo_.count() )
{
drawing->currentStrokeInfo_ = drawing->strokeInfo_[ value ];
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Next strokes will use stroke info #" << value;
#endif
}
else
{
#ifdef ISFQT_DEBUG
qWarning() << "Invalid stroke ID!";
#endif
}
break;
}
case TAG_COMPRESSION_HEADER:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_COMPRESSION_HEADER";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_COMPRESSION_HEADER" );
break;
case TAG_TRANSFORM_TABLE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_TABLE";
#endif
drawing->error_ = TagsParser::parseTransformationTable( isfData, *drawing );
break;
case TAG_TRANSFORM:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_ISOTROPIC_SCALE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ISOTROPIC_SCALE";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_ANISOTROPIC_SCALE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ANISOTROPIC_SCALE";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_ROTATE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_ROTATE";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_TRANSLATE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_TRANSLATE";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_SCALE_AND_TRANSLATE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_SCALE_AND_TRANSLATE";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TRANSFORM_QUAD:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TRANSFORM_QUAD";
#endif
drawing->error_ = TagsParser::parseTransformation( isfData, *drawing, tagIndex );
break;
case TAG_TIDX:
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_TIDX";
#endif
quint64 value = decodeUInt( isfData );
if( value < (uint)drawing->transforms_.count() )
{
drawing->currentTransform_ = drawing->transforms_[ value ];
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Next strokes will use transform #" << value;
#endif
}
else
{
#ifdef ISFQT_DEBUG
qWarning() << "Invalid transform ID!";
#endif
}
break;
}
case TAG_METRIC_TABLE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_METRIC_TABLE";
#endif
drawing->error_ = TagsParser::parseMetricTable( isfData, *drawing );
break;
case TAG_METRIC_BLOCK:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_METRIC_BLOCK";
#endif
drawing->error_ = TagsParser::parseMetricBlock( isfData, *drawing );
break;
case TAG_MIDX:
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_MIDX";
#endif
quint64 value = decodeUInt( isfData );
if( value < (uint)drawing->metrics_.count() )
{
drawing->currentMetrics_ = drawing->metrics_[ value ];
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Next strokes will use metrics #" << value;
#endif
}
else
{
#ifdef ISFQT_DEBUG
qWarning() << "Invalid metrics ID!";
#endif
}
break;
}
case TAG_MANTISSA:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_MANTISSA";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_MANTISSA" );
break;
case TAG_PERSISTENT_FORMAT:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_PERSISTENT_FORMAT";
#endif
drawing->error_ = TagsParser::parsePersistentFormat( isfData, *drawing );
break;
case TAG_HIMETRIC_SIZE:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_HIMETRIC_SIZE";
#endif
drawing->error_ = TagsParser::parseHiMetricSize( isfData, *drawing );
break;
case TAG_STROKE_IDS:
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_STROKE_IDS";
#endif
drawing->error_ = TagsParser::parseUnsupported( isfData, "TAG_STROKE_IDS" );
break;
default:
// If the tagIndex is known from the GUID table, show it differently
if( drawing->maxGuid_ > 0
&& tagIndex >= DEFAULT_TAGS_NUMBER && tagIndex <= drawing->maxGuid_ )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Got tag (@" << place << "): TAG_CUSTOM:" << tagIndex;
#endif
TagsParser::parseCustomTag( isfData, *drawing, tagIndex );
}
else
{
TagsParser::parseUnsupported( isfData, "Unknown " + QString::number( tagIndex ) );
}
break;
} // End of tagIndex switch
// Read the next tag from the stream
drawing->error_ = TagsParser::nextTag( streamData_, drawing );
if( drawing->error_ != ISF_ERROR_NONE )
{
@@ -489,8 +173,12 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
qDebug();
#endif
delete streamData_->dataSource;
if( drawing->error_ != ISF_ERROR_NONE )
{
delete streamData_;
streamData_ = 0;
return *drawing;
}
@@ -498,15 +186,17 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
// Adjust the bounding rectangle to include the strokes borders
QSize penSize( drawing->maxPenSize_.toSize() );
drawing->boundingRect_.adjust( -penSize.width() - 1, -penSize.height() - 1,
+penSize.width() + 1, +penSize.height() + 1 );
streamData_->boundingRect.adjust( -penSize.width() - 1, -penSize.height() - 1,
+penSize.width() + 1, +penSize.height() + 1 );
drawing->setBoundingRect( streamData_->boundingRect );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Drawing bounding rectangle:" << drawing->boundingRect_;
qDebug() << "Drawing bounding rectangle:" << drawing->boundingRect();
qDebug() << "Maximum thickness:" << drawing->maxPenSize_;
#endif
delete streamData_;
streamData_ = 0;
return *drawing;
}
@@ -528,7 +218,7 @@ Drawing &Stream::reader( const QByteArray &rawData, bool decodeFromBase64 )
* need to be decoded first
* @return an Isf::Drawing, with null contents on error
*/
Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64 )
Drawing& Stream::readerGif( const QByteArray& gifRawBytes, bool decodeFromBase64 )
{
QByteArray isfData;
@@ -549,7 +239,7 @@ Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64
gifData.open( QIODevice::ReadOnly );
// Open the gif file
GifFileType *gifImage = DGifOpen( (void*)&gifData, GifReadFromByteArray );
GifFileType* gifImage = DGifOpen( (void*)&gifData, GifReadFromByteArray );
if( gifImage != 0 )
{
DGifGetComment( gifImage, data?? );
@@ -622,6 +312,51 @@ Drawing &Stream::readerGif( const QByteArray &gifRawBytes, bool decodeFromBase64
/**
* Convert a Fortified-PNG image into a drawing.
*
* If the PNG image or the ISF data within it are invalid, or if the PNG did not
* have any ISF stream within, then a null Drawing is returned.
*
* @param gifRawBytes Source byte array with a Fortified PNG image
* @param decodeFromBase64 True if the bytes are in the Base64 format and
* need to be decoded first
* @return an Isf::Drawing, with null contents on error
*/
Drawing& Stream::readerPng( const QByteArray& pngRawBytes, bool decodeFromBase64 )
{
QByteArray isfData;
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Reading a PNG-Fortified file";
#endif
QByteArray pngBytes( decodeFromBase64
? QByteArray::fromBase64( pngRawBytes )
: pngRawBytes );
QImage imageData( QImage::fromData( pngBytes, "PNG" ) );
if( ! imageData.isNull() )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "Picture data is valid: checking for the ISF data tag...";
#endif
isfData = imageData.text( "application/x-ms-ink" ).toAscii();
if( ! isfData.isEmpty() )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "ISF data found! Decoding from Base64 and parsing it...";
#endif
isfData = QByteArray::fromBase64( isfData );
}
}
return reader( isfData );
}
/**
* Return whether the library was built with Fortified GIF support or not.
*
@@ -644,7 +379,7 @@ bool Stream::supportsGif()
* encoded with Base64 or not
* @return Byte array with an ISF data stream
*/
QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
QByteArray Stream::writer( const Drawing& drawing, bool encodeToBase64 )
{
if( &drawing == 0 || drawing.isNull() || drawing.error() != ISF_ERROR_NONE )
{
@@ -654,41 +389,51 @@ QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
return QByteArray();
}
DataSource isfData;
streamData_ = new StreamData();
streamData_->dataSource = new DataSource();
DataSource* dataSource = streamData_->dataSource;
// Add the initial data
TagsWriter::prepare( streamData_, &drawing );
// Write the persistent format tag
TagsWriter::addPersistentFormat( isfData, drawing );
TagsWriter::addPersistentFormat( streamData_, &drawing );
// Write the drawing size
TagsWriter::addHiMetricSize( isfData, drawing );
TagsWriter::addHiMetricSize( streamData_, &drawing );
// Write the attributes
TagsWriter::addAttributeTable( isfData, drawing );
TagsWriter::addAttributeTable( streamData_, &drawing );
// Write the metrics
TagsWriter::addMetricsTable( isfData, drawing );
TagsWriter::addMetricsTable( streamData_, &drawing );
// Write the transforms
TagsWriter::addTransformationTable( isfData, drawing );
TagsWriter::addTransformationTable( streamData_, &drawing );
// Write the strokes
TagsWriter::addStrokes( isfData, drawing );
TagsWriter::addStrokes( streamData_, &drawing );
// Write the stream size (at the start of the stream)
encodeUInt( isfData, isfData.size(), true/*prepend*/ );
encodeUInt( dataSource, dataSource->size(), true/*prepend*/ );
// Write the version number (at the start of the stream)
encodeUInt( isfData, SUPPORTED_ISF_VERSION, true/*prepend*/ );
encodeUInt( dataSource, SUPPORTED_ISF_VERSION, true/*prepend*/ );
QByteArray data( dataSource->data() );
delete streamData_->dataSource;
delete streamData_;
streamData_ = 0;
// Convert to Base64 if needed
if( encodeToBase64 )
{
return isfData.data().toBase64();
return data.toBase64();
}
else
{
return isfData.data();
return data;
}
}
@@ -703,13 +448,16 @@ QByteArray Stream::writer( const Drawing &drawing, bool encodeToBase64 )
* withous GIF support. Use Stream::supportsGif() to verify whether
* GIF was compiled in or not.
*
* The Fortified-GIF format is nothing more than a GIF image with the original
* ISF drawing added as a GIF Comment field.
*
* @see supportsGif()
* @param drawing Source drawing
* @param encodeToBase64 Whether the converted ISF stream should be
* @param encodeToBase64 Whether the converted GIF should be
* encoded with Base64 or not
* @return Byte array with an ISF data stream
* @return Byte array with a GIF data stream (optionally encoded with Base64)
*/
QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
QByteArray Stream::writerGif( const Drawing& drawing, bool encodeToBase64 )
{
QByteArray imageBytes;
@@ -730,8 +478,8 @@ QByteArray Stream::writerGif( const Drawing &drawing, bool encodeToBase64 )
// Initialise the gif variables
QBuffer gifData;
GifFileType *gifImage = NULL;
ColorMapObject *cmap = NULL;
GifFileType* gifImage = NULL;
ColorMapObject* cmap = NULL;
int height = isfImage.height();
int width = isfImage.width();
int numColors = 0;
@@ -908,3 +656,53 @@ writeError:
}
/**
* Convert a drawing into a Fortified-PNG image.
*
* The resulting byte array will be empty if the drawing is not valid.
*
* The Fortified-PNG format is nothing more than a PNG image with the original
* ISF drawing added as a PNG text field.
*
* @param drawing Source drawing
* @param encodeToBase64 Whether the converted ISF stream should be
* encoded with Base64 or not
* @return Byte array with a PNG data stream (optionally encoded with Base64)
*/
QByteArray Stream::writerPng( const Drawing& drawing, bool encodeToBase64 )
{
Drawing source( drawing );
// Get the ISF data stream
QByteArray isfData( writer( source ) );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "PNG-Fortifying an ISF stream of size" << isfData.size();
#endif
// Get the actual image
QImage isfImage( source.pixmap().toImage() );
// Add to it the Base64 version of the ISF drawing, as a comment and in Base64 form
// (that's because the PNG text fields are only meant to hold text)
isfImage.setText( "application/x-ms-ink", isfData.toBase64() );
// Save it as a PNG image
QBuffer imageBytes;
imageBytes.open( QIODevice::WriteOnly );
isfImage.save( &imageBytes, "PNG" );
imageBytes.close();
// Convert to Base64 if needed
if( encodeToBase64 )
{
return imageBytes.data().toBase64();
}
else
{
return imageBytes.data();
}
}
File diff suppressed because it is too large Load Diff
+517
View File
@@ -0,0 +1,517 @@
/***************************************************************************
* Copyright (C) 2010 by Valerio Pilo *
* valerio@kmess.org *
* *
* Copyright (C) 2010 by Adam Goossens *
* adam@kmess.org *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "isfqtstroke.h"
#include "isfqt-internal.h"
#include <QPainterPath>
using namespace Isf;
/**
* Constructor
*/
Stroke::Stroke()
: finalized_( true )
, metrics_( 0 )
, transform_( 0 )
{
}
/**
* Copy constructor
*
* @param other The object to clone
*/
Stroke::Stroke( const Stroke& other )
{
bezierControlPoints1_ = other.bezierControlPoints1_;
bezierControlPoints2_ = other.bezierControlPoints2_;
bezierKnots_ = other.bezierKnots_;
boundingRect_ = other.boundingRect_;
color_ = other.color_;
finalized_ = other.finalized_;
flags_ = other.flags_;
hasPressureData_ = other.hasPressureData_;
metrics_ = other.metrics_;
penSize_ = other.penSize_;
points_ = other.points_;
transform_ = other.transform_;
}
/**
* Destructor
*/
Stroke::~Stroke()
{
}
void Stroke::addPoint( Point point )
{
// Avoid splitting up the logic
addPoints( PointList() << point );
}
void Stroke::addPoints( PointList points )
{
points_.append( points );
// Hunt for pressure info
if( ! hasPressureData_ )
{
foreach( Point point, points )
{
if( point.pressureLevel != 0 )
{
hasPressureData_ = true;
break;
}
}
}
finalized_ = false;
}
/**
* Given a series of known (knot) points, knots, calculates the control points (c1, c2) to approximate a series of
* bezier curves passing smoothly through the knot points.
*/
void Stroke::bezierCalculateControlPoints()
{
// bezierKnots_.clear();
// bezierControlPoints1_.clear();
// bezierControlPoints2_.clear();
int numPoints = points_.size();
// For a better curve, don't pass through all of points:
// skip about 70% of them
int toSkip = 0.70 * numPoints;
int step = numPoints / ( numPoints - toSkip );
step = ( step < 1 ) ? 1 : step; // Sanity check
for( int i = 0; i < numPoints; i += step )
{
bezierKnots_.append( points_.at(i).position );
}
// always pass through the last point.
bezierKnots_.append( points_.last().position );
/////////////////////////////////////////////////////////////////////////////
if( bezierKnots_.size() == 0 )
{
return;
}
int n = bezierKnots_.size() - 1;
if( n < 1 )
{
#ifdef ISFQT_DEBUG
qWarning() << "Require at least two knot points to generate Bezier control points; ignoring.";
#endif
return;
}
// special case: Bezier curve should be a straight line.
if( n == 1 )
{
QPointF cp1, cp2;
QPointF k1 = bezierKnots_.at(0); // knot point 1
QPointF k2 = bezierKnots_.at(1); // knot point 2
cp1.setX( ( 2 * k1.x() + k2.x() ) / 3.0 );
cp1.setY( ( 2 * k1.y() + k2.y() ) / 3.0 );
cp2.setX( ( 2 * cp1.x() - k1.x() ) );
cp2.setY( ( 2 * cp1.y() - k1.y() ) );
bezierControlPoints1_.append( cp1 );
bezierControlPoints2_.append( cp2 );
return; // done!
}
// right hand side vector.
double rhs[n];
// set RHS x values
for( int i = 1; i < n-1; i++ )
{
rhs[i] = 4 * bezierKnots_[i].x() + 2 * bezierKnots_[i+1].x();
}
rhs[0] = bezierKnots_[0].x() + 2 * bezierKnots_[1].x();
rhs[n-1] = ( 8 * bezierKnots_[n-1].x() + bezierKnots_[n].x() ) / 2.0;
// get the first ctl points x values.
double x[n];
bezierGetFirstControlPoints( rhs, x, n );
// now set RHS y-values.
for(int i = 1; i < n-1; i++ )
{
rhs[i] = 4 * bezierKnots_[i].y() + 2 * bezierKnots_[i+1].y();
}
rhs[0] = bezierKnots_[0].y() + 2 * bezierKnots_[1].y();
rhs[n-1] = ( 8 * bezierKnots_[n-1].y() + bezierKnots_[n].y() ) / 2.0;
double y[n];
bezierGetFirstControlPoints( rhs, y, n );
// now fill the output QList.
for( int i = 0; i < n; i++ )
{
QPointF cp1( x[i], y[i] );
QPointF cp2;
// second ctl point
if ( i < n-1 )
{
cp2 = QPointF( 2 * bezierKnots_[i+1].x() - x[i+1],
2 * bezierKnots_[i+1].y() - y[i+1] );
}
else
{
cp2 = QPointF( ( bezierKnots_[n].x() + x[n-1] ) / 2,
( bezierKnots_[n].y() + y[n-1] ) / 2 );
}
bezierControlPoints1_.append( cp1 );
bezierControlPoints2_.append( cp2 );
}
}
// Solves the system for the first control points.
void Stroke::bezierGetFirstControlPoints( double rhs[], double* xOut, int n )
{
double* x = xOut; // solution vector.
double tmp[n]; // temp workspace.
double b = 2.0;
x[0] = rhs[0] / b;
for( int i = 1; i < n; i++ ) // decomposition and forward substitution
{
tmp[i] = 1 / b;
b = ( i < n - 1 ? 4.0 : 3.5 ) - tmp[i];
x[i] = (rhs[i] - x[i-1]) / b;
}
for( int i = 1; i < n; i++ )
{
x[n-i-1] -= tmp[n-i] * x[n-i]; // back substitution.
}
// results are in xOut.
}
/**
* Returns the rectangle which contains this stroke.
*
* @return Rectangle
*/
QRect Stroke::boundingRect() const
{
return boundingRect_;
}
QColor Stroke::color() const
{
return color_;
}
/**
* Apply the changes to the stroke.
*
* Calculating the stroke bounds is complex, so a lazy approach was
* chosen instead of recalculating them for every added point.
*/
void Stroke::finalize()
{
if( finalized_ )
{
return;
}
// A polygon is used to determine the stroke's bounding rect
quint64 numPoints = points_.count();
QPolygon polygon( numPoints );
for( quint64 index = 0; index < numPoints; ++index )
{
polygon.setPoint( index, points_.at( index ).position );
}
// Transform the bounding rect with the current transformation
if( transform_ )
{
polygon = transform_->map( polygon );
}
// Set the bounding rectangle, expanded it to also accommodate pen size
float halfPenSize = penSize_.width() / 2;
boundingRect_ = polygon.boundingRect().adjusted( -( halfPenSize ), -( halfPenSize ),
halfPenSize, halfPenSize );
// Finally, pre-calculate the stroke paths
painterPath();
finalized_ = true;
}
/**
* Get the stroke drawing flags.
*
* @return Stroke flags
*/
StrokeFlags Stroke::flags() const
{
return flags_;
}
/**
* Get whether the stroke contains pressure information.
*
* @return bool
*/
bool Stroke::hasPressureData() const
{
return hasPressureData_;
}
/**
* Get the stroke metrics.
*
* @return Metrics*
*/
Metrics* Stroke::metrics()
{
return metrics_;
}
/**
* Get a painter path to draw this stroke.
*
* The path is adjusted according to the drawing flags.
* Given a list of knot points, generates a QPainterPath that describes the stroke.
*
* If the FitToCurve flag is present, the stroke path is generated using bezier curves
* to approximate the stroke, giving a much smoother appearance.
*
* @see calculateControlPoints()
* @return QPainterPath
*/
QPainterPath Stroke::painterPath()
{
int numPoints = points_.size();
if( numPoints == 0 )
{
return QPainterPath();
}
QPointF startPos( points_.first().position );
QPainterPath path( startPos );
if( ( flags_ & FitToCurve ) == false )
{
foreach( Point point, points_ )
{
path.lineTo( point.position );
}
return path;
}
// don't calculate control points if they've
// already been calculated.
if( bezierKnots_.isEmpty() )
{
bezierCalculateControlPoints();
}
for( int i = 0; i < bezierControlPoints1_.size(); i++ )
{
// draw the bezier curve!
path.cubicTo( bezierControlPoints1_[ i ], bezierControlPoints2_[ i ], bezierKnots_[ i + 1 ] );
}
return path;
}
/**
* Get the current pen size
*
* @return QSizeF of the stroke pen
*/
QSizeF Stroke::penSize() const
{
return penSize_;
}
/**
* Get the list of points
*
* @return List of stroke points
*/
PointList& Stroke::points()
{
return points_;
}
/**
* Change pen color
*
* @param newColor new pen color
*/
void Stroke::setColor( QColor newColor )
{
color_ = newColor;
}
/**
* Change a flag
*
* @param flag The flag to alter
* @param set If true, the flag will be set. If false, it will be unset.
*/
void Stroke::setFlag( StrokeFlag flag, bool set )
{
if( set )
{
flags_ |= flag;
}
else
{
flags_ ^= flag;
}
}
/**
* Change stroke flags all at once.
*
* @param newFlags Flags bitfield
*/
void Stroke::setFlags( StrokeFlags newFlags )
{
flags_ = newFlags;
}
/**
* Get the current pen size
*
* @param newMetrics The new metrics object
*/
void Stroke::setMetrics( Metrics* newMetrics )
{
metrics_ = newMetrics;
}
/**
* Get the current pen size
*
* @return QSizeF of the stroke pen
*/
void Stroke::setPenSize( QSizeF newSize )
{
penSize_ = newSize;
// The bounding box changes with pen size
finalized_ = false;
}
/**
* Apply a transformation to the stroke.
*
* The stroke doesn't take ownership of the transformation.
*
* @param newTransform Transformation to apply
*/
void Stroke::setTransform( QMatrix* newTransform )
{
transform_ = newTransform;
}
/**
* Get the stroke transformation, if any
*
* @return QMatrix, possibly null
*/
QMatrix* Stroke::transform()
{
return transform_;
}
File diff suppressed because it is too large Load Diff
+21 -25
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -39,11 +37,7 @@ namespace Isf
// Forward declarations
namespace Compress
{
class DataSource;
}
using Compress::DataSource;
class StreamData;
class Drawing;
@@ -57,27 +51,29 @@ namespace Isf
{
public: // Static public methods
static IsfError parseCustomTag( DataSource &source, Drawing &drawing, quint64 tagIndex );
static IsfError parseGuidTable( DataSource &source, Drawing &drawing );
static IsfError parseHiMetricSize( DataSource &source, Drawing &drawing );
static IsfError parseInkSpaceRectangle( DataSource &source, Drawing &drawing );
static IsfError parseAttributeBlock( DataSource &source, Drawing &drawing );
static IsfError parseAttributeTable( DataSource &source, Drawing &drawing );
static IsfError parsePersistentFormat( DataSource &source, Drawing &drawing );
static IsfError parseMetricBlock( DataSource &source, Drawing &drawing );
static IsfError parseMetricTable( DataSource &source, Drawing &drawing );
static IsfError parseTransformation( DataSource &source, Drawing &drawing, quint64 transformType );
static IsfError parseTransformationTable( DataSource &source, Drawing &drawing );
static IsfError parseStroke( DataSource &source, Drawing &drawing );
static IsfError parseStrokeDescBlock( DataSource &source, Drawing &drawing );
static IsfError parseStrokeDescTable( DataSource &source, Drawing &drawing );
static IsfError nextTag( StreamData* streamData, Drawing* drawing );
static IsfError parseCustomTag( StreamData* streamData, Drawing* drawing, quint64 tagIndex );
static IsfError parseGuidTable( StreamData* streamData, Drawing* drawing );
static IsfError parseHiMetricSize( StreamData* streamData, Drawing* drawing );
static IsfError parseInkSpaceRectangle( StreamData* streamData, Drawing* drawing );
static IsfError parseAttributeBlock( StreamData* streamData, Drawing* drawing );
static IsfError parseAttributeTable( StreamData* streamData, Drawing* drawing );
static IsfError parsePersistentFormat( StreamData* streamData, Drawing* drawing );
static IsfError parseMetricBlock( StreamData* streamData, Drawing* drawing );
static IsfError parseMetricTable( StreamData* streamData, Drawing* drawing );
static IsfError parseTransformation( StreamData* streamData, Drawing* drawing, quint64 transformType );
static IsfError parseTransformationTable( StreamData* streamData, Drawing* drawing );
static IsfError parseStroke( StreamData* streamData, Drawing* drawing );
static IsfError parseStrokeDescBlock( StreamData* streamData, Drawing* drawing );
static IsfError parseStrokeDescTable( StreamData* streamData, Drawing* drawing );
public: // Static public debugging methods
static IsfError parseUnsupported( DataSource &source, const QString &tagName );
static IsfError parseUnsupported( StreamData* streamData, const QString& tagName );
private: // Static private debugging methods
static QByteArray analyzePayload( DataSource &source, const QString &tagName );
static QByteArray analyzePayload( DataSource &source, const quint64 payloadSize, const QString &message = QString() );
static QByteArray analyzePayload( StreamData* streamData, const QString& tagName );
static QByteArray analyzePayload( StreamData* streamData, const quint64 payloadSize, const QString& message = QString() );
};
}
+176 -84
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -46,7 +44,7 @@ using namespace Isf::Compress;
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addPersistentFormat( StreamData* streamData, const Drawing* drawing )
{
Q_UNUSED( drawing );
@@ -57,7 +55,7 @@ IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &dra
tagContents.prepend( encodeUInt( tagContents.size() ) );
tagContents.prepend( encodeUInt( TAG_PERSISTENT_FORMAT ) );
source.append( tagContents );
streamData->dataSource->append( tagContents );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Persistent Format version";
@@ -75,19 +73,20 @@ IsfError TagsWriter::addPersistentFormat( DataSource &source, const Drawing &dra
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addHiMetricSize( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addHiMetricSize( StreamData* streamData, const Drawing* drawing )
{
QByteArray tagContents;
tagContents.append( encodeInt( drawing.size_.width () ) );
tagContents.append( encodeInt( drawing.size_.height() ) );
QPoint size( drawing->boundingRect().bottomRight() );
tagContents.append( encodeInt( size.x() ) );
tagContents.append( encodeInt( size.y() ) );
encodeUInt( source, TAG_HIMETRIC_SIZE );
encodeUInt( source, tagContents.size() );
source.append( tagContents );
encodeUInt( streamData->dataSource, TAG_HIMETRIC_SIZE );
encodeUInt( streamData->dataSource, tagContents.size() );
streamData->dataSource->append( tagContents );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Added drawing dimensions:" << drawing.size_;
qDebug() << "- Added drawing dimensions:" << size;
#endif
return ISF_ERROR_NONE;
@@ -105,68 +104,85 @@ IsfError TagsWriter::addHiMetricSize( DataSource &source, const Drawing &drawing
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addAttributeTable( StreamData* streamData, const Drawing* drawing )
{
Q_UNUSED( drawing );
QByteArray blockData;
QByteArray tagContents;
AttributeSet defaultAttributeSet;
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Adding" << drawing.attributeSets_.count() << "attributes...";
quint8 counter = 0;
#endif
foreach( const AttributeSet *info, drawing.attributeSets_ )
// Add default attributes if the drawing didn't contain any
if( streamData->attributeSets.isEmpty() )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Adding a default attribute set...";
#endif
AttributeSet set;
streamData->attributeSets.append( set );
}
#ifdef ISFQT_DEBUG_VERBOSE
else
{
qDebug() << "- Adding" << streamData->attributeSets.count() << "attributes...";
}
#endif
foreach( const AttributeSet set, streamData->attributeSets )
{
// Add the color to the attribute block
if( info->color != defaultAttributeSet.color )
if( set.color != defaultAttributeSet.color )
{
blockData.append( encodeUInt( GUID_COLORREF ) );
// Prepare the color value, it needs to be stored in BGR format,
// in the 24 least significant bits
quint64 value = ( info->color.blue () << 16 )
| ( info->color.green() << 8 )
| ( info->color.red () << 0 );
quint64 value = ( set.color.blue () << 16 )
| ( set.color.green() << 8 )
| ( set.color.red () << 0 );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Color:" << info->color.name();
qDebug() << " - Color:" << set.color.name();
#endif
blockData.append( encodeUInt( value ) );
// Add the transparency if needed
if( info->color.alpha() < 255 )
if( set.color.alpha() < 255 )
{
blockData.append( encodeUInt( GUID_TRANSPARENCY ) );
blockData.append( encodeUInt( info->color.alpha() ) );
blockData.append( encodeUInt( set.color.alpha() ) );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Alpha:" << info->color.alpha();
qDebug() << " - Alpha:" << set.color.alpha();
#endif
}
}
// Add the pen size
if( info->penSize != defaultAttributeSet.penSize )
if( set.penSize != defaultAttributeSet.penSize )
{
blockData.append( encodeUInt( GUID_PEN_WIDTH ) );
blockData.append( encodeUInt( info->penSize.width() * HiMetricToPixel ) );
blockData.append( encodeUInt( set.penSize.width() * HiMetricToPixel ) );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Pen width:" << ( info->penSize.width() * HiMetricToPixel );
qDebug() << " - Pen width:" << ( set.penSize.width() * HiMetricToPixel );
#endif
if( info->penSize.width() != info->penSize.height() )
if( set.penSize.width() != set.penSize.height() )
{
blockData.append( encodeUInt( GUID_PEN_HEIGHT ) );
blockData.append( encodeUInt( info->penSize.height() * HiMetricToPixel ) );
blockData.append( encodeUInt( set.penSize.height() * HiMetricToPixel ) );
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Pen height:" << ( info->penSize.height() * HiMetricToPixel );
qDebug() << " - Pen height:" << ( set.penSize.height() * HiMetricToPixel );
#endif
}
}
// Add the other drawing flags
if( info->flags != defaultAttributeSet.flags )
if( set.flags != defaultAttributeSet.flags )
{
StrokeFlags flags = info->flags;
StrokeFlags flags = set.flags;
if( flags & IsRectangle )
{
blockData.append( encodeUInt( GUID_PEN_TIP ) );
@@ -185,9 +201,6 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
}
*/
// Add FitToCurve too for now, as a test
flags |= FitToCurve;
// Copy the other flags as they are
blockData.append( encodeUInt( GUID_DRAWING_FLAGS ) );
blockData.append( encodeUInt( flags ) );
@@ -207,7 +220,7 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
#endif
}
if( drawing.attributeSets_.count() > 1 )
if( streamData->attributeSets.count() > 1 )
{
tagContents.prepend( encodeUInt( tagContents.size() ) );
tagContents.prepend( encodeUInt( TAG_DRAW_ATTRS_TABLE ) );
@@ -217,7 +230,7 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
tagContents.prepend( encodeUInt( TAG_DRAW_ATTRS_BLOCK ) );
}
source.append( tagContents );
streamData->dataSource->append( tagContents );
return ISF_ERROR_NONE;
}
@@ -234,27 +247,29 @@ IsfError TagsWriter::addAttributeTable( DataSource &source, const Drawing &drawi
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addMetricsTable( StreamData* streamData, const Drawing* drawing )
{
Q_UNUSED( drawing );
QByteArray metricData;
QByteArray metricBlockData;
QByteArray tagData;
Metrics defaultMetrics;
Metric *defaultMetric;
Metric* defaultMetric;
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Adding" << drawing.metrics_.count() << "metrics...";
qDebug() << "- Adding" << streamData->metrics.count() << "metrics...";
quint8 counter = 0;
#endif
foreach( const Metrics *metrics, drawing.metrics_ )
foreach( const Metrics* metrics, streamData->metrics )
{
QMapIterator<int,Metric> it( metrics->items );
while( it.hasNext() )
{
it.next();
const quint64 &property = it.key ();
const Metric &metric = it.value();
const quint64& property = it.key ();
const Metric& metric = it.value();
// Skip metrics which are set to the default
defaultMetric = &defaultMetrics.items[ property ];
@@ -293,17 +308,17 @@ IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing
#endif
}
if( drawing.metrics_.count() > 1 )
if( streamData->metrics.count() > 1 )
{
tagData.prepend( encodeUInt( TAG_METRIC_TABLE ) );
}
else if ( drawing.metrics_.count() == 1 )
else if ( streamData->metrics.count() == 1 )
{
tagData.prepend( encodeUInt( TAG_METRIC_BLOCK ) );
}
// else: don't do anything.
source.append( tagData );
streamData->dataSource->append( tagData );
return ISF_ERROR_NONE;
}
@@ -320,8 +335,10 @@ IsfError TagsWriter::addMetricsTable( DataSource &source, const Drawing &drawing
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addTransformationTable( StreamData* streamData, const Drawing* drawing )
{
Q_UNUSED( drawing );
QByteArray blockData;
QByteArray tagContents;
quint64 transformTag;
@@ -337,11 +354,11 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
*/
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Adding" << drawing.transforms_.count() << "transformations...";
qDebug() << "- Adding" << streamData->transforms.count() << "transformations...";
quint8 counter = 0;
#endif
foreach( const QMatrix *trans, drawing.transforms_ )
foreach( const QMatrix* trans, streamData->transforms )
{
/*
* All transforms are written backwards because they're stored my most
@@ -443,24 +460,27 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
}
if ( drawing.transforms_.size() == 0 )
if ( streamData->transforms.size() == 0 )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Added default transformation";
#endif
// write the default transform.
const QMatrix *transform = &drawing.defaultTransform_;
// Write the default transform
QMatrix defaultTransform;
defaultTransform.scale( 1.f, 1.f );
defaultTransform.translate( .0f, .0f );
tagContents.append( TAG_TRANSFORM_ISOTROPIC_SCALE );
tagContents.append( encodeFloat( transform->m11() * HiMetricToPixel ) );
tagContents.append( encodeFloat( defaultTransform.m11() * HiMetricToPixel ) );
}
else if ( drawing.transforms_.size() > 1 )
else if ( streamData->transforms.size() > 1 )
{
tagContents.prepend( encodeUInt( tagContents.size() ) );
tagContents.prepend( encodeUInt( TAG_TRANSFORM_TABLE ) );
}
source.append( tagContents );
streamData->dataSource->append( tagContents );
return ISF_ERROR_NONE;
}
@@ -474,76 +494,75 @@ IsfError TagsWriter::addTransformationTable( DataSource &source, const Drawing &
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
IsfError TagsWriter::addStrokes( StreamData* streamData, const Drawing* drawing )
{
QByteArray blockData;
QByteArray tagContents;
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Adding" << drawing.strokes_.count() << "strokes...";
qDebug() << "- Adding" << drawing->strokes_.count() << "strokes...";
quint8 counter = 0;
#endif
// Last set of attibutes applied to a stroke
Metrics *currentMetrics = 0;
AttributeSet *currentAttributeSet = 0;
QMatrix *currentTransform = 0;
AttributeSet currentAttributeSet;
const Metrics* currentMetrics = 0;
const QMatrix* currentTransform = 0;
foreach( const Stroke *stroke, drawing.strokes_ )
foreach( Stroke* stroke, drawing->strokes_ )
{
// There is more than one set of metrics, assign each stroke to its own
if( drawing.metrics_.count() > 1 )
if( streamData->metrics.count() > 1 )
{
// Make sure that the first strokes use the first metrics list (write a MIDX only
// when needed)
if( currentMetrics == 0 )
{
currentMetrics = drawing.metrics_.first();
currentMetrics = streamData->metrics.first();
}
// Only write a MIDX if this stroke needs different metrics than the last stroke
if( currentMetrics != stroke->metrics && stroke->metrics != 0 )
Metrics* metrics = stroke->metrics();
if( metrics && currentMetrics != metrics )
{
currentMetrics = stroke->metrics;
currentMetrics = metrics;
blockData.append( encodeUInt( TAG_MIDX ) );
blockData.append( encodeUInt( drawing.metrics_.indexOf( stroke->metrics ) ) );
blockData.append( encodeUInt( streamData->metrics.indexOf( metrics ) ) );
}
}
// There is more than one set of attributes, assign each stroke to its own
if( drawing.attributeSets_.count() > 1 )
if( streamData->attributeSets.count() > 1 )
{
// Make sure that the first strokes use the first attribute set (write a DIDX only
// when needed)
if( currentAttributeSet == 0 )
{
currentAttributeSet = drawing.attributeSets_.first();
}
// Only write a DIDX if this stroke needs a different attribute set than the last stroke
if( currentAttributeSet != stroke->attributes && stroke->attributes != 0 )
if( currentAttributeSet.color != stroke->color()
|| currentAttributeSet.flags != stroke->flags()
|| currentAttributeSet.penSize != stroke->penSize() )
{
currentAttributeSet = stroke->attributes;
currentAttributeSet.color = stroke->color();
currentAttributeSet.flags = stroke->flags();
currentAttributeSet.penSize = stroke->penSize();
blockData.append( encodeUInt( TAG_DIDX ) );
blockData.append( encodeUInt( drawing.attributeSets_.indexOf( stroke->attributes ) ) );
blockData.append( encodeUInt( streamData->attributeSets.indexOf( currentAttributeSet ) ) );
}
}
// Make sure that the first strokes use the first transform (write a TIDX only
// when needed)
if ( drawing.transforms_.count() > 0 )
if ( streamData->transforms.count() > 0 )
{
if( currentTransform == 0 )
{
currentTransform = drawing.transforms_.first();
currentTransform = streamData->transforms.first();
}
// Only write a TIDX if this stroke needs a different transform than the last stroke
if( currentTransform != stroke->transform && stroke->transform != 0 )
if( currentTransform != stroke->transform() && stroke->transform() != 0 )
{
currentTransform = stroke->transform;
currentTransform = stroke->transform();
blockData.append( encodeUInt( TAG_TIDX ) );
blockData.append( encodeUInt( drawing.transforms_.indexOf( stroke->transform ) ) );
blockData.append( encodeUInt( streamData->transforms.indexOf( stroke->transform() ) ) );
}
}
@@ -557,7 +576,7 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
// Write this stroke in the stream
QList<qint64> xPoints, yPoints;
foreach( const Point &point, stroke->points )
foreach( const Point& point, stroke->points() )
{
xPoints.append( point.position.x() );
yPoints.append( point.position.y() );
@@ -568,7 +587,7 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
// The stroke is made by tag, then payload size, then number of points, then
// the compressed points data
blockData.prepend( encodeUInt( stroke->points.count() ) );
blockData.prepend( encodeUInt( stroke->points().count() ) );
blockData.prepend( encodeUInt( blockData.size() ) );
blockData.prepend( encodeUInt( TAG_STROKE ) );
@@ -580,7 +599,80 @@ IsfError TagsWriter::addStrokes( DataSource &source, const Drawing &drawing )
#endif
}
source.append( tagContents );
streamData->dataSource->append( tagContents );
return ISF_ERROR_NONE;
}
/**
* Prepare the stream data for writing.
*
* @param source Data Source where to write bytes to
* @param drawing Drawing from which to obtain the data to write
* @return IsfError
*/
IsfError TagsWriter::prepare( StreamData* streamData, const Drawing* drawing )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Optimizing data...";
#endif
streamData->attributeSets.clear();
streamData->metrics.clear();
streamData->transforms.clear();
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - " << drawing->strokes_.count() << "strokes to optimize";
#endif
// Prepare the list of attributes
foreach( Stroke* stroke, drawing->strokes_ )
{
AttributeSet set;
set.color = stroke->color();
set.flags = stroke->flags();
set.penSize = stroke->penSize();
Metrics* metrics = stroke->metrics();
QMatrix* transform = stroke->transform();
if( ! streamData->attributeSets.contains( set ) )
{
streamData->attributeSets.append( set );
}
if( metrics && ! streamData->metrics.contains( metrics ) )
{
streamData->metrics.append( metrics );
}
if( transform && ! streamData->transforms.contains( transform ) )
{
streamData->transforms.append( transform );
}
}
#ifdef ISFQT_DEBUG_VERBOSE
int count = 0;
#endif
// Add default elements if the drawing didn't contain any
if( streamData->attributeSets.isEmpty() )
{
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Added " << count << "default elements";
#endif
AttributeSet set;
streamData->attributeSets.append( set );
}
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << " - Added " << count << "default elements";
#endif
#ifdef ISFQT_DEBUG_VERBOSE
qDebug() << "- Optimization phase complete";
#endif
return ISF_ERROR_NONE;
}
+8 -10
View File
@@ -4,9 +4,7 @@
* *
* Copyright (C) 2009 by Adam Goossens *
* adam@kmess.org *
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of the *
@@ -52,13 +50,13 @@ namespace Isf
class TagsWriter
{
public: // Static public methods
static IsfError addPersistentFormat( DataSource &source, const Drawing &drawing );
static IsfError addHiMetricSize( DataSource &source, const Drawing &drawing );
static IsfError addAttributeTable( DataSource &source, const Drawing &drawing );
static IsfError addMetricsTable( DataSource &source, const Drawing &drawing );
static IsfError addTransformationTable( DataSource &source, const Drawing &drawing );
static IsfError addStrokes( DataSource &source, const Drawing &drawing );
static IsfError addPersistentFormat( StreamData* streamData, const Drawing* drawing );
static IsfError addHiMetricSize( StreamData* streamData, const Drawing* drawing );
static IsfError addAttributeTable( StreamData* streamData, const Drawing* drawing );
static IsfError addMetricsTable( StreamData* streamData, const Drawing* drawing );
static IsfError addTransformationTable( StreamData* streamData, const Drawing* drawing );
static IsfError addStrokes( StreamData* streamData, const Drawing* drawing );
static IsfError prepare( StreamData* streamData, const Drawing* drawing );
};
}
+2 -1
View File
@@ -7,7 +7,7 @@ MACRO( add_multiple_tests )
QT4_AUTOMOC( test_${test}.cpp )
ADD_EXECUTABLE( test_${test} test_${test}.cpp )
ADD_TEST( libisf-${test} test_${test} )
TARGET_LINK_LIBRARIES( test_${test} ${QT_QTTEST_LIBRARY} ${QT_QTCORE_LIBRARY} isf-qt )
TARGET_LINK_LIBRARIES( test_${test} ${QT_QTTEST_LIBRARY} ${QT_QTGUI_LIBRARY} isf-qt )
ENDFOREACH( test )
ENDMACRO( add_multiple_tests )
@@ -15,6 +15,7 @@ ADD_MULTIPLE_TESTS(
isfdrawing
multibyte_coding
algorithms
png_fortification
)
+2 -2
View File
@@ -130,7 +130,7 @@ class TestDecode : public QMainWindow, private Ui::TestDecode
// read some test raw ISF data from a file on the filesystem and
// return it as a QByteArray.
QByteArray readTestIsfData( const QString &filename )
QByteArray readTestIsfData( const QString& filename )
{
QFile file( filename );
if ( !file.exists() )
@@ -154,7 +154,7 @@ class TestDecode : public QMainWindow, private Ui::TestDecode
// read some test raw ISF data from a file on the filesystem and
// return it as a QByteArray.
void saveTestIsfData( const QByteArray &data )
void saveTestIsfData( const QByteArray& data )
{
static int number = 1;
QString fileName( "test" + QString::number( number ) + "." );
+28 -17
View File
@@ -33,6 +33,7 @@
#include <QDataStream>
#include <QTextStream>
#include <QFile>
#include <QTimer>
#include <IsfInkCanvas>
@@ -46,22 +47,24 @@ TestInkEdit::TestInkEdit()
connect( cmdSave_, SIGNAL(clicked()), this, SLOT( saveInk() ) );
connect( cmdLoad_, SIGNAL(clicked()), this, SLOT( loadInk() ) );
connect( cmdClear_, SIGNAL(clicked()), this, SLOT( clearInk() ) );
connect( cmdStrokeColor_, SIGNAL(clicked()), this, SLOT( chooseColor() ) );
connect( cmdCanvasColor_, SIGNAL(clicked()), this, SLOT( chooseColor() ) );
connect( editor_, SIGNAL(inkChanged()), this, SLOT( inkChanged() ) );
QButtonGroup *grp = new QButtonGroup( this );
grp->addButton( rbDrawing_ );
grp->addButton( rbEraser_ );
connect( grp, SIGNAL( buttonClicked( QAbstractButton * ) ), this, SLOT( penTypeChanged( QAbstractButton * ) ) );
connect( spinWidth_, SIGNAL( valueChanged( int ) ), editor_, SLOT( setPenSize( int ) ) );
editor_->setPenSize( spinWidth_->value() );
/*
setWindowTitle("Ink Edit Test");
editor_ = new Isf::InkEdit();
editor_->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
@@ -72,29 +75,29 @@ TestInkEdit::TestInkEdit()
cmdSave_ = new QPushButton();
cmdSave_->setText( "Save Ink" );
connect( cmdSave_, SIGNAL(clicked()), this, SLOT( saveInk() ) );
cmdLoad_ = new QPushButton();
cmdLoad_->setText( "Load Ink" );
connect( cmdLoad_, SIGNAL(clicked()), this, SLOT( loadInk() ) );
QPushButton *cmdClear_ = new QPushButton();
cmdClear_->setText( "Clear Ink" );
connect( cmdClear_, SIGNAL(clicked()), this, SLOT( clearInk() ) );
QVBoxLayout *layout = new QVBoxLayout();
QHBoxLayout *strokeBtnLayout = new QHBoxLayout();
layout->addWidget( sayLabel_ );
layout->addWidget( editor_ );
QHBoxLayout *ctlBtnLayout = new QHBoxLayout();
ctlBtnLayout->addWidget(cmdSave_);
ctlBtnLayout->addWidget(cmdLoad_);
ctlBtnLayout->addWidget(cmdClear_);
layout->addLayout( ctlBtnLayout );
setLayout( layout );
*/
}
@@ -135,7 +138,7 @@ void TestInkEdit::saveInk()
{
QString filter;
QString saveFile = QFileDialog::getSaveFileName( this, "Save Ink", QString(), "Raw ISF (*.isf);;base64-encoded ISF (*.isf64)", &filter );
if ( saveFile != QString() )
if ( saveFile != QString() )
{
QFile file(saveFile);
file.open(QIODevice::WriteOnly);
@@ -148,18 +151,18 @@ void TestInkEdit::saveInk()
{
editor_->save( file );
}
file.close();
QMessageBox::information(0, "Save complete", "Saved to " + saveFile );
}
}
void TestInkEdit::loadInk()
void TestInkEdit::loadInk()
{
QString filter;
QString filename = QFileDialog::getOpenFileName( this, "Open Ink", QString(), "Raw ISF (*.isf);;base64-encoded ISF (*.isf64)", &filter );
if ( ! filename.isEmpty() )
if ( ! filename.isEmpty() )
{
QFile file(filename);
file.open(QIODevice::ReadOnly);
@@ -170,7 +173,7 @@ void TestInkEdit::loadInk()
// got some ink.
Isf::Drawing *drawing = &Isf::Stream::reader(data);
editor_->setDrawing( drawing );
editor_->updateGeometry();
@@ -182,12 +185,20 @@ void TestInkEdit::clearInk()
editor_->clear();
}
void TestInkEdit::inkChanged()
{
emptyDrawingCheckbox_->setChecked( editor_->isEmpty() );
statusLabel_->setText( "Drawing changed!" );
QTimer::singleShot( 3000, statusLabel_, SLOT(clear()) );
}
int main( int argc, char **argv )
{
QApplication app( argc, argv );
TestInkEdit edit;
edit.show();
return app.exec();
}
+5 -4
View File
@@ -40,19 +40,20 @@
class TestInkEdit : public QWidget, public Ui::TestInkEdit
{
Q_OBJECT
public:
TestInkEdit();
~TestInkEdit();
public slots:
void saveInk();
void loadInk();
void clearInk();
void penTypeChanged( QAbstractButton *button );
void chooseColor();
void inkChanged();
};
@@ -130,6 +130,9 @@ p, li { white-space: pre-wrap; }
<property name="text">
<string>Drawing</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
@@ -142,6 +145,19 @@ p, li { white-space: pre-wrap; }
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="emptyDrawingCheckbox_">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Is empty?</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@@ -161,6 +177,9 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="statusLabel_"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
+1 -1
View File
@@ -116,7 +116,7 @@ void TestIsfDrawing::createDrawing()
// read some test raw ISF data from a file on the filesystem and
// return it as a QByteArray.
void TestIsfDrawing::readTestIsfData( const QString &filename, QByteArray &byteArray )
void TestIsfDrawing::readTestIsfData( const QString& filename, QByteArray& byteArray )
{
QFile file( filename );
QVERIFY( file.exists() );
+1 -1
View File
@@ -23,7 +23,7 @@ class TestIsfDrawing : public QObject
Q_OBJECT
public:
TestIsfDrawing();
void readTestIsfData( const QString &filename, QByteArray &byteArray );
void readTestIsfData( const QString& filename, QByteArray& byteArray );
private slots:
void emptyConstructor_NullDrawing();
@@ -138,7 +138,7 @@ void TestMultibyteCoding::unsignedDecode()
data.append( Q_UINT64_C(0x7D) ); // decimal 125
data.reset(); // To re-read the appended bytes
result = Isf::Compress::decodeUInt( data );
result = Isf::Compress::decodeUInt( &data );
QVERIFY(result == Q_UINT64_C(0x7D) );
@@ -150,7 +150,7 @@ void TestMultibyteCoding::unsignedDecode()
data.append( Q_UINT64_C(0x01) );
data.reset(); // To re-read the appended bytes
result = Isf::Compress::decodeUInt( data );
result = Isf::Compress::decodeUInt( &data );
QVERIFY( result == Q_UINT64_C(0x80) );
data.clear();
@@ -162,7 +162,7 @@ void TestMultibyteCoding::unsignedDecode()
data.append( Q_UINT64_C(0x03) );
data.reset(); // To re-read the appended bytes
result = Isf::Compress::decodeUInt( data );
result = Isf::Compress::decodeUInt( &data );
QVERIFY( result == Q_UINT64_C(0xFFFF) );
}
@@ -189,7 +189,7 @@ void TestMultibyteCoding::signedDecode()
data.append( (char)((0x0A << 1) | 0x01) );
data.reset(); // To re-read the appended byte
result = Isf::Compress::decodeInt( data );
result = Isf::Compress::decodeInt( &data );
QVERIFY( result == Q_INT64_C(-10) );
data.clear();
@@ -200,7 +200,7 @@ void TestMultibyteCoding::signedDecode()
data.append( Q_INT64_C(0x01) );
data.reset(); // To re-read the appended byte
result = Isf::Compress::decodeInt( data );
result = Isf::Compress::decodeInt( &data );
QVERIFY( result == Q_INT64_C(-64) );
data.clear();
@@ -211,7 +211,7 @@ void TestMultibyteCoding::signedDecode()
data.append( Q_INT64_C(0x01) );
data.reset(); // To re-read the appended byte
result = Isf::Compress::decodeInt( data );
result = Isf::Compress::decodeInt( &data );
QVERIFY( result == Q_INT64_C(100) );
data.clear();
@@ -222,7 +222,7 @@ void TestMultibyteCoding::signedDecode()
data.append( Q_INT64_C(0x07) );
data.reset(); // To re-read the appended byte
result = Isf::Compress::decodeInt( data );
result = Isf::Compress::decodeInt( &data );
QVERIFY( result == Q_INT64_C(-500) );
}
@@ -254,7 +254,7 @@ void TestMultibyteCoding::floatDecode()
data.append( Q_INT64_C(0xC1) );
data.reset(); // To re-read the appended bytes
result = Isf::Compress::decodeFloat( data );
result = Isf::Compress::decodeFloat( &data );
QVERIFY( result == -12.345678901f );
}
@@ -0,0 +1,90 @@
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.*/
#include "test_png_fortification.h"
#include <IsfQtDrawing>
#include "isfqt-internal.h"
#include <QtTest/QtTest>
#include <QPixmap>
using namespace Isf;
using namespace Isf::Compress;
void TestPngFortification::testEncode()
{
QPixmap pix( QSize( 135, 114 ) );
pix.fill( Qt::transparent );
qDebug() << "pix size:" << pix.size();
qDebug() << "#################### ENCODER TEST ####################";
QFile file( "../../tests/test2.isf" );
QVERIFY( file.exists() );
// read file into qbytearray.
QVERIFY( file.open( QIODevice::ReadOnly ) );
Drawing drawing = Stream::reader( file.readAll(), false );
QVERIFY( ! drawing.isNull() );
QByteArray byteArray( Stream::writerPng( drawing, false ) );
QVERIFY( ! byteArray.isEmpty() );
QImage img = QImage::fromData( byteArray, "PNG" );
QVERIFY( ! img.isNull() );
qDebug() << "Image size:" << img.size();
QVERIFY( tempFile.open() );
tempFile.write( byteArray );
tempFile.close();
}
void TestPngFortification::testDecode()
{
qDebug() << "#################### DECODER TEST ####################";
QVERIFY( tempFile.exists() );
// read file and convert to qbytearray.
QVERIFY( tempFile.open() );
QByteArray byteArray( tempFile.readAll() );
Drawing drawing = Stream::readerPng( byteArray, false );
QVERIFY( ! drawing.isNull() );
qDebug() << "Drawing size:" << drawing.size();
}
QTEST_MAIN(TestPngFortification)
#include "test_png_fortification.moc"
@@ -0,0 +1,36 @@
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.*/
#ifndef TESTPNG_FORTIFICATION_H
#define TESTPNG_FORTIFICATION_H
#include <QtCore/QObject>
#include <QtCore/QTemporaryFile>
class TestPngFortification : public QObject
{
Q_OBJECT
private slots:
void testEncode();
void testDecode();
private:
QTemporaryFile tempFile;
};
#endif // TESTPNG_FORTIFICATION_H
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Classic-compact.xsl Classic-compact.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Classic-compact/ )
install(
FILES
Classic-compact.xsl
Classic-compact.css
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Classic-compact/
)
@@ -67,6 +67,19 @@ div.conversation
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
/**
* Remaining markup is done inline in the .xsl file.
@@ -27,6 +27,36 @@
omit-xml-declaration="yes"
encoding="utf-8" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div style="margin:2em;padding:.5em;border:1px solid #dce6ff;font-size:larger;color:purple;text-align:center;" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Normal chat message.
This is used to process individual chat messages.
+7 -1
View File
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Classic.xsl Classic.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Classic/ )
install(
FILES
Classic.xsl
Classic.css
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Classic/
)
+13
View File
@@ -67,6 +67,19 @@ div.conversation
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
/**
* Remaining markup is done inline in the .xsl file.
*/
+30
View File
@@ -27,6 +27,36 @@
indent="no"
omit-xml-declaration="yes" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div style="margin:2em;padding:.5em;border:1px solid #dce6ff;font-size:larger;color:purple;text-align:center;" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Normal chat message.
This is used to process individual chat messages.
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Colourful-Enclosed.xsl Colourful-Enclosed.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Colourful-Enclosed/ )
install(
FILES
Colourful-Enclosed.xsl
Colourful-Enclosed.css
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Colourful-Enclosed/
)
@@ -214,3 +214,16 @@ div.conversation
color: purple;
text-align: center;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
@@ -38,6 +38,16 @@
<xsl:param name="csspath" select="'Colourful-Enclosed.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -68,6 +78,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
+7 -1
View File
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Dim.xsl Dim.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Dim/ )
install(
FILES
Dim.xsl
Dim.css
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Dim/
)
+15
View File
@@ -200,3 +200,18 @@ div.conversation
margin-bottom: 1em;
color: purple;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
+28
View File
@@ -38,6 +38,16 @@
<xsl:param name="csspath" select="'Dim.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -68,6 +78,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
-->
+7 -1
View File
@@ -4,5 +4,11 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Efficient.xsl Efficient.css DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Efficient/ )
install(
FILES
Efficient.xsl
Efficient.css
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Efficient/
)
+16
View File
@@ -271,3 +271,19 @@ div.conversation
font-size: larger;
color: purple;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
+28
View File
@@ -38,6 +38,16 @@
<xsl:param name="csspath" select="'Efficient.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -68,6 +78,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
-->
+13 -1
View File
@@ -4,5 +4,17 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Fresh-dark.xsl Fresh-dark.css bg_gravatar.gif bg_gravatar_rtl.gif buddy_icon.png DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Fresh-dark/ )
install(
FILES
Fresh-dark.xsl
Fresh-dark.css
bg_gravatar.gif
bg_gravatar_rtl.gif
bg_gravatar_gray.gif
bg_gravatar_gray_rtl.gif
buddy_icon.png
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Fresh-dark/
)
+25
View File
@@ -300,3 +300,28 @@ div.conversation
font-size: larger;
color: #bb0;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
.history .avatar
{
background-image: url("bg_gravatar_gray.gif");
}
.history .rtl .avatar
{
background-image: url("bg_gravatar_gray_rtl.gif");
}
+28
View File
@@ -39,6 +39,16 @@
<xsl:param name="csspath" select="'Fresh-dark.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -69,6 +79,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
-->
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.
+12 -1
View File
@@ -4,5 +4,16 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
install( FILES Fresh.xsl Fresh.css bg_gravatar.gif bg_gravatar_rtl.gif buddy_icon.png DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Fresh/ )
install(
FILES
Fresh.xsl
Fresh.css
bg_gravatar.gif
bg_gravatar_rtl.gif
bg_gravatar_gray.gif
bg_gravatar_gray_rtl.gif
buddy_icon.png
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Fresh/
)
+24 -1
View File
@@ -52,7 +52,6 @@ dl, dt, dd
position: relative;
}
/*
* general message layout and colors.
*/
@@ -300,3 +299,27 @@ div.conversation
color: purple;
text-align: center;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
.history .avatar
{
background-image: url("bg_gravatar_gray.gif");
}
.history .rtl .avatar
{
background-image: url("bg_gravatar_gray_rtl.gif");
}
+28
View File
@@ -38,6 +38,16 @@
<xsl:param name="csspath" select="'Fresh.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -68,6 +78,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
-->
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+18 -17
View File
@@ -4,21 +4,22 @@ include_directories( ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} )
########### install files ###############
set(kmess_pure_FILES
Pure.css
Pure.xsl
arrow0.png
arrow1.png
clock.png
contact.png
corner-bl.png
corner-br.png
corner-tl.png
corner-tr.png
important.png
myself.png
system.png
)
install( FILES ${kmess_pure_FILES} DESTINATION ${DATA_INSTALL_DIR}/kmess/styles/Pure/ )
install(
FILES
Pure.css
Pure.xsl
arrow0.png
arrow1.png
clock.png
contact.png
corner-bl.png
corner-br.png
corner-tl.png
corner-tr.png
important.png
myself.png
system.png
DESTINATION
${DATA_INSTALL_DIR}/kmess/styles/Pure/
)
+16
View File
@@ -338,3 +338,19 @@ div.conversation
font-size: larger;
color: purple;
}
/*
* Style overrides for chat history messages
*/
.history {
margin-bottom: 3em;
}
.history * {
color: #444;
background-color: transparent;
border: 0;
}
+28
View File
@@ -38,6 +38,16 @@
<xsl:param name="csspath" select="'Pure.css'" />
<!--
Template for the chat history
-->
<xsl:template match="history">
<div class="history">
<xsl:apply-templates />
</div>
</xsl:template>
<!--
Template for the page body
-->
@@ -68,6 +78,24 @@
</html>
</xsl:template>
<!--
Template for conversation headers
-->
<xsl:template match="header">
<div class="{body/@dir}">
<div class="conversation" dir="{body/@dir}">
<div class="conversationLabel" dir="{body/@dir}">
<xsl:text kmess:translate="true"> Conversation time: </xsl:text>
</div>
<div class="conversationDate" dir="{body/@dir}">
<xsl:value-of select="date"/>
<xsl:text> &#160; </xsl:text>
<xsl:value-of select="time"/>
</div>
</div>
</div>
</xsl:template>
<!--
Template for normal messages
-1
View File
@@ -1,5 +1,4 @@
[Desktop Entry]
Encoding=UTF-8
Name=KMess
Exec=kmess -caption "%c" %i
Icon=kmess
+17 -1
View File
@@ -2,6 +2,10 @@
Name=KMess
IconName=kmess
Comment=KMess Messenger Client
# Please note that all the events listed in this file are implemented
# differently; apart from knotify, in the MacNotification class in
# KMess. It can be found in src/notification. If you modify this file,
# please keep that one up to date too.
[Event/contact online]
Name=Contact Online
@@ -45,8 +49,20 @@ Comment=You have received a new email
Sound=kmess_msg.ogg
Action=Sound|Popup|Taskbar
[Event/contact changed]
Name=Contact Changed
Comment=A contact was changed (added, deleted, unblocked, changed group, etc).
Sound=kmess_msg.ogg
Action=Sound|Popup|Taskbar
[Event/group changed]
Name=Group Changed
Comment=A group was changed (added, deleted, renamed).
Sound=kmess_msg.ogg
Action=Sound|Popup|Taskbar
[Event/status]
Name=KMess and Network Status
Comment=Information on network and application status
Sound=KDE-Sys-Special.ogg
Action=Sound|Popup
Action=Sound|Popup
+4 -2
View File
@@ -16,9 +16,11 @@ SET( kmess_PICS
online.png
onthephone.png
unknown.png
contact_food_overlay.png
contact_phone_overlay.png
contact_away_overlay.png
contact_busy_overlay.png
contact_food_overlay.png
contact_invisible_overlay.png
contact_phone_overlay.png
)
INSTALL( FILES ${kmess_PICS} DESTINATION ${DATA_INSTALL_DIR}/kmess/pics )
Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,3 +1,3 @@
[Project]
Name=KMess
Name=KMess (2.0.x branch)
Manager=KDevCMakeManager
-606
View File
@@ -1,606 +0,0 @@
{
<insert a suppression name here>
Memcheck:Param
write(buf)
fun:__write_nocancel
obj:/usr/lib/libICE.so.6.3.0
fun:_IceWrite
fun:IceFlush
fun:_ZL14sm_setPropertyPKcS0_iP11SmPropValue
fun:_ZL14sm_setPropertyRK7QStringS1_
fun:_ZL22sm_performSaveYourselfP22QSessionManagerPrivate
fun:_ZL23sm_saveYourselfCallbackP8_SmcConnPviiii
fun:_SmcProcessMessage
fun:IceProcessMessages
fun:_ZN17QSmSocketReceiver11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_mod_inverse
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:RSA_verify
fun:EVP_VerifyFinal
fun:ASN1_item_verify
obj:/lib/libcrypto.so.0.9.8
fun:X509_verify_cert
fun:ssl_verify_cert_chain
fun:ssl3_get_server_certificate
fun:ssl3_connect
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_div
fun:BN_nnmod
fun:BN_mod_inverse
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:RSA_verify
fun:EVP_VerifyFinal
fun:ASN1_item_verify
obj:/lib/libcrypto.so.0.9.8
fun:X509_verify_cert
fun:ssl_verify_cert_chain
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_div
fun:BN_nnmod
fun:BN_mod_inverse
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:RSA_verify
fun:EVP_VerifyFinal
fun:ASN1_item_verify
obj:/lib/libcrypto.so.0.9.8
fun:X509_verify_cert
fun:ssl_verify_cert_chain
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_mod_inverse
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:ssl3_send_client_key_exchange
fun:ssl3_connect
fun:_ZN24QSslSocketBackendPrivate14testConnectionEv
fun:_ZN24QSslSocketBackendPrivate8transmitEv
fun:_ZN10QSslSocket11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
fun:_ZN22QAbstractSocketPrivate19canReadNotificationEv
fun:_ZN13QReadNotifier5eventEP6QEvent
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_div
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:ssl3_send_client_key_exchange
fun:ssl3_connect
fun:_ZN24QSslSocketBackendPrivate14testConnectionEv
fun:_ZN24QSslSocketBackendPrivate8transmitEv
fun:_ZN10QSslSocket11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
fun:_ZN22QAbstractSocketPrivate19canReadNotificationEv
fun:_ZN13QReadNotifier5eventEP6QEvent
}
{
<insert a suppression name here>
Memcheck:Cond
fun:deflate
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
fun:png_write_row
fun:png_write_image
fun:_ZN15QPNGImageWriter10writeImageERK6QImageiRK7QStringii
fun:_ZN11QPngHandler5writeERK6QImage
fun:_ZN12QImageWriter5writeERK6QImage
fun:_ZlsR11QDataStreamRK6QImage
fun:_ZlsR11QDataStreamRK7QPixmap
fun:_ZN20KNotificationManager6notifyEP13KNotificationRK7QPixmapRK11QStringListRK5QListI5QPairI7QStringSA_EERKSA_
}
{
<insert a suppression name here>
Memcheck:Value8
fun:crc32
obj:/usr/lib/libpng12.so.0.27.0
fun:png_write_chunk_data
fun:png_write_chunk
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
fun:png_write_row
fun:png_write_image
fun:_ZN15QPNGImageWriter10writeImageERK6QImageiRK7QStringii
fun:_ZN11QPngHandler5writeERK6QImage
}
{
<insert a suppression name here>
Memcheck:Value8
fun:crc32
obj:/usr/lib/libpng12.so.0.27.0
fun:png_write_chunk_data
fun:png_write_chunk
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
obj:/usr/lib/libpng12.so.0.27.0
fun:png_write_row
fun:png_write_image
fun:_ZN15QPNGImageWriter10writeImageERK6QImageiRK7QStringii
fun:_ZN11QPngHandler5writeERK6QImage
}
{
<insert a suppression name here>
Memcheck:Param
writev(vector[...])
fun:writev
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
obj:/lib/libdbus-1.so.3.4.0
fun:dbus_connection_send_with_reply
fun:_ZN22QDBusConnectionPrivate18sendWithReplyAsyncERK12QDBusMessagei
fun:_ZN22QDBusConnectionPrivate18sendWithReplyAsyncERK12QDBusMessageP7QObjectPKcS6_i
fun:_ZNK15QDBusConnection16callWithCallbackERK12QDBusMessageP7QObjectPKcS6_i
}
{
<insert a suppression name here>
Memcheck:Param
write(buf)
obj:/lib/libc-2.9.so
obj:/usr/lib/libICE.so.6.3.0
fun:_IceWrite
fun:IceFlush
fun:SmcCloseConnection
fun:_ZN15QSessionManagerD0Ev
fun:_ZN12QApplicationD2Ev
fun:_ZN16KMessApplicationD1Ev
fun:main
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN7QString7reallocEi
fun:_ZN7QString6resizeEi
fun:_ZN7QString8fromUtf8EPKci
fun:_ZL26fromPercentEncodingMutableP10QByteArray
fun:_ZNK11QUrlPrivate5parseENS_12ParseOptionsE
fun:_ZNK4QUrl7isValidEv
fun:_ZN4KUrl14_setEncodedUrlERK10QByteArray
fun:_ZN4KUrlC1ERK7QString
fun:_ZN5khtml6Loader20servePendingRequestsEv
fun:_ZN5khtml19CachedCSSStyleSheetC1EPNS_9DocLoaderERKN3DOM9DOMStringEN3KIO12CacheControlEPKc
fun:_ZN5khtml5Cache13requestObjectINS_19CachedCSSStyleSheetELNS_12CachedObject4TypeE1EEEPT_PNS_9DocLoaderERK4KUrlPKc
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
obj:/usr/lib/libxml2.so.2.6.32
fun:xmlSAX2StartElementNs
obj:/usr/lib/libxml2.so.2.6.32
fun:xmlParseElement
fun:xmlParseContent
fun:xmlParseElement
fun:xmlParseDocument
fun:xmlSAXParseMemoryWithData
fun:_ZN17XslTransformation13setStylesheetERK7QString
fun:_ZN16ChatMessageStyle8setStyleERK7QString
fun:_ZN15ChatMessageView15updateChatStyleEv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwm
fun:_ZN19QDockAreaLayoutInfo12restoreStateER11QDataStreamR5QListIP11QDockWidgetEb
fun:_ZN15QDockAreaLayout12restoreStateER11QDataStreamRK5QListIP11QDockWidgetEb
fun:_ZN22QMainWindowLayoutState11checkFormatER11QDataStreamb
fun:_ZN22QMainWindowLayoutState12restoreStateER11QDataStreamRKS_
fun:_ZN17QMainWindowLayout12restoreStateER11QDataStream
fun:_ZN11QMainWindow12restoreStateERK10QByteArrayi
fun:_ZN11KMainWindow23applyMainWindowSettingsERK12KConfigGroupb
fun:_ZN13KXmlGuiWindow23applyMainWindowSettingsERK12KConfigGroupb
fun:_ZN10ChatWindow10initializeEv
fun:_ZN10ChatMaster16createChatWindowEP4Chat
fun:_ZN10ChatMaster10createChatEP24MsnSwitchboardConnectionb
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN8QMapData11node_createEPPNS_4NodeEi
fun:_ZN4QMapI10QByteArray11QStringListE11node_createEP8QMapDataPPNS3_4NodeERKS0_RKS1_
fun:_ZNK13KStandardDirs12resourceDirsEPKc
fun:_ZN10KIconThemeC1ERK7QStringS2_
fun:_ZN18KIconLoaderPrivate14initIconThemesEv
fun:_ZN11KIconLoader9addAppDirERK7QString
fun:_ZN16KMessApplication15initializePathsEv
fun:_ZN16KMessApplicationC1Ev
fun:main
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
obj:/usr/lib/libxslt.so.1.1.24
fun:xsltParseStylesheetProcess
fun:xsltParseStylesheetImportedDoc
fun:xsltParseStylesheetDoc
fun:_ZN17XslTransformation13setStylesheetERK7QString
fun:_ZN16ChatMessageStyle8setStyleERK7QString
fun:_ZN15ChatMessageView15updateChatStyleEv
fun:_ZN8ChatView10initializeEv
fun:_ZN4Chat10initializeEP24MsnSwitchboardConnection
fun:_ZN10ChatMaster10createChatEP24MsnSwitchboardConnectionb
fun:_ZN10ChatMaster11qt_metacallEN11QMetaObject4CallEiPPv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libexpat.so.1.5.2
obj:/usr/lib/libexpat.so.1.5.2
obj:/usr/lib/libexpat.so.1.5.2
obj:/usr/lib/libexpat.so.1.5.2
fun:XML_ParseBuffer
fun:FcConfigParseAndLoad
fun:FcConfigParseAndLoad
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:nss_parse_service_list
fun:__nss_database_lookup
obj:*
obj:*
fun:getpwuid_r@@GLIBC_2.2.5
fun:_ZL22sm_performSaveYourselfP22QSessionManagerPrivate
fun:_ZL23sm_saveYourselfCallbackP8_SmcConnPviiii
fun:_SmcProcessMessage
fun:IceProcessMessages
fun:_ZN17QSmSocketReceiver11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_XimOpenIM
fun:_XimRegisterIMInstantiateCallback
fun:XRegisterIMInstantiateCallback
fun:_ZN16QXIMInputContextC1Ev
fun:_ZN20QInputContextFactory6createERK7QStringP7QObject
fun:_ZNK12QApplication12inputContextEv
fun:_ZN19QApplicationPrivate14setFocusWidgetEP7QWidgetN2Qt11FocusReasonE
fun:_ZN7QWidget8setFocusEN2Qt11FocusReasonE
fun:_ZN12QApplication15setActiveWindowEP7QWidget
fun:_ZN12QApplication15x11ProcessEventEP7_XEvent
fun:_ZL22x11EventSourceDispatchP8_GSourcePFiPvES1_
}
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwm
fun:_ZN5khtml11RenderStyleC1Eb
fun:_ZN5khtml11RenderStyleC1Ev
fun:_ZN5khtml16CSSStyleSelector21setupDefaultRootStyleEPN3DOM12DocumentImplE
fun:_ZN5khtml16CSSStyleSelectorC1EPN3DOM12DocumentImplE7QStringPNS1_18StyleSheetListImplERK4KUrlb
fun:_ZN3DOM12DocumentImpl6attachEv
fun:_ZN9KHTMLPart5beginERK4KUrlii
fun:_ZN15ChatMessageView7setHtmlERK7QString
fun:_ZN15ChatMessageView9clearViewEb
fun:_ZN15ChatMessageViewC1EP7QWidget
fun:_ZN8ChatViewC2EP7QWidget
fun:_ZN4ChatC1EP7QWidget
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:CRYPTO_malloc
fun:c2i_ASN1_BIT_STRING
fun:asn1_ex_c2i
obj:/lib/libcrypto.so.0.9.8
fun:ASN1_item_ex_d2i
obj:/lib/libcrypto.so.0.9.8
obj:/lib/libcrypto.so.0.9.8
fun:ASN1_item_ex_d2i
obj:/lib/libcrypto.so.0.9.8
obj:/lib/libcrypto.so.0.9.8
fun:ASN1_item_ex_d2i
}
{
<insert a suppression name here>
Memcheck:Leak
fun:realloc
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
fun:FcDefaultSubstitute
fun:_ZN13QFontDatabase4loadEPK12QFontPrivatei
fun:_ZNK12QFontPrivate15engineForScriptEi
fun:_ZNK12QFontMetrics6heightEv
fun:_ZN10QStatusBar8reformatEv
fun:_ZN10QStatusBar18setSizeGripEnabledEb
fun:_ZN10QStatusBarC2EP7QWidget
fun:_ZN10KStatusBarC1EP7QWidget
fun:_ZN11KMainWindow9statusBarEv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN8QMapData11node_createEPPNS_4NodeEi
fun:_ZN4QMapI9KEntryKey6KEntryE6insertERKS0_RKS1_
fun:_ZN9KEntryMap8setEntryERK10QByteArrayS2_S2_6QFlagsINS_11EntryOptionEE
fun:_ZN17KConfigIniBackend11parseConfigERK10QByteArrayR9KEntryMap6QFlagsIN14KConfigBackend11ParseOptionEEb
fun:_ZN17KConfigIniBackend11parseConfigERK10QByteArrayR9KEntryMap6QFlagsIN14KConfigBackend11ParseOptionEE
fun:_ZN14KConfigPrivate16parseConfigFilesEv
fun:_ZN7KConfig20reparseConfigurationEv
fun:_ZN7KConfigC1ERK7QString6QFlagsINS_8OpenFlagEEPKc
fun:_ZN11KMessConfig15getGlobalConfigERK7QString
fun:_ZN13NetworkWindowD0Ev
fun:_ZN13NetworkWindow7destroyEv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:CRYPTO_malloc
fun:SSL_new
fun:_ZN24QSslSocketBackendPrivate14initSslContextEv
fun:_ZN24QSslSocketBackendPrivate21startClientEncryptionEv
fun:_ZN17QSslSocketPrivate16_q_connectedSlotEv
fun:_ZN10QSslSocket11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
fun:_ZN22QAbstractSocketPrivate25fetchConnectionParametersEv
fun:_ZN22QAbstractSocketPrivate17_q_testConnectionEv
fun:_ZN14QWriteNotifier5eventEP6QEvent
fun:_ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent
}
{
<insert a suppression name here>
Memcheck:Cond
fun:BN_div
fun:BN_MONT_CTX_set
fun:BN_MONT_CTX_set_locked
obj:/lib/libcrypto.so.0.9.8
fun:RSA_verify
fun:EVP_VerifyFinal
fun:ASN1_item_verify
obj:/lib/libcrypto.so.0.9.8
fun:X509_verify_cert
fun:ssl_verify_cert_chain
fun:ssl3_get_server_certificate
fun:ssl3_connect
}
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwm
fun:_ZNK14QX11PixmapData11paintEngineEv
fun:_ZN8QPainter5beginEP12QPaintDevice
fun:_ZN11KIconEngine6pixmapERK5QSizeN5QIcon4ModeENS3_5StateE
fun:_ZNK5QIcon6pixmapERK5QSizeNS_4ModeENS_5StateE
fun:_ZN14QWidgetPrivate17setWindowIcon_sysEb
fun:_ZN7QWidget6createEmbb
fun:_ZN7QWidget10setVisibleEb
fun:_ZN7QWidget4showEv
fun:_ZN11LikeBackBar8autoMoveEv
fun:_ZN11LikeBackBar11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:CRYPTO_malloc
fun:ssl3_setup_buffers
fun:ssl3_connect
fun:_ZN24QSslSocketBackendPrivate14testConnectionEv
fun:_ZN24QSslSocketBackendPrivate21startClientEncryptionEv
fun:_ZN17QSslSocketPrivate16_q_connectedSlotEv
fun:_ZN10QSslSocket11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
fun:_ZN22QAbstractSocketPrivate25fetchConnectionParametersEv
fun:_ZN22QAbstractSocketPrivate17_q_testConnectionEv
fun:_ZN14QWriteNotifier5eventEP6QEvent
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:CRYPTO_malloc
fun:ASN1_OBJECT_new
fun:c2i_ASN1_OBJECT
fun:asn1_ex_c2i
obj:/lib/libcrypto.so.0.9.8
fun:ASN1_item_ex_d2i
obj:/lib/libcrypto.so.0.9.8
obj:/lib/libcrypto.so.0.9.8
fun:ASN1_item_ex_d2i
obj:/lib/libcrypto.so.0.9.8
obj:/lib/libcrypto.so.0.9.8
}
{
<insert a suppression name here>
Memcheck:Cond
fun:_ZL13PolygonRegionPK6QPointii
fun:_ZN7QRegionC1ERK8QPolygonN2Qt8FillRuleE
fun:_ZN15QX11PaintEngine11updateStateERK17QPaintEngineState
fun:_ZN15QPainterPrivate15updateStateImplEP13QPainterState
fun:_ZN15QPainterPrivate11updateStateEP13QPainterState
fun:_ZN8QPainter13setClipRegionERK7QRegionN2Qt13ClipOperationE
fun:_ZNK14QWidgetPrivate15paintBackgroundEP8QPainterRK7QRegionRK6QPointi
fun:_ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore
fun:_ZN19QWidgetBackingStore4syncEv
fun:_ZN14QWidgetPrivate16syncBackingStoreEv
fun:_ZN7QWidget5eventEP6QEvent
fun:_ZN11QMainWindow5eventEP6QEvent
}
{
<insert a suppression name here>
Memcheck:Cond
fun:_ZL13PolygonRegionPK6QPointii
fun:_ZN7QRegionC1ERK8QPolygonN2Qt8FillRuleE
fun:_ZN15QX11PaintEngine11updateStateERK17QPaintEngineState
fun:_ZN15QPainterPrivate15updateStateImplEP13QPainterState
fun:_ZN15QPainterPrivate11updateStateEP13QPainterState
fun:_ZN8QPainter13setClipRegionERK7QRegionN2Qt13ClipOperationE
fun:_ZNK14QWidgetPrivate15paintBackgroundEP8QPainterRK7QRegionRK6QPointi
fun:_ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7QRegionRK6QPointiP8QPainterP19QWidgetBackingStore
fun:_ZN19QWidgetBackingStore4syncEv
fun:_ZN14QWidgetPrivate16syncBackingStoreEv
fun:_ZN7QWidget5eventEP6QEvent
fun:_ZN11QMainWindow5eventEP6QEvent
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN7QString7reallocEi
fun:_ZN7QString6resizeEi
fun:_ZN7QString8fromUtf8EPKci
fun:_ZL26fromPercentEncodingMutableP10QByteArray
fun:_ZNK11QUrlPrivate5parseENS_12ParseOptionsE
fun:_ZNK4QUrl7isValidEv
fun:_ZN4KUrl14_setEncodedUrlERK10QByteArray
fun:_ZN4KUrlC1ERK7QString
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
fun:_ZN11QMetaObject8activateEP7QObjectiiPPv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:realloc
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
fun:FcPatternDuplicate
fun:_ZL14tryPatternLoadP10_FcPatterniRK8QFontDefiPS0_
fun:_ZN13QFontDatabase4loadEPK12QFontPrivatei
fun:_ZNK12QFontPrivate15engineForScriptEi
fun:_ZNK12QFontMetrics6ascentEv
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN8QMapData11node_createEPPNS_4NodeEi
fun:_ZN4QMapI7QStringS0_E11node_createEP8QMapDataPPNS2_4NodeERKS0_S8_
fun:_ZN4QMapI7QStringS0_E13detach_helperEv
fun:_ZN4QMapI7QStringS0_E6detachEv
fun:_ZN4QMapI7QStringS0_E5beginEv
fun:_ZN17XslTransformation20updateParametersListEv
fun:_ZN17XslTransformation13setParametersE4QMapI7QStringS1_E
fun:_ZN16ChatMessageStyle8setStyleERK7QString
fun:_ZN13ChatStylePage20slotChatStyleChangedERK7QString
fun:_ZN13ChatStylePage12loadSettingsEPK7Account
fun:_ZN21AccountSettingsDialog12loadSettingsEP7AccountbNS_4PageE
}
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwm
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
obj:/usr/lib/libkhtml.so.5.2.0
fun:_ZN9KHTMLPart5beginERK4KUrlii
fun:_ZN15ChatMessageView7setHtmlERK7QString
fun:_ZN15ChatMessageView9clearViewEb
fun:_ZN15ChatMessageViewC1EP7QWidget
fun:_ZN8ChatViewC2EP7QWidget
fun:_ZN4ChatC1EP7QWidget
}
{
<insert a suppression name here>
Memcheck:Leak
fun:_Znwm
fun:_ZN19QDockAreaLayoutInfo12restoreStateER11QDataStreamR5QListIP11QDockWidgetEb
fun:_ZN15QDockAreaLayout12restoreStateER11QDataStreamRK5QListIP11QDockWidgetEb
fun:_ZN22QMainWindowLayoutState11checkFormatER11QDataStreamb
fun:_ZN22QMainWindowLayoutState12restoreStateER11QDataStreamRKS_
fun:_ZN17QMainWindowLayout12restoreStateER11QDataStream
fun:_ZN11QMainWindow12restoreStateERK10QByteArrayi
fun:_ZN10ChatWindow14readPropertiesERK12KConfigGroup
fun:_ZN10ChatWindow10initializeEv
fun:_ZN10ChatMaster16createChatWindowEP4Chat
fun:_ZN10ChatMaster10createChatEP24MsnSwitchboardConnectionb
fun:_ZN10ChatMaster11qt_metacallEN11QMetaObject4CallEiPPv
}
{
<insert a suppression name here>
Memcheck:Leak
fun:malloc
fun:_ZN7QVectorI5QListIN14QObjectPrivate10ConnectionEEE7reallocEii
fun:_ZN14QObjectPrivate13addConnectionEiPNS_10ConnectionE
fun:_ZN11QMetaObject7connectEPK7QObjectiS2_iiPi
fun:_ZN7QObject7connectEPKS_PKcS1_S3_N2Qt14ConnectionTypeE
fun:_ZN14KActionPrivate4initEP7KAction
fun:_ZN7KActionC1ERK5KIconRK7QStringP7QObject
fun:_ZN8LikeBack18sendACommentActionEP17KActionCollection
fun:_ZN14KMessInterface10initializeEv
fun:_ZN5KMess10initializeEv
fun:_ZN16KMessApplication20initializeMainWindowEv
fun:_ZN16KMessApplicationC1Ev
}
{
<insert a suppression name here>
Memcheck:Leak
fun:realloc
fun:_ZN9QListData7reallocEi
fun:_ZN9QListData6appendEv
fun:_ZN5QListIP7QObjectE6appendERKS1_
fun:_ZN14QObjectPrivate16setParent_helperEP7QObject
fun:_ZN15QSocketNotifierC2EiNS_4TypeEP7QObject
fun:_ZN19QNativeSocketEngine27setWriteNotificationEnabledEb
fun:_ZN22QAbstractSocketPrivate23_q_connectToNextAddressEv
fun:_ZN22QAbstractSocketPrivate18_q_startConnectingERK9QHostInfo
fun:_ZN15QAbstractSocket27connectToHostImplementationERK7QStringt6QFlagsIN9QIODevice12OpenModeFlagEE
fun:_ZN15QAbstractSocket11qt_metacallEN11QMetaObject4CallEiPPv
fun:_ZNK11QMetaMethod6invokeEP7QObjectN2Qt14ConnectionTypeE22QGenericReturnArgument16QGenericArgumentS5_S5_S5_S5_S5_S5_S5_S5_S5_
}
{
<insert a suppression name here>
Memcheck:Leak
fun:realloc
obj:/usr/lib/libfontconfig.so.1.3.0
obj:/usr/lib/libfontconfig.so.1.3.0
fun:FcDefaultSubstitute
fun:_ZN13QFontDatabase4loadEPK12QFontPrivatei
fun:_ZNK12QFontPrivate15engineForScriptEi
fun:_ZNK12QFontMetrics6ascentEv
fun:_ZN5khtml18CachedFontInstanceC1EPNS_16CachedFontFamilyEi
fun:_ZN5khtml16CachedFontFamily9queryFontEi
fun:_ZNK5khtml4Font6updateEi
fun:_ZN5khtml4Font11initDefaultEv
fun:_ZN5khtml11RenderStyleC1Eb
}
+938 -788
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More