diff options
Diffstat (limited to 'basebmp')
60 files changed, 13240 insertions, 0 deletions
diff --git a/basebmp/CppunitTest_basebmp.mk b/basebmp/CppunitTest_basebmp.mk new file mode 100644 index 000000000000..90d7de57e445 --- /dev/null +++ b/basebmp/CppunitTest_basebmp.mk @@ -0,0 +1,50 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,basebmp_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,basebmp_test, \ + basebmp/test/basictest \ + basebmp/test/bmpmasktest \ + basebmp/test/bmptest \ + basebmp/test/cliptest \ + basebmp/test/filltest \ + basebmp/test/linetest \ + basebmp/test/masktest \ + basebmp/test/polytest \ + basebmp/test/tools \ +)) + +$(eval $(call gb_CppunitTest_add_linked_libs,basebmp_test, \ + basebmp \ + basegfx \ + sal \ + $(gb_STDLIBS) \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/Executable_basebmp_cppunittester_all.mk b/basebmp/Executable_basebmp_cppunittester_all.mk new file mode 100644 index 000000000000..c2cd64554e5d --- /dev/null +++ b/basebmp/Executable_basebmp_cppunittester_all.mk @@ -0,0 +1,70 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License or as specified alternatively below. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Tor Lillqvist <tml@iki.fi> +# Portions created by the Initial Developer are Copyright (C) 2011 the +# Initial Developer. All Rights Reserved. +# +# Major Contributor(s): +# +# For minor contributions see the git repository. +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +#************************************************************************* + +$(eval $(call gb_Executable_Executable,basebmp_cppunittester_all)) + +$(eval $(call gb_Executable_add_defs,basebmp_cppunittester_all,\ + $(gb_OBJCXXFLAGS) \ +)) + +$(eval $(call gb_Executable_add_linked_libs,basebmp_cppunittester_all, \ + basebmp \ + basegfx \ + cppu \ + cppunit \ + sal \ + sal_textenc \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Executable_use_externals,basebmp_cppunittester_all, \ + uikit \ + foundation \ +)) + +$(eval $(call gb_Executable_add_exception_objects,basebmp_cppunittester_all, \ + basebmp/test/basebmp_cppunittester_all \ + basebmp/test/basictest \ + basebmp/test/bmpmasktest \ + basebmp/test/bmptest \ + basebmp/test/cliptest \ + basebmp/test/filltest \ + basebmp/test/linetest \ + basebmp/test/masktest \ + basebmp/test/polytest \ + basebmp/test/tools \ +)) + +$(eval $(call gb_Executable_add_api,basebmp_cppunittester_all, \ + udkapi \ + offapi \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/Library_basebmp.mk b/basebmp/Library_basebmp.mk new file mode 100644 index 000000000000..80b811cb5b53 --- /dev/null +++ b/basebmp/Library_basebmp.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,basebmp)) + +$(eval $(call gb_Library_add_package_headers,basebmp,basebmp_inc)) + +$(eval $(call gb_Library_set_include,basebmp,\ + -I$(realpath $(SRCDIR)/basebmp/inc/) \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Library_use_api,basebmp,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_defs,basebmp,\ + -DBASEBMP_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_add_linked_libs,basebmp,\ + basegfx \ + sal \ + $(gb_STDLIBS) \ +)) + +ifeq ($(OS),SOLARIS) +$(eval $(call gb_Library_add_cxxobjects,basebmp, \ + basebmp/source/bitmapdevice \ + basebmp/source/debug \ + basebmp/source/polypolygonrenderer \ + , $(gb_COMPILEROPTFLAGS) $(gb_LinkTarget_EXCEPTIONFLAGS) -xalias_level=compatible \ +)) +else +$(eval $(call gb_Library_add_exception_objects,basebmp,\ + basebmp/source/bitmapdevice \ + basebmp/source/debug \ + basebmp/source/polypolygonrenderer \ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/Makefile b/basebmp/Makefile new file mode 100644 index 000000000000..b912f2f0532b --- /dev/null +++ b/basebmp/Makefile @@ -0,0 +1,39 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif + +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk + +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/Module_basebmp.mk b/basebmp/Module_basebmp.mk new file mode 100644 index 000000000000..b3da038c0de7 --- /dev/null +++ b/basebmp/Module_basebmp.mk @@ -0,0 +1,46 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Module_Module,basebmp)) + +$(eval $(call gb_Module_add_targets,basebmp,\ + Library_basebmp \ + Package_inc \ +)) + +$(eval $(call gb_Module_add_check_targets,basebmp,\ + CppunitTest_basebmp \ +)) + +ifeq ($(OS),IOS) +$(eval $(call gb_Module_add_targets,basebmp,\ + Executable_basebmp_cppunittester_all \ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/Package_inc.mk b/basebmp/Package_inc.mk new file mode 100644 index 000000000000..eeec45f35e4e --- /dev/null +++ b/basebmp/Package_inc.mk @@ -0,0 +1,65 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Package_Package,basebmp_inc,$(SRCDIR)/basebmp/inc)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/accessor.hxx,basebmp/accessor.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/accessoradapters.hxx,basebmp/accessoradapters.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/accessorfunctors.hxx,basebmp/accessorfunctors.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/accessortraits.hxx,basebmp/accessortraits.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/bitmapdevice.hxx,basebmp/bitmapdevice.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/clippedlinerenderer.hxx,basebmp/clippedlinerenderer.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/color.hxx,basebmp/color.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/colorblendaccessoradapter.hxx,basebmp/colorblendaccessoradapter.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/colormisc.hxx,basebmp/colormisc.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/colortraits.hxx,basebmp/colortraits.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/compositeiterator.hxx,basebmp/compositeiterator.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/debug.hxx,basebmp/debug.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/drawmodes.hxx,basebmp/drawmodes.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/endian.hxx,basebmp/endian.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/fillimage.hxx,basebmp/fillimage.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/genericcolorimageaccessor.hxx,basebmp/genericcolorimageaccessor.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/greylevelformats.hxx,basebmp/greylevelformats.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/iteratortraits.hxx,basebmp/iteratortraits.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/linerenderer.hxx,basebmp/linerenderer.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/metafunctions.hxx,basebmp/metafunctions.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/nonstandarditerator.hxx,basebmp/nonstandarditerator.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/packedpixeliterator.hxx,basebmp/packedpixeliterator.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/paletteformats.hxx,basebmp/paletteformats.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/paletteimageaccessor.hxx,basebmp/paletteimageaccessor.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/pixelformatadapters.hxx,basebmp/pixelformatadapters.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/pixeliterator.hxx,basebmp/pixeliterator.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/polypolygonrenderer.hxx,basebmp/polypolygonrenderer.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/rgb24pixelformats.hxx,basebmp/rgb24pixelformats.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/rgbmaskpixelformats.hxx,basebmp/rgbmaskpixelformats.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/scaleimage.hxx,basebmp/scaleimage.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/scanlineformats.hxx,basebmp/scanlineformats.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/stridedarrayiterator.hxx,basebmp/stridedarrayiterator.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/tools.hxx,basebmp/tools.hxx)) +$(eval $(call gb_Package_add_file,basebmp_inc,inc/basebmp/truecolormaskaccessor.hxx,basebmp/truecolormaskaccessor.hxx)) + +# vim: set noet sw=4 ts=4: diff --git a/basebmp/inc/basebmp/accessor.hxx b/basebmp/inc/basebmp/accessor.hxx new file mode 100644 index 000000000000..9bf2d1b6d140 --- /dev/null +++ b/basebmp/inc/basebmp/accessor.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSOR_HXX +#define INCLUDED_BASEBMP_ACCESSOR_HXX + +#include <vigra/numerictraits.hxx> + +namespace basebmp +{ + +/** Standard accessor type + + Accesses the iterator values the standard way (i.e. via + *operator()/operator[]) + */ +template<typename ValueType> class StandardAccessor +{ +public: + typedef ValueType value_type; + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return *i; + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return i[diff]; + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + *i = vigra::detail::RequiresExplicitCast<value_type>::cast(value); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i[diff] = vigra::detail::RequiresExplicitCast<value_type>::cast(value); + } +}; + +//----------------------------------------------------------------------------- + +/** Non-standard accessor type + + Uses getter/setter methods at the given iterator type, to access + the underlying values. + */ +template<typename ValueType> class NonStandardAccessor +{ +public: + typedef ValueType value_type; + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return i.get(); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return i.get(diff); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + i.set( vigra::detail::RequiresExplicitCast<value_type>::cast(value) ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i.set( vigra::detail::RequiresExplicitCast<value_type>::cast(value), + diff ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/accessoradapters.hxx b/basebmp/inc/basebmp/accessoradapters.hxx new file mode 100644 index 000000000000..8fb801d7c8ca --- /dev/null +++ b/basebmp/inc/basebmp/accessoradapters.hxx @@ -0,0 +1,529 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX +#define INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX + +#include <vigra/numerictraits.hxx> + +namespace basebmp +{ + +/** Interpose given accessor's set and get methods with two unary + functors. + + @tpl WrappedAccessor + Wrapped type must provide the usual get and set accessor methods, + with the usual signatures (see StandardAccessor for a conforming + example). + + @tpl GetterFunctor + An Adaptable Unary Function (i.e. providing result_type and + argument_type typedefs) + + @tpl SetterFunctor + An Adaptable Unary Function (i.e. providing result_type and + argument_type typedefs) + */ +template< class WrappedAccessor, + typename GetterFunctor, + typename SetterFunctor > class UnaryFunctionAccessorAdapter +{ +public: + typedef typename GetterFunctor::result_type value_type; + typedef typename SetterFunctor::argument_type argument_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A, typename G, typename S> friend class UnaryFunctionAccessorAdapter; +#endif + + // we don't derive from wrapped type, to avoid ambiguities + // regarding templatized getter/setter methods. + WrappedAccessor maAccessor; + GetterFunctor maGetterFunctor; + SetterFunctor maSetterFunctor; + +public: + UnaryFunctionAccessorAdapter() : + maAccessor(), + maGetterFunctor(), + maSetterFunctor() + {} + + template< class A > explicit + UnaryFunctionAccessorAdapter( UnaryFunctionAccessorAdapter< A, + GetterFunctor, + SetterFunctor > const& rSrc ) : + maAccessor( rSrc.maAccessor ), + maGetterFunctor( rSrc.maGetterFunctor ), + maSetterFunctor( rSrc.maSetterFunctor ) + {} + + template< class T > explicit UnaryFunctionAccessorAdapter( T const& accessor ) : + maAccessor( accessor ), + maGetterFunctor(), + maSetterFunctor() + {} + + template< class T > UnaryFunctionAccessorAdapter( T accessor, + GetterFunctor getterFunctor, + SetterFunctor setterFunctor) : + maAccessor( accessor ), + maGetterFunctor( getterFunctor ), + maSetterFunctor( setterFunctor ) + {} + + // ------------------------------------------------------- + + WrappedAccessor const& getWrappedAccessor() const { return maAccessor; } + WrappedAccessor& getWrappedAccessor() { return maAccessor; } + + // ------------------------------------------------------- + + value_type getter(typename GetterFunctor::argument_type v) const + { + return maGetterFunctor(v); + } + typename SetterFunctor::result_type setter(argument_type v) const + { + return maSetterFunctor(v); + } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return maGetterFunctor( maAccessor(i) ); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return maGetterFunctor( maAccessor(i,diff) ); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + maAccessor.set( + maSetterFunctor( + vigra::detail::RequiresExplicitCast<argument_type>::cast(value) ), + i ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + maAccessor.set( + maSetterFunctor( + vigra::detail::RequiresExplicitCast<argument_type>::cast(value) ), + i, + diff ); + } + +}; + +//----------------------------------------------------------------------------- + +/** Interpose given accessor's set methods with a binary function, + taking both old and new value. + + The wrappee's getter methods kept as-is. + + @tpl WrappedAccessor + Wrapped type must provide the usual get and set accessor methods, + with the usual signatures (see StandardAccessor for a conforming + example). Furthermore, must provide a nested typedef value_type. + + @tpl SetterFunctor + An adaptable binary function (i.e. providing nested typedefs for + result_type and first and second argument type) + */ +template< class WrappedAccessor, + typename SetterFunctor > class BinarySetterFunctionAccessorAdapter +{ +public: + typedef typename WrappedAccessor::value_type value_type; + typedef typename SetterFunctor::second_argument_type argument_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A, typename S> friend class BinarySetterFunctionAccessorAdapter; +#endif + + WrappedAccessor maAccessor; + SetterFunctor maFunctor; + +public: + BinarySetterFunctionAccessorAdapter() : + maAccessor(), + maFunctor() + {} + + template< class A > explicit + BinarySetterFunctionAccessorAdapter( + BinarySetterFunctionAccessorAdapter< A, + SetterFunctor > const& rSrc ) : + maAccessor( rSrc.maAccessor ), + maFunctor( rSrc.maFunctor ) + {} + + template< class T > explicit BinarySetterFunctionAccessorAdapter( T const& accessor ) : + maAccessor( accessor ), + maFunctor() + {} + + template< class T > BinarySetterFunctionAccessorAdapter( T accessor, + SetterFunctor functor ) : + maAccessor( accessor ), + maFunctor( functor ) + {} + + // ------------------------------------------------------- + + WrappedAccessor const& getWrappedAccessor() const { return maAccessor; } + WrappedAccessor& getWrappedAccessor() { return maAccessor; } + + // ------------------------------------------------------- + + typename SetterFunctor::result_type setter( + typename SetterFunctor::first_argument_type v1, + argument_type v2 ) const + { + return maSetterFunctor(v1,v2); + } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return maAccessor(i); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return maAccessor(i,diff); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + maAccessor.set( + maFunctor(maAccessor(i), + vigra::detail::RequiresExplicitCast<argument_type>::cast(value)), + i ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + maAccessor.set( + maFunctor(maAccessor(i,diff), + vigra::detail::RequiresExplicitCast<argument_type>::cast(value)), + i, + diff ); + } + +}; + +//----------------------------------------------------------------------------- + +/** Write through a CompositeIterator's first wrapped iterator, by + piping the first wrapped iterator value, the second iterator + value, and the specified new value through a ternary function. + + Passed iterator must fulfill the CompositeIterator concept. Note + that the getter/setter methods are not templatized regarding the + iterator type, to make the mask calculation optimization below + safe (see the maskedAccessor template metafunction below) + + @tpl WrappedAccessor1 + Wrapped type must provide the usual get and set accessor methods, + with the usual signatures (see StandardAccessor for a conforming + example). Furthermore, the type must provide a nested typedef + value_type (the selection of WrappedAccessor1 as the provider for + that typedef is rather arbitrary. Could have been + WrappedAccessor2, too. So sue me) + + @tpl Functor + An adaptable ternary function (i.e. providing nested typedefs for + result_type and first, second and third argument type) + */ +template< class WrappedAccessor1, + class WrappedAccessor2, + typename Functor > class TernarySetterFunctionAccessorAdapter +{ +public: + typedef typename WrappedAccessor1::value_type value_type; + typedef typename Functor::third_argument_type argument_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A1, class A2, typename F> friend class TernarySetterFunctionAccessorAdapter; +#endif + + WrappedAccessor1 ma1stAccessor; + WrappedAccessor2 ma2ndAccessor; + Functor maFunctor; + +public: + TernarySetterFunctionAccessorAdapter() : + ma1stAccessor(), + ma2ndAccessor(), + maFunctor() + {} + + template< class T > explicit TernarySetterFunctionAccessorAdapter( T const& accessor ) : + ma1stAccessor( accessor ), + ma2ndAccessor(), + maFunctor() + {} + + template< class A1, class A2 > explicit + TernarySetterFunctionAccessorAdapter( + TernarySetterFunctionAccessorAdapter< A1, + A2, + Functor > const& rSrc ) : + ma1stAccessor( rSrc.ma1stAccessor ), + ma2ndAccessor( rSrc.ma2ndAccessor ), + maFunctor( rSrc.maFunctor ) + {} + + template< class T1, class T2 > + TernarySetterFunctionAccessorAdapter( T1 accessor1, + T2 accessor2 ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor( accessor2 ), + maFunctor() + {} + + template< class T1, class T2 > + TernarySetterFunctionAccessorAdapter( T1 accessor1, + T2 accessor2, + Functor func ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor( accessor2 ), + maFunctor( func ) + {} + + // ------------------------------------------------------- + + WrappedAccessor1 const& get1stWrappedAccessor() const { return ma1stAccessor; } + WrappedAccessor1& get1stWrappedAccessor() { return ma1stAccessor; } + + WrappedAccessor2 const& get2ndWrappedAccessor() const { return ma2ndAccessor; } + WrappedAccessor2& get2ndWrappedAccessor() { return ma2ndAccessor; } + + // ------------------------------------------------------- + + typename Functor::result_type setter( + typename Functor::first_argument_type v1, + typename Functor::second_argument_type v2, + argument_type v3 ) const + { + return maSetterFunctor(v1,v2,v3); + } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return ma1stAccessor(i.first()); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return ma1stAccessor(i.second(),diff); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + ma1stAccessor.set( + maFunctor(ma1stAccessor(i.first()), + ma2ndAccessor(i.second()), + vigra::detail::RequiresExplicitCast<argument_type>::cast(value)), + i.first() ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + ma1stAccessor.set( + maFunctor(ma1stAccessor(i.first(), diff), + ma2ndAccessor(i.second(),diff), + vigra::detail::RequiresExplicitCast<argument_type>::cast(value)), + i.first(), + diff ); + } + +}; + +//----------------------------------------------------------------------------- + +/** Access two distinct images simultaneously + + Passed iterator must fulfill the CompositeIterator concept + (i.e. wrap the two image's iterators into one + CompositeIterator). The getter and setter methods expect and + return a pair of values, with types equal to the two accessors + value types + + @tpl WrappedAccessor1 + Wrapped type must provide the usual get and set accessor methods, + with the usual signatures (see StandardAccessor for a conforming + example). Furthermore, the type must provide a nested typedef + value_type. + + @tpl WrappedAccessor2 + Wrapped type must provide the usual get and set accessor methods, + with the usual signatures (see StandardAccessor for a conforming + example). Furthermore, the type must provide a nested typedef + value_type. + */ +template< class WrappedAccessor1, + class WrappedAccessor2 > class JoinImageAccessorAdapter +{ +public: + // TODO(F3): Need numeric traits and a few free functions to + // actually calculate with a pair (semantic: apply every operation + // individually to the contained types) + typedef std::pair<typename WrappedAccessor1::value_type, + typename WrappedAccessor2::value_type> value_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A1, class A2> friend class JoinImageAccessorAdapter; +#endif + + WrappedAccessor1 ma1stAccessor; + WrappedAccessor2 ma2ndAccessor; + +public: + JoinImageAccessorAdapter() : + ma1stAccessor(), + ma2ndAccessor() + {} + + template< class T > explicit JoinImageAccessorAdapter( T const& accessor ) : + ma1stAccessor( accessor ), + ma2ndAccessor() + {} + + template< class A1, class A2 > explicit + JoinImageAccessorAdapter( + JoinImageAccessorAdapter< A1, + A2 > const& rSrc ) : + ma1stAccessor( rSrc.ma1stAccessor ), + ma2ndAccessor( rSrc.ma2ndAccessor ) + {} + + template< class T1, class T2 > + JoinImageAccessorAdapter( T1 accessor1, + T2 accessor2 ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor( accessor2 ) + {} + + // ------------------------------------------------------- + + WrappedAccessor1 const& get1stWrappedAccessor() const { return ma1stAccessor; } + WrappedAccessor1& get1stWrappedAccessor() { return ma1stAccessor; } + + WrappedAccessor2 const& get2ndWrappedAccessor() const { return ma2ndAccessor; } + WrappedAccessor2& get2ndWrappedAccessor() { return ma2ndAccessor; } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return std::make_pair(ma1stAccessor(i.first()), + ma2ndAccessor(i.second())); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return std::make_pair(ma1stAccessor(i.first(),diff), + ma2ndAccessor(i.second(),diff)); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + ma1stAccessor.set( + vigra::detail::RequiresExplicitCast<typename WrappedAccessor1::value_type>::cast( + value.first), + i.first() ); + ma2ndAccessor.set( + vigra::detail::RequiresExplicitCast<typename WrappedAccessor2::value_type>::cast( + value.second), + i.second() ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + ma1stAccessor.set( + vigra::detail::RequiresExplicitCast<typename WrappedAccessor1::value_type>::cast( + value.first), + i.first(), + diff ); + ma2ndAccessor.set( + vigra::detail::RequiresExplicitCast<typename WrappedAccessor2::value_type>::cast( + value.second), + i.second(), + diff ); + } + +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/accessorfunctors.hxx b/basebmp/inc/basebmp/accessorfunctors.hxx new file mode 100644 index 000000000000..1d5464ac0c2f --- /dev/null +++ b/basebmp/inc/basebmp/accessorfunctors.hxx @@ -0,0 +1,190 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSORFUNCTORS_HXX +#define INCLUDED_BASEBMP_ACCESSORFUNCTORS_HXX + +#include <osl/diagnose.h> +#include <basebmp/metafunctions.hxx> + +#include <functional> + +namespace basebmp +{ + +// Some common accessor functors +// ------------------------------------------------------------ + + +/// combine two values via XOR +template< typename T > struct XorFunctor : public std::binary_function<T,T,T> +{ + T operator()( T v1, T v2 ) const { return v1 ^ v2; } +}; + +//----------------------------------------------------------------------------- + +/// Base class, passing on the arg types +template< typename T, typename M > struct MaskFunctorBase : + public TernaryFunctorBase<T,M,T,T> {}; + + +/** Let a mask flag decide between two values + + @tpl polarity + Mask polarity. When true, a false in the mask denotes + transparency, i.e. the original value will display. And vice + versa. + */ +template< typename T, + typename M, + bool polarity > struct GenericOutputMaskFunctor : public MaskFunctorBase<T,M> +{ + /// Ternary mask operation - selects v1 for !m == polarity, v2 otherwise + T operator()( T v1, M m, T v2 ) const + { + return !m == polarity ? v1 : v2; + } +}; + +/** Let a mask bit decide between two values (specialization for + integer mask types) + */ +template< typename T, + typename M, + bool polarity > struct IntegerOutputMaskFunctor; +template< typename T, + typename M > struct IntegerOutputMaskFunctor<T,M,true> : public MaskFunctorBase<T,M> +{ + /** Mask v with state of m + + @return v2, if m != 0, v1 otherwise. + */ + T operator()( T v1, M m, T v2 ) const + { + typedef typename make_unsigned<T>::type unsigned_T; + + // mask will be 0, iff m == 0, and 1 otherwise + const T mask( unsigned_cast<T>(m | -m) >> (sizeof(unsigned_T)*8 - 1) ); + return v1*(M)(1-mask) + v2*mask; + } +}; +template< typename T, + typename M > struct IntegerOutputMaskFunctor<T,M,false> : public MaskFunctorBase<T,M> +{ + /** Mask v with state of m + + @return v2, if m != 0, v1 otherwise. + */ + T operator()( T v1, M m, T v2 ) const + { + typedef typename make_unsigned<T>::type unsigned_T; + + // mask will be 0, iff m == 0, and 1 otherwise + const T mask( unsigned_cast<T>(m | -m) >> (sizeof(unsigned_T)*8 - 1) ); + return v1*mask + v2*(M)(1-mask); + } +}; + +/** Let a mask bit decide between two values (specialization for + binary-valued mask types) + */ +template< typename T, typename M, bool polarity > struct FastIntegerOutputMaskFunctor; +template< typename T, typename M > struct FastIntegerOutputMaskFunctor<T,M,true> : + public MaskFunctorBase<T,M> +{ + /// Specialization, only valid if mask can only attain 0 or 1 + T operator()( T v1, M m, T v2 ) const + { + OSL_ASSERT(m<=1); + + return v1*(M)(1-m) + v2*m; + } +}; +template< typename T, typename M > struct FastIntegerOutputMaskFunctor<T,M,false> : + public MaskFunctorBase<T,M> +{ + /// Specialization, only valid if mask can only attain 0 or 1 + T operator()( T v1, M m, T v2 ) const + { + OSL_ASSERT(m<=1); + + return v1*m + v2*(M)(1-m); + } +}; + +//----------------------------------------------------------------------------- + +/** Split a pair value from a JoinImageAccessorAdapter into its + individual values, and pass it on to a ternary functor + + This wrapper is an adaptable binary functor, and can thus be used + with a BinarySetterFunctionAccessorAdapter. Useful e.g. for + out-of-image alpha channel, or a masked image. + + @tpl Functor + An adaptable ternary functor (as can e.g. be passed to the + TernarySetterFunctionAccessorAdapter) + */ +template< typename Functor > struct BinaryFunctorSplittingWrapper : + public std::binary_function<typename Functor::first_argument_type, + std::pair<typename Functor::third_argument_type, + typename Functor::second_argument_type>, + typename Functor::result_type> +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A> friend struct BinaryFunctorSplittingWrapper; +#endif + Functor maFunctor; + +public: + BinaryFunctorSplittingWrapper() : maFunctor() {} + + template< class A > explicit + BinaryFunctorSplittingWrapper( + BinaryFunctorSplittingWrapper<A> const& src ) : maFunctor(src.maFunctor) {} + + template< class F > explicit + BinaryFunctorSplittingWrapper( F const& func ) : maFunctor(func) {} + + typename Functor::result_type operator()( + typename Functor::first_argument_type v1, + std::pair< typename Functor::third_argument_type, + typename Functor::second_argument_type > const& v2 ) const + { + return maFunctor( v1, v2.second, v2.first ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSORFUNCTORS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/accessortraits.hxx b/basebmp/inc/basebmp/accessortraits.hxx new file mode 100644 index 000000000000..30bdcd59c4ee --- /dev/null +++ b/basebmp/inc/basebmp/accessortraits.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSORTRAITS_HXX +#define INCLUDED_BASEBMP_ACCESSORTRAITS_HXX + +#include <basebmp/accessorfunctors.hxx> +#include <basebmp/accessoradapters.hxx> +#include <basebmp/metafunctions.hxx> + +#include <functional> + +namespace basebmp +{ + +struct FastMask; +struct NoFastMask; + +/// Metafunction to select output mask functor from iterator and mask value type +template< typename T, typename M, bool polarity, typename DUMMY > struct outputMaskFunctorSelector : public + ifBothScalarIntegral< T, M, + IntegerOutputMaskFunctor< T, M, polarity >, + GenericOutputMaskFunctor< T, M, polarity > > +{ +}; +template< typename T, typename M, bool polarity > struct outputMaskFunctorSelector< T, M, polarity, FastMask > : public + ifBothScalarIntegral< T, M, + FastIntegerOutputMaskFunctor< T, M, polarity >, + GenericOutputMaskFunctor< T, M, polarity > > +{ +}; + +/** Metafunction providing a point of configuration for iterators + capable of employing the fast output mask functor. + + Specialize this metafunction for your case, and pass FastMask to + the outputMaskFunctorSelector. + */ +template< class Accessor, + class MaskAccessor, + class Iterator, + class MaskIterator, + bool polarity > struct maskedAccessorSelector +{ + typedef TernarySetterFunctionAccessorAdapter< + Accessor, + MaskAccessor, + typename outputMaskFunctorSelector< + typename Accessor::value_type, + typename MaskAccessor::value_type, + polarity, + NoFastMask > ::type > + type; +}; + +//----------------------------------------------------------------------------- + +/** Traits template for Accessor + + Provides wrapped types for color lookup, raw pixel access, xor and + mask accessors. + */ +template< class Accessor > struct AccessorTraits +{ + /// value type of described accessor + typedef typename Accessor::value_type value_type; + + /// Retrieve stand-alone color lookup function for given Accessor type + typedef project2nd< Accessor, value_type > color_lookup; + + /// Retrieve raw pixel data accessor for given Accessor type + typedef Accessor raw_accessor; + + /// Retrieve wrapped accessor for XOR setter access + typedef BinarySetterFunctionAccessorAdapter< + Accessor, + XorFunctor< value_type > > xor_accessor; + + /** Retrieve masked accessor for given types + + A masked accessor works like a filter, where the mask gates + the accessor's setter methods (if the mask contains a 0 at a + given iterator position, the original value is + preserved. Otherwise, the new value gets set). + + @attention be careful when retrieving a masked accessor for a + set of types, and using it for a different one - there are + partial specializations that take an optimized functor for + certain mask accessors. + */ + template< class MaskAccessor, + class Iterator, + class MaskIterator, + bool polarity > struct masked_accessor : + public maskedAccessorSelector< Accessor, + MaskAccessor, + Iterator, + MaskIterator, + polarity > + {}; + +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSORTRAITS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/bitmapdevice.hxx b/basebmp/inc/basebmp/bitmapdevice.hxx new file mode 100644 index 000000000000..0db4099213f4 --- /dev/null +++ b/basebmp/inc/basebmp/bitmapdevice.hxx @@ -0,0 +1,711 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_BITMAPDEVICE_HXX +#define INCLUDED_BASEBMP_BITMAPDEVICE_HXX + +#include <sal/types.h> +#include <basebmp/drawmodes.hxx> + +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/shared_array.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/noncopyable.hpp> +#include <vector> + +#if defined BASEBMP_DLLIMPLEMENTATION +#define BASEBMP_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define BASEBMP_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define BASEBMP_DLLPRIVATE SAL_DLLPRIVATE + +namespace basegfx +{ + class B2IPoint; + class B2DPoint; + class B2IVector; + class B2IRange; + class B2DPolygon; + class B2DPolyPolygon; +} + +namespace basebmp +{ + +// Temporary. Use like the tools color object +class Color; +typedef boost::shared_ptr< class BitmapDevice > BitmapDeviceSharedPtr; +typedef boost::shared_array< sal_uInt8 > RawMemorySharedArray; +typedef boost::shared_ptr< const std::vector<Color> > PaletteMemorySharedVector; + +struct ImplBitmapDevice; + +class BitmapDeviceDamageTracker { + public: + virtual void damaged (const basegfx::B2IRange& rDamageRect) = 0; +}; + +/** Definition of BitmapDevice interface + + Use the createBitmapDevice() factory method to create instances. + + Implementation note: the clip mask and bitmap parameter instances + of BitmapDevice that are passed to individual BitmapDevice + instances work best with 1 bit grey masks for the clip and a + format matching that of the target BitmapDevice for the other + parameters. The alpha mask passed to the drawMaskedColor() methods + works best when given as an eight bit grey bitmap. Everything else + is accepted, but potentially slow. + */ +class BASEBMP_DLLPUBLIC BitmapDevice : public boost::enable_shared_from_this<BitmapDevice>, + private boost::noncopyable +{ +public: + /** Query size of device in pixel + */ + basegfx::B2IVector getSize() const; + + /** Query whether buffer starts with 0th scanline + + @return true, if the buffer memory starts with the 0th + scanline, and false if it starts with the last one. The latter + is e.g. the typical scan line ordering for the Windows BMP + format. + */ + bool isTopDown() const; + + /** Query type of scanline memory format + */ + sal_Int32 getScanlineFormat() const; + + /** Query byte offset to get from scanline n to scanline n+1 + + @return the scanline stride in bytes. In the case of + isTopDown()==false, this offset will be negative. + */ + sal_Int32 getScanlineStride() const; + + /** Get pointer to frame buffer + + @return a shared ptr to the bitmap buffer memory. As this is a + shared ptr, you can freely store and use the pointer, even + after this object has been deleted. + */ + RawMemorySharedArray getBuffer() const; + + BitmapDeviceDamageTracker *getDamageTracker() const; + + /** Get pointer to palette + + The returned pointer is const on purpose, since the + BitmapDevice might internally cache lookup information. Don't + modify the returned data, unless you want to enter the realm + of completely undefined behaviour. + + @return shared pointer to vector of Color entries. + */ + PaletteMemorySharedVector getPalette() const; + + /** Query number of palette entries. + + This is just a frontend for getPalette->size() + */ + sal_Int32 getPaletteEntryCount() const; + + /** Clear whole device with given color + + This method works like a fill with the given color value, + resulting in a bitmap uniformly colored in fillColor. + */ + void clear( Color fillColor ); + + /** Set given pixel to specified color + + @param rPt + Pixel to set + + @param pixelColor + Color value to set the pixel to + + @param drawMode + Draw mode to use when changing the pixel value + */ + void setPixel( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode ); + + /** Set given pixel to specified color + + @param rPt + Pixel to set + + @param pixelColor + Color value to set the pixel to + + @param drawMode + Draw mode to use when changing the pixel value + + @param rClip + Clip mask to use. If the clip mask is 1 at the given pixel + position, no change will take place. + */ + void setPixel( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Get color value at given pixel + */ + Color getPixel( const basegfx::B2IPoint& rPt ); + + /** Get underlying pixel data value at given position + + This method returns the raw pixel data. In the case of + paletted bitmaps, this is the palette index, not the final + color value. + */ + sal_uInt32 getPixelData( const basegfx::B2IPoint& rPt ); + + /** Draw a line + + @param rPt1 + Start point of the line + + @param rPt2 + End point of the line. If the analytical line from rP1 to rPt2 + (with the actual pixel positions assumed to be the center of + the pixel) is exactly in the middle between two pixel, this + method always selects the pixel closer to rPt1. + + @param lineColor + Color value to draw the line with + + @param drawMode + Draw mode to use when changing the pixel value + */ + void drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode ); + + /** Draw a line + + @param rPt1 + Start point of the line + + @param rPt2 + End point of the line. If the analytical line from rP1 to rPt2 + (with the actual pixel positions assumed to be the center of + the pixel) is exactly in the middle between two pixel, this + method always selects the pixel closer to rPt1. + + @param lineColor + Color value to draw the line with + + @param drawMode + Draw mode to use when changing the pixel value + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Draw a polygon + + @param rPoly + Polygon to draw. Depending on the value returned by rPoly's + isClosed() method, the resulting line polygon will be drawn + closed or not. + + @param lineColor + Color value to draw the polygon with + + @param drawMode + Draw mode to use when changing pixel values + */ + void drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ); + + /** Draw a polygon + + @param rPoly + Polygon to draw. Depending on the value returned by rPoly's + isClosed() method, the resulting line polygon will be drawn + closed or not. + + @param lineColor + Color value to draw the polygon with + + @param drawMode + Draw mode to use when changing pixel values + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Fill a poly-polygon + + @param rPoly + Poly-polygon to fill. Regardless of the value returned by + rPoly's isClosed() method, the resulting filled poly-polygon + is always considered closed. As usual, when filling a shape, + the rightmost and bottommost pixel are not filled, compared to + the drawPolygon() method. For example, the rectangle + (0,0),(1,1) will have four pixel set, when drawn via + drawPolygon(), and only one pixel, when filled via + fillPolyPolygon(). + + @param fillColor + Color value to fill the poly-polygon with + + @param drawMode + Draw mode to use when changing pixel values + */ + void fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode ); + + /** Fill a poly-polygon + + @param rPoly + Poly-polygon to fill. Regardless of the value returned by + rPoly's isClosed() method, the resulting filled poly-polygon + is always considered closed. As usual, when filling a shape, + the rightmost and bottommost pixel are not filled, compared to + the drawPolygon() method. For example, the rectangle + (0,0),(1,1) will have four pixel set, when drawn via + drawPolygon(), and only one pixel, when filled via + fillPolyPolygon(). + + @param fillColor + Color value to fill the poly-polygon with + + @param drawMode + Draw mode to use when changing pixel values + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Draw another bitmap into this device + + @param rSrcBitmap + Bitmap to render into this one. It is permitted that source + and destination bitmap are the same. + + @param rSrcRect + Rectangle within the source bitmap to take the pixel from. + + @param rDstRect + Rectangle in the destination bitmap to put the pixel + into. Source and destination rectangle are permitted to have + differing sizes; this method will scale the source pixel + accordingly. Please note that both source and destination + rectangle are interpreted excluding the rightmost pixel column + and the bottommost pixel row, this is much like polygon + filling. As a result, filling a given rectangle with + fillPolyPolygon(), and using the same rectangle as the + destination rectangle of this method, will affect exactly the + same set of pixel. + + @param drawMode + Draw mode to use when changing pixel values + */ + void drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ); + + /** Draw another bitmap into this device + + @param rSrcBitmap + Bitmap to render into this one. It is permitted that source + and destination bitmap are the same. + + @param rSrcRect + Rectangle within the source bitmap to take the pixel from. + + @param rDstRect + Rectangle in the destination bitmap to put the pixel + into. Source and destination rectangle are permitted to have + differing sizes; this method will scale the source pixel + accordingly. Please note that both source and destination + rectangle are interpreted excluding the rightmost pixel column + and the bottommost pixel row, this is much like polygon + filling. As a result, filling a given rectangle with + fillPolyPolygon(), and using the same rectangle as the + destination rectangle of this method, will affect exactly the + same set of pixel. + + @param drawMode + Draw mode to use when changing pixel values + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Draw a color with an alpha-modulation bitmap into this device + + This method takes a fixed color value, and an alpha mask. For + each pixel in the alpha mask, the given color value is blended + with the corresponding alpha value against the content of this + object. + + @param aSrcColor + Color value to use for blending + + @param rAlphaMask + Alpha mask to use for blending. It is permitted that alpha + mask and this bitmap are the same object. + + @param rSrcRect + Rectangle within the alpha mask to take the pixel from. + Please note that the destination rectangle is interpreted + excluding the rightmost pixel column and the bottommost pixel + row, this is much like polygon filling. As a result, filling a + given rectangle with fillPolyPolygon(), and using the same + rectangle as the source rectangle of this method, will affect + exactly the same set of pixel. + + @param rDstPoint + Destination point, where to start placing the pixel from the + source rectangle + */ + void drawMaskedColor( Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ); + + /** Draw a color with an alpha-modulation bitmap into this device + + This method takes a fixed color value, and an alpha mask. For + each pixel in the alpha mask, the given color value is blended + with the corresponding alpha value against the content of this + object. + + @param aSrcColor + Color value to use for blending + + @param rAlphaMask + Alpha mask to use for blending. It is permitted that alpha + mask and this bitmap are the same object. + + @param rSrcRect + Rectangle within the alpha mask to take the pixel from. + Please note that the destination rectangle is interpreted + excluding the rightmost pixel column and the bottommost pixel + row, this is much like polygon filling. As a result, filling a + given rectangle with fillPolyPolygon(), and using the same + rectangle as the source rectangle of this method, will affect + exactly the same set of pixel. + + @param rDstPoint + Destination point, where to start placing the pixel from the + source rectangle + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void drawMaskedColor( Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ); + + /** Draw another bitmap through a mask into this device + + This method renders a source bitmap into this device, much + like the drawBitmap() method. The only difference is the + additional mask parameter, which operates much like an + additional clip mask: pixel with value zero in this mask + result in destination pixel not being modified. + + @param rSrcBitmap + Bitmap to render into this one. It is permitted that source + and destination bitmap are the same. + + @param rMask + Bitmap to use as a mask. Pixel with value != zero in this mask + will result in destination pixel not being affected by the + blit operation. + + @param rSrcRect + Rectangle within the source bitmap to take the pixel from. + + @param rDstRect + Rectangle in the destination bitmap to put the pixel + into. Source and destination rectangle are permitted to have + differing sizes; this method will scale the source pixel + accordingly. Please note that both source and destination + rectangle are interpreted excluding the rightmost pixel column + and the bottommost pixel row, this is much like polygon + filling. As a result, filling a given rectangle with + fillPolyPolygon(), and using the same rectangle as the + destination rectangle of this method, will affect exactly the + same set of pixel. + + @param drawMode + Draw mode to use when changing pixel values + */ + void drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ); + + /** Draw another bitmap through a mask into this device + + This method renders a source bitmap into this device, much + like the drawBitmap() method. The only difference is the + additional mask parameter, which operates much like an + additional clip mask: pixel with value != zero in this mask + result in destination pixel not being modified. + + @param rSrcBitmap + Bitmap to render into this one. It is permitted that source + and destination bitmap are the same. + + @param rMask + Bitmap to use as a mask. Pixel with value != zero in this mask + will result in destination pixel not being affected by the + blit operation. + + @param rSrcRect + Rectangle within the source bitmap to take the pixel from. + + @param rDstRect + Rectangle in the destination bitmap to put the pixel + into. Source and destination rectangle are permitted to have + differing sizes; this method will scale the source pixel + accordingly. Please note that both source and destination + rectangle are interpreted excluding the rightmost pixel column + and the bottommost pixel row, this is much like polygon + filling. As a result, filling a given rectangle with + fillPolyPolygon(), and using the same rectangle as the + destination rectangle of this method, will affect exactly the + same set of pixel. + + @param drawMode + Draw mode to use when changing pixel values + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 1 will not be modified. + */ + void drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + +protected: + BitmapDevice( const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + const RawMemorySharedArray& rMem, + const PaletteMemorySharedVector& rPalette, + BitmapDeviceDamageTracker* pDamage = NULL ); + + virtual ~BitmapDevice(); + +private: + virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const = 0; + virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const = 0; + virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const = 0; + + virtual void clear_i( Color fillColor, + const basegfx::B2IRange& rBounds ) = 0; + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual Color getPixel_i( const basegfx::B2IPoint& rPt ) = 0; + + virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt ) = 0; + + virtual void drawLine_i( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void drawLine_i( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual void drawPolygon_i( const basegfx::B2DPolygon& rPoly, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void drawPolygon_i( const basegfx::B2DPolygon& rPoly, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual void fillPolyPolygon_i( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds ) = 0; + virtual void fillPolyPolygon_i( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) = 0; + virtual void drawBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawMaskedColor_i( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ) = 0; + virtual void drawMaskedColor_i( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawMaskedBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) = 0; + virtual void drawMaskedBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + BitmapDeviceSharedPtr getGenericRenderer() const; + + boost::scoped_ptr< ImplBitmapDevice > mpImpl; +}; + +/** Factory method to create a BitmapDevice for given scanline format + */ +BASEBMP_DLLPUBLIC BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + BitmapDeviceDamageTracker* pDamage = NULL ); + +/** Factory method to create a BitmapDevice for given scanline format + with the given palette + + Note: the provided palette must have sufficient size, to satisfy + lookups for the whole range of pixel values from the specified + format. + */ +BASEBMP_DLLPUBLIC BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + const PaletteMemorySharedVector& rPalette ); + +/** Factory method to create a BitmapDevice for given scanline format + from the given piece of raw memory and palette + + Note: the provided memory must have sufficient size, to store the + image of the specified area and format. + */ +BASEBMP_DLLPUBLIC BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + const RawMemorySharedArray& rMem, + const PaletteMemorySharedVector& rPalette ); + + +/** Factory method to retrieve a subsetted BitmapDevice to the same + memory. + + This method creates a second bitmap device instance, which renders + to the same memory as the original, but to a limited, rectangular + area. Useful to implement rectangular clips (usually faster than + setting up a 1bpp clip mask). + */ +BASEBMP_DLLPUBLIC BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto, + const basegfx::B2IRange& rSubset ); + +/** Factory method to clone a BitmapDevice from a given prototype. + + All attributes (like scanline format and top-down state) are + copied, only the size can be varied. Note that the prototype's + bitmap content is <em>not</em> copied, only a palette (if any). + */ +BASEBMP_DLLPUBLIC BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize, + const BitmapDeviceSharedPtr& rProto ); + +} + +#endif /* INCLUDED_BASEBMP_BITMAPDEVICE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/clippedlinerenderer.hxx b/basebmp/inc/basebmp/clippedlinerenderer.hxx new file mode 100644 index 000000000000..e023581416d6 --- /dev/null +++ b/basebmp/inc/basebmp/clippedlinerenderer.hxx @@ -0,0 +1,415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX +#define INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX + +#include <basegfx/tools/rectcliptools.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/range/b2irange.hxx> + +#include <vigra/diff2d.hxx> +#include <vigra/iteratortraits.hxx> + +namespace basebmp +{ + +// factored-out bresenham setup code, which is used from two different +// places in renderClippedLine() below. Admittedly messy for the long +// parameter list... +inline bool prepareClip( sal_Int32 a1, + sal_Int32 a2, + sal_Int32 b1, + sal_Int32 da, + sal_Int32 db, + sal_Int32& o_as, + sal_Int32& o_bs, + int sa, + int sb, + sal_Int32& io_rem, + int& o_n, + sal_uInt32 clipCode1, + sal_uInt32 clipCount1, + sal_uInt32 clipCode2, + sal_uInt32 clipCount2, + sal_Int32 aMin, + sal_uInt32 aMinFlag, + sal_Int32 aMax, + sal_uInt32 aMaxFlag, + sal_Int32 bMin, + sal_uInt32 bMinFlag, + sal_Int32 bMax, + sal_uInt32 bMaxFlag, + bool bRoundTowardsPt2 ) +{ + int ca(0), cb(0); + if( clipCode1 ) + { + if( clipCode1 & aMinFlag ) + { + ca = 2*db*(aMin - a1); + o_as = aMin; + } + else if( clipCode1 & aMaxFlag ) + { + ca = 2*db*(a1 - aMax); + o_as = aMax; + } + + if( clipCode1 & bMinFlag ) + { + cb = 2*da*(bMin - b1); + o_bs = bMin; + } + else if( clipCode1 & bMaxFlag ) + { + cb = 2*da*(b1 - bMax); + o_bs = bMax; + } + + if( clipCount1 == 2 ) + clipCode1 &= (ca + da < cb + !bRoundTowardsPt2) ? ~(aMinFlag|aMaxFlag) : ~(bMinFlag|bMaxFlag); + + if( clipCode1 & (aMinFlag|aMaxFlag) ) + { + cb = (ca + da - !bRoundTowardsPt2) / (2*da); + + if( sb >= 0 ) + { + o_bs = b1 + cb; + if( o_bs > bMax ) + return false; + } + else + { + o_bs = b1 - cb; + if( o_bs < bMin ) + return false; + } + + io_rem += ca - 2*da*cb; + } + else + { + ca = (cb - da + 2*db - bRoundTowardsPt2) / (2*db); + if( sa >= 0 ) + { + o_as = a1 + ca; + if( o_as > aMax ) + return false; + } + else + { + o_as = a1 - ca; + if( o_as < aMin ) + return false; + } + + io_rem += 2*db*ca - cb; + } + } + else + { + o_as = a1; o_bs = b1; + } + + bool bRetVal = false; + if( clipCode2 ) + { + if( clipCount2 == 2 ) + { + ca = 2*db*((clipCode2 & aMinFlag) ? a1 - aMin : aMax - a1); + cb = 2*da*((clipCode2 & bMinFlag) ? b1 - bMin : bMax - b1); + clipCode2 &= (cb + da < ca + bRoundTowardsPt2) ? ~(aMinFlag|aMaxFlag) : ~(bMinFlag|bMaxFlag); + } + + if( clipCode2 & (aMinFlag|aMaxFlag) ) + o_n = (clipCode2 & aMinFlag) ? o_as - aMin : aMax - o_as; + else + { + o_n = (clipCode2 & bMinFlag) ? o_bs - bMin : bMax - o_bs; + bRetVal = true; + } + } + else + o_n = (a2 >= o_as) ? a2 - o_as : o_as - a2; + + return bRetVal; +} + + +/** Render line to image iterators, clip against given rectangle + + This method renders a line from aPt1 to aPt2, clipped against + rClipRect (the clipping will take place pixel-perfect, i.e. as if + the original bresenham-rendered line would have been clipped each + pixel individually. No slight shifts compared to unclipped lines). + + @param aPt1 + Start point of the line + + @param aPt2 + End point of the line + + @param rClipRect + Rectangle to clip against + + @param color + Color value to render the line with + + @param begin + left-top image iterator + + @param end + right-bottom image iterator + + @param acc + Image accessor + + @param bRoundTowardsPt2 + Rounding mode to use. Giving false here results in line pixel tend + towards pt1, i.e. when a pixel exactly hits the middle between two + pixel, the pixel closer to pt1 will be chosen. Giving true here + makes renderClippedLine() choose pt2 in those cases. + */ +template< class Iterator, class Accessor > +void renderClippedLine( basegfx::B2IPoint aPt1, + basegfx::B2IPoint aPt2, + const basegfx::B2IRange& rClipRect, + typename Accessor::value_type color, + Iterator begin, + Accessor acc, + bool bRoundTowardsPt2=false ) +{ + // Algorithm according to Steven Eker's 'Pixel-perfect line clipping', + // Graphics Gems V, pp. 314-322 + sal_uInt32 clipCode1 = basegfx::tools::getCohenSutherlandClipFlags(aPt1, + rClipRect); + sal_uInt32 clipCode2 = basegfx::tools::getCohenSutherlandClipFlags(aPt2, + rClipRect); + + if( clipCode1 & clipCode2 ) + return; // line fully clipped away + + sal_uInt32 clipCount1 = basegfx::tools::getNumberOfClipPlanes(clipCode1); + sal_uInt32 clipCount2 = basegfx::tools::getNumberOfClipPlanes(clipCode2); + + if( (clipCode1 != 0 && clipCode2 == 0) + || (clipCount1 == 2 && clipCount2 == 1) ) + { + std::swap(clipCount2,clipCount1); + std::swap(clipCode2,clipCode1); + std::swap(aPt1,aPt2); + bRoundTowardsPt2 = !bRoundTowardsPt2; + } + + const sal_Int32 x1 = aPt1.getX(); + const sal_Int32 x2 = aPt2.getX(); + const sal_Int32 y1 = aPt1.getY(); + const sal_Int32 y2 = aPt2.getY(); + + // TODO(E1): This might overflow + sal_Int32 adx = x2 - x1; + int sx = 1; + if( adx < 0 ) + { + adx *= -1; + sx = -1; + } + + // TODO(E1): This might overflow + sal_Int32 ady = y2 - y1; + int sy = 1; + if( ady < 0 ) + { + ady *= -1; + sy = -1; + } + + int n = 0; + sal_Int32 xs = x1; + sal_Int32 ys = y1; + if( adx >= ady ) + { + // semi-horizontal line + sal_Int32 rem = 2*ady - adx - !bRoundTowardsPt2; + + const bool bUseAlternateBresenham( + prepareClip(x1, x2, y1, adx, ady, xs, ys, sx, sy, + rem, n, clipCode1, clipCount1, clipCode2, clipCount2, + rClipRect.getMinX(), basegfx::tools::RectClipFlags::LEFT, + rClipRect.getMaxX(), basegfx::tools::RectClipFlags::RIGHT, + rClipRect.getMinY(), basegfx::tools::RectClipFlags::TOP, + rClipRect.getMaxY(), basegfx::tools::RectClipFlags::BOTTOM, + bRoundTowardsPt2 )); + + Iterator currIter( begin + vigra::Diff2D(0,ys) ); + typename vigra::IteratorTraits<Iterator>::row_iterator + rowIter( currIter.rowIterator() + xs ); + + adx *= 2; + ady *= 2; + + if( bUseAlternateBresenham ) + { + while(true) + { + acc.set(color, rowIter); + + if( rem >= 0 ) + { + if( --n < 0 ) + break; + + ys += sy; + xs += sx; + rem -= adx; + + currIter.y += sy; + rowIter = currIter.rowIterator() + xs; + } + else + { + xs += sx; + rowIter += sx; + } + + rem += ady; + } + } + else + { + while(true) + { + acc.set(color, rowIter); + + if( --n < 0 ) + break; + + if( rem >= 0 ) + { + ys += sy; + xs += sx; + rem -= adx; + + currIter.y += sy; + rowIter = currIter.rowIterator() + xs; + } + else + { + xs += sx; + rowIter += sx; + } + + rem += ady; + } + } + } + else + { + // semi-vertical line + sal_Int32 rem = 2*adx - ady - !bRoundTowardsPt2; + + const bool bUseAlternateBresenham( + prepareClip(y1, y2, x1, ady, adx, ys, xs, sy, sx, + rem, n, clipCode1, clipCount1, clipCode2, clipCount2, + rClipRect.getMinY(), basegfx::tools::RectClipFlags::TOP, + rClipRect.getMaxY(), basegfx::tools::RectClipFlags::BOTTOM, + rClipRect.getMinX(), basegfx::tools::RectClipFlags::LEFT, + rClipRect.getMaxX(), basegfx::tools::RectClipFlags::RIGHT, + bRoundTowardsPt2 )); + + Iterator currIter( begin + vigra::Diff2D(xs,0) ); + typename vigra::IteratorTraits<Iterator>::column_iterator + colIter( currIter.columnIterator() + ys ); + + adx *= 2; + ady *= 2; + + if( bUseAlternateBresenham ) + { + while(true) + { + acc.set(color, colIter); + + if( rem >= 0 ) + { + if( --n < 0 ) + break; + + xs += sx; + ys += sy; + rem -= ady; + + currIter.x += sx; + colIter = currIter.columnIterator() + ys; + } + else + { + ys += sy; + colIter += sy; + } + + rem += adx; + } + } + else + { + while(true) + { + acc.set(color, colIter); + + if( --n < 0 ) + break; + + if( rem >= 0 ) + { + xs += sx; + ys += sy; + rem -= ady; + + currIter.x += sx; + colIter = currIter.columnIterator() + ys; + } + else + { + ys += sy; + colIter += sy; + } + + rem += adx; + } + } + } +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/color.hxx b/basebmp/inc/basebmp/color.hxx new file mode 100644 index 000000000000..1bd70198a280 --- /dev/null +++ b/basebmp/inc/basebmp/color.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COLOR_HXX +#define INCLUDED_BASEBMP_COLOR_HXX + +#include <sal/types.h> +#include <rtl/math.hxx> + +namespace basebmp +{ + +class Color +{ +private: + sal_uInt32 mnColor; + +public: + typedef sal_uInt32 value_type; + typedef sal_uInt8 component_type; + + Color() : mnColor(0) {} + explicit Color( sal_uInt32 nVal ) : mnColor(nVal) {} + Color( sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue ) : + mnColor( ((sal_uInt32)nRed << 16) | ((sal_uInt32)nGreen << 8) | nBlue ) + {} + + void setRed( sal_uInt8 nRed ) { mnColor &= ~0x00FF0000UL; mnColor |= (sal_uInt32)nRed << 16; } + void setGreen( sal_uInt8 nGreen ) { mnColor &= ~0x0000FF00UL; mnColor |= (sal_uInt32)nGreen << 8; } + void setBlue( sal_uInt8 nBlue ) { mnColor &= ~0x000000FFUL; mnColor |= nBlue; } + + void setGrey( sal_uInt8 nGreyVal ) { mnColor = (sal_uInt32)nGreyVal << 16 | (sal_uInt32)nGreyVal << 8 | nGreyVal; } + + sal_uInt8 getRed() const { return 0xFF & (sal_uInt8)(mnColor >> 16); } + sal_uInt8 getGreen() const { return 0xFF & (sal_uInt8)(mnColor >> 8); } + sal_uInt8 getBlue() const { return 0xFF & (sal_uInt8)mnColor; } + + sal_uInt8 getGreyscale() const { return (sal_uInt8)((getBlue()*28UL + + getGreen()*151 + + getRed()*77) / 256); } + + sal_uInt32 toInt32() const { return mnColor; } + + bool operator!() const { return mnColor == 0; } + Color operator&( sal_uInt32 nMask ) const { return Color(mnColor & nMask); } + Color operator^( Color col ) const { return Color(col.getRed()^getRed(), + col.getGreen()^getGreen(), + col.getBlue()^getBlue()); } + Color operator-( Color col ) const { return Color((sal_uInt8)abs((int)getRed()-col.getRed()), + (sal_uInt8)abs((int)getGreen()-col.getGreen()), + (sal_uInt8)abs((int)getBlue()-col.getBlue())); } + Color operator+( Color col ) const { return Color(getRed()+col.getRed(), + getGreen()+col.getGreen(), + getBlue()+col.getBlue()); } + Color operator*( Color col ) const { return Color((sal_uInt8)((sal_uInt32)col.getRed()*getRed()/SAL_MAX_UINT8), + (sal_uInt8)((sal_uInt32)col.getGreen()*getGreen()/SAL_MAX_UINT8), + (sal_uInt8)((sal_uInt32)col.getBlue()*getBlue()/SAL_MAX_UINT8)); } + Color operator*( sal_uInt8 n ) const { return Color((sal_uInt8)((sal_uInt32)n*getRed()/SAL_MAX_UINT8), + (sal_uInt8)((sal_uInt32)n*getGreen()/SAL_MAX_UINT8), + (sal_uInt8)((sal_uInt32)n*getBlue()/SAL_MAX_UINT8)); } + Color operator*( double n ) const { return Color((sal_uInt8)(n*getRed()+.5), + (sal_uInt8)(n*getGreen()+.5), + (sal_uInt8)(n*getBlue()+.5)); } + bool operator==( const Color& rhs ) const { return (getRed()==rhs.getRed() && + getGreen()==rhs.getGreen() && + getBlue()==rhs.getBlue()); } + bool operator!=( const Color& rhs ) const { return !(*this==rhs); } + double magnitude() const { return sqrt((double)getRed()*getRed() + + getGreen()*getGreen() + + getBlue()*getBlue()); } +}; + +} // namespace vigra + +#endif /* INCLUDED_BASEBMP_COLOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/colorblendaccessoradapter.hxx b/basebmp/inc/basebmp/colorblendaccessoradapter.hxx new file mode 100644 index 000000000000..4bb913500bd9 --- /dev/null +++ b/basebmp/inc/basebmp/colorblendaccessoradapter.hxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COLORBLENDACCESSORADAPTER_HXX +#define INCLUDED_BASEBMP_COLORBLENDACCESSORADAPTER_HXX + +#include <basebmp/colortraits.hxx> + +namespace basebmp +{ + +/** Accessor adapter that blends input value against fixed color value + + Used to blend an alpha mask 'through' a fixed color value into the + destination. + + The getter functors return a constant value (usually the zero of + the value type, this preserves the original destination content + when blitting through a mask) - there really isn't no other + sensible default behaviour for these methods. + */ +template< class WrappedAccessor, + typename AlphaType, + bool polarity > class ConstantColorBlendSetterAccessorAdapter +{ +public: + typedef AlphaType alpha_type; + typedef AlphaType value_type; + typedef typename WrappedAccessor::value_type color_type; + +private: + typename ColorTraits< color_type >:: + template blend_functor<alpha_type,polarity>::type maFunctor; + WrappedAccessor maWrappee; + color_type maBlendColor; + value_type maGetterValue; + +public: + ConstantColorBlendSetterAccessorAdapter() : + maFunctor(), + maWrappee(), + maBlendColor(), + maGetterValue() + {} + + template< class T > explicit ConstantColorBlendSetterAccessorAdapter( T acc ) : + maFunctor(), + maWrappee(acc), + maBlendColor(), + maGetterValue() + {} + + template< class T > ConstantColorBlendSetterAccessorAdapter( T acc, + color_type col ) : + maFunctor(), + maWrappee(acc), + maBlendColor(col), + maGetterValue() + {} + + template< class T > ConstantColorBlendSetterAccessorAdapter( T acc, + color_type col, + value_type val ) : + maFunctor(), + maWrappee(acc), + maBlendColor(col), + maGetterValue(val) + {} + + // ------------------------------------------------------- + + void setColor( color_type col ) { maBlendColor=col; } + color_type getColor() { return maBlendColor; } + void setGetterValue( value_type val ) { maGetterValue=val; } + value_type getGetterValue() { return maGetterValue; } + + // ------------------------------------------------------- + + WrappedAccessor const& getWrappedAccessor() const { return maWrappee; } + WrappedAccessor& getWrappedAccessor() { return maWrappee; } + + // ------------------------------------------------------- + + /// @return constant value, regardless of iterator content + template< typename IteratorType > value_type operator()(IteratorType const& ) const + { + return maGetterValue; + } + /// @return constant value, regardless of iterator content + template< typename IteratorType, class Difference > + value_type operator()(IteratorType const& , Difference const& ) const + { + return maGetterValue; + } + + // ------------------------------------------------------- + + template< typename V, typename IteratorType > + void set(V const& value, IteratorType const& i) const + { + maWrappee.set( + maFunctor( + vigra::detail::RequiresExplicitCast<alpha_type>::cast(value), + maWrappee(i), + maBlendColor), + i ); + } + + template< typename V, typename IteratorType, class Difference > + void set(V const& value, IteratorType const& i, Difference const& diff) const + { + maWrappee.set( + maFunctor( + vigra::detail::RequiresExplicitCast<alpha_type>::cast(value), + maWrappee(i,diff), + maBlendColor), + i, + diff ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_COLORBLENDACCESSORADAPTER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/colormisc.hxx b/basebmp/inc/basebmp/colormisc.hxx new file mode 100644 index 000000000000..96a312c251ae --- /dev/null +++ b/basebmp/inc/basebmp/colormisc.hxx @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COLORMISC_HXX +#define INCLUDED_BASEBMP_COLORMISC_HXX + +#include <osl/diagnose.h> +#include <basebmp/color.hxx> +#include <basebmp/colortraits.hxx> +#include <basebmp/accessortraits.hxx> +#include <vigra/mathutil.hxx> + +// Contents of this header moved out of color.hxx, as it is not useful +// for the general public (drags in vigra and other template +// functionality, that shouldn't be necessary for the ordinary client +// of BitmapDevice etc.) + +namespace basebmp +{ + +template< bool polarity > struct ColorBitmaskOutputMaskFunctor; +template<> struct ColorBitmaskOutputMaskFunctor<true> : MaskFunctorBase<Color,sal_uInt8> +{ + Color operator()( Color v1, sal_uInt8 m, Color v2 ) const + { + OSL_ASSERT(m<=1); + + return Color(v1.toInt32()*(sal_uInt8)(1-m) + v2.toInt32()*m); + } +}; +template<> struct ColorBitmaskOutputMaskFunctor<false> : MaskFunctorBase<Color,sal_uInt8> +{ + Color operator()( Color v1, sal_uInt8 m, Color v2 ) const + { + OSL_ASSERT(m<=1); + + return Color(v1.toInt32()*m + v2.toInt32()*(sal_uInt8)(1-m)); + } +}; + +/// Specialized output mask functor for Color value type +template<bool polarity> struct outputMaskFunctorSelector< Color, sal_uInt8, polarity, FastMask > +{ + typedef ColorBitmaskOutputMaskFunctor<polarity> type; +}; + +template< bool polarity > struct ColorBlendFunctor8 + : public TernaryFunctorBase<sal_uInt8,Color,Color,Color> +{ + Color operator()( sal_uInt8 alpha, + Color v1, + Color v2 ) const + { + alpha = polarity ? alpha : 255 - alpha; + + const sal_uInt8 v1_red( v1.getRed() ); + const sal_uInt8 v1_green( v1.getGreen() ); + const sal_uInt8 v1_blue( v1.getBlue() ); + + // using '>> 8' instead of '/ 0x100' is ill-advised (shifted + // value might be negative). Better rely on decent optimizer + // here... + return Color(((((sal_Int32)v2.getRed() - v1_red)*alpha) / 0x100) + v1_red, + ((((sal_Int32)v2.getGreen() - v1_green)*alpha) / 0x100) + v1_green, + ((((sal_Int32)v2.getBlue() - v1_blue)*alpha) / 0x100) + v1_blue); + } +}; + +template< bool polarity > struct ColorBlendFunctor32 + : public TernaryFunctorBase<Color,Color,Color,Color> +{ + Color operator()( Color input, + Color v1, + Color v2 ) const + { + sal_uInt8 alpha = input.getGreyscale(); + alpha = polarity ? alpha : 255 - alpha; + + const sal_uInt8 v1_red( v1.getRed() ); + const sal_uInt8 v1_green( v1.getGreen() ); + const sal_uInt8 v1_blue( v1.getBlue() ); + + // using '>> 8' instead of '/ 0x100' is ill-advised (shifted + // value might be negative). Better rely on decent optimizer + // here... + return Color(((((sal_Int32)v2.getRed() - v1_red)*alpha) / 0x100) + v1_red, + ((((sal_Int32)v2.getGreen() - v1_green)*alpha) / 0x100) + v1_green, + ((((sal_Int32)v2.getBlue() - v1_blue)*alpha) / 0x100) + v1_blue); + } +}; + +//----------------------------------------------------------------------------- + +template<> struct ColorTraits< Color > +{ + /// @return number of color channels + static int numChannels() { return 3; } + + /// Type of a color component (i.e. the type of an individual channel) + typedef sal_uInt8 component_type; + + /// Metafunction to select blend functor from color and alpha type + template< typename AlphaType, bool polarity > struct blend_functor; + + /// Calculate normalized distance between color c1 and c2 + static inline double distance( const Color& c1, + const Color& c2 ) + { + return (c1 - c2).magnitude(); + } + + static inline component_type toGreyscale( const Color& c ) + { + return c.getGreyscale(); + } + + static inline Color fromGreyscale( component_type c ) + { + return Color(c,c,c); + } +}; + +/// The version for plain 8 bit alpha +template<bool polarity> struct ColorTraits< Color >::blend_functor< sal_uInt8, polarity > +{ + typedef ColorBlendFunctor8<polarity> type; +}; + +/// The version taking grey value of a Color +template<bool polarity> struct ColorTraits< Color >::blend_functor< Color, polarity > +{ + typedef ColorBlendFunctor32<polarity> type; +}; + +} // namespace basebmp + +namespace vigra +{ + +template<> +struct NumericTraits<basebmp::Color> +{ + typedef basebmp::Color Type; + typedef basebmp::Color Promote; + typedef basebmp::Color RealPromote; + typedef std::complex<basebmp::Color> ComplexPromote; + typedef sal_uInt8 ValueType; + + typedef VigraTrueType isIntegral; + typedef VigraFalseType isScalar; + typedef VigraTrueType isSigned; + typedef VigraTrueType isOrdered; + typedef VigraFalseType isComplex; + + static Type zero() { return Type(); } + static Type one() { return Type(0x01010101); } + static Type nonZero() { return Type(0x01010101); } + + static Promote toPromote(const Type& v) { return v; } + static RealPromote toRealPromote(const Type& v) { return v; } + static Type fromPromote(const Promote& v) { return v; } + static Type fromRealPromote(const RealPromote& v) { return v; } +}; + +} // namespace vigra + +#endif /* INCLUDED_BASEBMP_COLORMISC_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/colortraits.hxx b/basebmp/inc/basebmp/colortraits.hxx new file mode 100644 index 000000000000..ba6a4cfeee27 --- /dev/null +++ b/basebmp/inc/basebmp/colortraits.hxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COLORTRAITS_HXX +#define INCLUDED_BASEBMP_COLORTRAITS_HXX + +#include <basebmp/accessoradapters.hxx> +#include <basebmp/metafunctions.hxx> + +#include <vigra/mathutil.hxx> + +namespace basebmp +{ + +/** Functor template, to calculate alpha blending between two + values. Float case. + + @tpl polarity + When true, 0 means fully transparent, and 1 fully opaque. And vice + versa. + */ +template< typename ValueType, + typename AlphaType, + bool polarity > struct BlendFunctor; +template< typename ValueType, + typename AlphaType > struct BlendFunctor<ValueType,AlphaType,true> + : public TernaryFunctorBase<AlphaType,ValueType,ValueType,ValueType> +{ + ValueType operator()( AlphaType alpha, + ValueType v1, + ValueType v2 ) const + { + const typename vigra::NumericTraits<AlphaType>::RealPromote fAlpha( + vigra::NumericTraits<AlphaType>::toRealPromote(alpha)); + return (vigra::NumericTraits<AlphaType>::one()-fAlpha)*v1 + fAlpha*v2; + } +}; +template< typename ValueType, + typename AlphaType > struct BlendFunctor<ValueType,AlphaType,false> + : public TernaryFunctorBase<AlphaType,ValueType,ValueType,ValueType> +{ + ValueType operator()( AlphaType alpha, + ValueType v1, + ValueType v2 ) const + { + const typename vigra::NumericTraits<AlphaType>::RealPromote fAlpha( + vigra::NumericTraits<AlphaType>::toRealPromote(alpha)); + return fAlpha*v1 + (vigra::NumericTraits<AlphaType>::one()-fAlpha)*v2; + } +}; + +/** Functor template, to calculate alpha blending between two + values. Integer case. + + @tpl polarity + When true, 0 means fully transparent, and 1 fully opaque. And vice + versa. + */ +template< typename ValueType, + typename AlphaType, + bool polarity > struct IntegerBlendFunctor; +template< typename ValueType, + typename AlphaType > struct IntegerBlendFunctor<ValueType,AlphaType,true> + : public TernaryFunctorBase<AlphaType,ValueType,ValueType,ValueType> +{ + ValueType operator()( AlphaType alpha, + ValueType v1, + ValueType v2 ) const + { + return (vigra::NumericTraits<AlphaType>::toPromote( + vigra::NumericTraits<AlphaType>::max()-alpha)*v1 + alpha*v2) / + vigra::NumericTraits<AlphaType>::max(); + } +}; +template< typename ValueType, + typename AlphaType > struct IntegerBlendFunctor<ValueType,AlphaType,false> + : public TernaryFunctorBase<AlphaType,ValueType,ValueType,ValueType> +{ + ValueType operator()( AlphaType alpha, + ValueType v1, + ValueType v2 ) const + { + return (alpha*v1 + + vigra::NumericTraits<AlphaType>::toPromote( + vigra::NumericTraits<AlphaType>::max()-alpha)*v2) / + vigra::NumericTraits<AlphaType>::max(); + } +}; + +//----------------------------------------------------------------------------- + +template< typename ColorType > struct ColorTraits +{ + /// Metafunction to select blend functor from color and alpha type + template< typename AlphaType, bool polarity > struct blend_functor : public + ifScalarIntegral< AlphaType, + IntegerBlendFunctor< ColorType, AlphaType, polarity >, + BlendFunctor< ColorType, AlphaType, polarity > > {}; + + /// @return number of color channels + static int numChannels() { return 1; } + + /// Type of a color component (i.e. the type of an individual channel) + typedef ColorType component_type; + + /// Calculate normalized distance between color c1 and c2 + static inline vigra::NormTraits<ColorType> distance( ColorType c1, + ColorType c2 ) + { + return vigra::norm(c1 - c2); + } + + static inline component_type toGreyscale( ColorType c ) + { + return c; + } + + static inline ColorType fromGreyscale( component_type c ) + { + return c; + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_COLORTRAITS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/compositeiterator.hxx b/basebmp/inc/basebmp/compositeiterator.hxx new file mode 100644 index 000000000000..e64cf0d8c093 --- /dev/null +++ b/basebmp/inc/basebmp/compositeiterator.hxx @@ -0,0 +1,370 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX +#define INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX + +#include <sal/types.h> +#include <osl/diagnose.h> + +#include <basebmp/nonstandarditerator.hxx> +#include <vigra/tuple.hxx> +#include <vigra/iteratortraits.hxx> + + +namespace basebmp +{ + +namespace detail +{ + template< typename T1, typename T2 > class ArithmeticProxy + { + public: + ArithmeticProxy(T1& val1, T2& val2) : + mpVal1( &val1 ), + mpVal2( &val2 ) + {} + + void operator++() { ++(*mpVal1); ++(*mpVal2); } + void operator++(int) { (*mpVal1)++; (*mpVal2)++; } + void operator--() { --(*mpVal1); --(*mpVal2); } + void operator--(int) { (*mpVal1)--; (*mpVal2)--; } + void operator+=(int d) {*mpVal1+=d; *mpVal2+=d; } + void operator-=(int d) {*mpVal1-=d; *mpVal2-=d; } + + bool operator==(ArithmeticProxy const & rhs) const + { return *mpVal1==*rhs.mpVal1 && *mpVal2==*rhs.mpVal2; } + + bool operator!=(ArithmeticProxy const & rhs) const + { return *mpVal1!=*rhs.mpVal1 || *mpVal2!=*rhs.mpVal2; } + + bool operator<(ArithmeticProxy const & rhs) const + { return *mpVal1<*rhs.mpVal1 && *mpVal2<*rhs.mpVal2; } + + bool operator<=(ArithmeticProxy const & rhs) const + { return *mpVal1<=*rhs.mpVal1 && *mpVal2<=*rhs.mpVal2; } + + bool operator>(ArithmeticProxy const & rhs) const + { return *mpVal1>*rhs.mpVal1 && *mpVal2>*rhs.mpVal2; } + + bool operator>=(ArithmeticProxy const & rhs) const + { return *mpVal1>=*rhs.mpVal1 && *mpVal2>=*rhs.mpVal2; } + + int operator-(ArithmeticProxy const & rhs) const + { return *mpVal1 - *rhs.mpVal1; } + + private: + T1* mpVal1; + T2* mpVal2; + }; + + template< typename Iterator1, + typename Iterator2, + typename ValueType, + typename DifferenceType, + typename IteratorCategory, + class Derived > + class CompositeIteratorBase : public NonStandardIterator + { + public: + typedef Iterator1 iterator1_type; + typedef Iterator2 iterator2_type; + typedef ValueType value_type; + typedef DifferenceType difference_type; + typedef IteratorCategory iterator_category; + + protected: + iterator1_type maIter1; + iterator2_type maIter2; + + private: + bool equal(CompositeIteratorBase const & rhs) const + { + return (maIter1 == rhs.maIter1) && (maIter2 == rhs.maIter2); + } + + public: + CompositeIteratorBase() : + maIter1(), + maIter2() + {} + + CompositeIteratorBase( const iterator1_type& rIter1, const iterator2_type& rIter2 ) : + maIter1( rIter1 ), + maIter2( rIter2 ) + {} + + bool operator==(Derived const & rhs) const + { + return equal(rhs); + } + + bool operator!=(Derived const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(Derived const & rhs) const + { + OSL_ASSERT( maIter1 - rhs.maIter1 == maIter2 - rhs.maIter2 ); + return maIter1 - rhs.maIter1; + } + + Derived & operator+=(difference_type const & s) + { + maIter1 += s; + maIter2 += s; + return static_cast<Derived&>(*this); + } + + Derived & operator-=(difference_type const & s) + { + maIter1 -= s; + maIter2 -= s; + return static_cast<Derived&>(*this); + } + + Derived operator+(difference_type const & s) const + { + Derived ret(static_cast<Derived const&>(*this)); + ret += s; + return ret; + } + + Derived operator-(difference_type const & s) const + { + Derived ret(static_cast<Derived const&>(*this)); + ret -= s; + return ret; + } + + Derived& operator++() + { + ++maIter1; + ++maIter2; + return static_cast<Derived&>(*this); + } + + Derived& operator--() + { + --maIter1; + --maIter2; + return static_cast<Derived&>(*this); + } + + Derived operator++(int) + { + Derived ret(static_cast<Derived const&>(*this)); + ++maIter1; + ++maIter2; + return ret; + } + + Derived operator--(int) + { + Derived ret(static_cast<Derived const&>(*this)); + --maIter1; + --maIter2; + return ret; + } + + value_type get() const + { + return value_type(maIter1.get(), + maIter2.get()); + } + + value_type get(difference_type const & d) const + { + return value_type(maIter1.get(d), + maIter2.get(d)); + } + + void set( value_type v ) const + { + maIter1.set(v); + maIter2.set(v); + } + + void set( value_type v, difference_type const & d ) const + { + maIter1.set(v,d); + maIter2.set(v,d); + } + + const iterator1_type& first() const { return maIter1; } + iterator1_type& first() { return maIter1; } + + const iterator2_type& second() const { return maIter2; } + iterator2_type& second() { return maIter2; } + }; +} + +/** Provide the composition of two 1D image iterators + + Use this template to compose two iterators into one (e.g. image + and mask). Operations are transitive, e.g. operator== only returns + true, if both wrapped iterator operator== have yielded true. + + Note that both iterators must have compatible difference types. To + avoid funny effects, iterator ranges given by a CompositeIterator + should consist of wrapped iterators of similar range + */ +template< typename Iterator1, + typename Iterator2, + typename ValueType, + typename DifferenceType, + typename IteratorCategory > +class CompositeIterator1D : + public detail::CompositeIteratorBase< Iterator1, + Iterator2, + ValueType, + DifferenceType, + IteratorCategory, + CompositeIterator1D<Iterator1, + Iterator2, + ValueType, + DifferenceType, + IteratorCategory> > +{ + typedef detail::CompositeIteratorBase< Iterator1, + Iterator2, + ValueType, + DifferenceType, + IteratorCategory, + CompositeIterator1D<Iterator1, + Iterator2, + ValueType, + DifferenceType, + IteratorCategory> > base_type; +public: + CompositeIterator1D() : + base_type() + {} + + CompositeIterator1D( const Iterator1& rIter1, + const Iterator2& rIter2 ) : + base_type( rIter1, rIter2 ) + {} +}; + +/** Provide the composition of two 2D image iterators + + Use this template to compose two iterators into one (e.g. image + and mask). Operations are transitive, e.g. operator== only returns + true, if both wrapped iterator operator== have yielded true. + + Note that both iterators must have compatible difference types. To + avoid funny effects, iterator ranges given by a CompositeIterator + should consist of wrapped iterators of similar range + */ +template< typename Iterator1, typename Iterator2 > class CompositeIterator2D : + public detail::CompositeIteratorBase< Iterator1, + Iterator2, + std::pair< + typename vigra::IteratorTraits<Iterator1>::value_type, + typename vigra::IteratorTraits<Iterator2>::value_type >, + typename vigra::IteratorTraits<Iterator1>::difference_type, + typename vigra::IteratorTraits<Iterator1>::iterator_category, + CompositeIterator2D<Iterator1, Iterator2> > +{ + typedef detail::CompositeIteratorBase< Iterator1, + Iterator2, + std::pair< + typename vigra::IteratorTraits<Iterator1>::value_type, + typename vigra::IteratorTraits<Iterator2>::value_type >, + typename vigra::IteratorTraits<Iterator1>::difference_type, + typename vigra::IteratorTraits<Iterator1>::iterator_category, + CompositeIterator2D<Iterator1, Iterator2> > base_type; +public: + typedef CompositeIterator1D< typename Iterator1::row_iterator, + typename Iterator2::row_iterator, + typename base_type::value_type, + int, + typename base_type::iterator_category > row_iterator; + typedef CompositeIterator1D< typename Iterator1::column_iterator, + typename Iterator2::column_iterator, + typename base_type::value_type, + int, + typename base_type::iterator_category > column_iterator; + + typedef detail::ArithmeticProxy< typename Iterator1::MoveX, + typename Iterator2::MoveX > MoveX; + typedef detail::ArithmeticProxy< typename Iterator1::MoveY, + typename Iterator2::MoveY > MoveY; + + MoveX x; + MoveY y; + + CompositeIterator2D() : + base_type(), + x(this->maIter1.x,this->maIter2.x), + y(this->maIter1.y,this->maIter2.y) + {} + + CompositeIterator2D( const Iterator1& rIter1, const Iterator2& rIter2 ) : + base_type( rIter1, rIter2 ), + x(this->maIter1.x,this->maIter2.x), + y(this->maIter1.y,this->maIter2.y) + {} + + CompositeIterator2D( const CompositeIterator2D& rOld ) : + base_type(rOld), + x(this->maIter1.x,this->maIter2.x), + y(this->maIter1.y,this->maIter2.y) + {} + + CompositeIterator2D& operator=( const CompositeIterator2D& rNew ) + { + this->maIter1 = rNew.maIter1; + this->maIter2 = rNew.maIter2; + + x = MoveX(this->maIter1.x, + this->maIter2.x); + y = MoveY(this->maIter1.y, + this->maIter2.y); + } + + row_iterator rowIterator() const + { + return row_iterator(this->maIter1.rowIterator(), + this->maIter2.rowIterator()); + } + + column_iterator columnIterator() const + { + return column_iterator(this->maIter1.columnIterator(), + this->maIter2.columnIterator()); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_COMPOSITEITERATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/debug.hxx b/basebmp/inc/basebmp/debug.hxx new file mode 100644 index 000000000000..c5660b9a6a74 --- /dev/null +++ b/basebmp/inc/basebmp/debug.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_DEBUG_HXX +#define INCLUDED_BASEBMP_DEBUG_HXX + +#include <iostream> +#include <boost/shared_ptr.hpp> + +namespace basebmp +{ + class BitmapDevice; + + /** Dump content of BitmapDevice to given output stream. + + @param rDevice + Device whose content should be dumped. + + @param rOutputStream + Stream to write output to. + */ + void debugDump( const boost::shared_ptr< BitmapDevice >& rDevice, + ::std::ostream& rOutputStream ); +} + +#endif /* INCLUDED_BASEBMP_DEBUG_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/drawmodes.hxx b/basebmp/inc/basebmp/drawmodes.hxx new file mode 100644 index 000000000000..7e59f81b6140 --- /dev/null +++ b/basebmp/inc/basebmp/drawmodes.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_DRAWMODES_HXX +#define INCLUDED_BASEBMP_DRAWMODES_HXX + +/* Definition of Draw modes */ + +namespace basebmp +{ + enum DrawMode + { + /** Default draw mode, which simply renders pixel in the + requested color + */ + DrawMode_PAINT, + + /** XOR draw mode, which XORs each existing pixel value with + the new color. + + The result of this XOR operation strongly depends on the + underlying pixel format, as it is defined by the bitwise + XOR of the (potentially palette-looked-up) color value and + the existing pixel content (being it true color or a + palette index). + */ + DrawMode_XOR + }; +} + +#endif /* INCLUDED_BASEBMP_DRAWMODES_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/endian.hxx b/basebmp/inc/basebmp/endian.hxx new file mode 100644 index 000000000000..03a0dbeb9fbf --- /dev/null +++ b/basebmp/inc/basebmp/endian.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ENDIAN_HXX +#define INCLUDED_BASEBMP_ENDIAN_HXX + +#include <osl/endian.h> + +namespace basebmp +{ + +/// Swap the order of bytes for the given POD type +template< typename T > inline T byteSwap( T ); + +#define BASEBMP_BYTE_SWAP(Type,SwapFunc) \ + template<> inline Type byteSwap<Type>( Type v ) \ + { \ + return SwapFunc(v); \ + } + +// byteSwap<T> shall fail for any type T not in the list below +BASEBMP_BYTE_SWAP(sal_Int8,) +BASEBMP_BYTE_SWAP(sal_uInt8,) +BASEBMP_BYTE_SWAP(sal_Int16,OSL_SWAPWORD) +BASEBMP_BYTE_SWAP(sal_uInt16,OSL_SWAPWORD) +BASEBMP_BYTE_SWAP(sal_Int32,OSL_SWAPDWORD) +BASEBMP_BYTE_SWAP(sal_uInt32,OSL_SWAPDWORD) + +#undef BASEBMP_BYTE_SWAP + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ENDIAN_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/fillimage.hxx b/basebmp/inc/basebmp/fillimage.hxx new file mode 100644 index 000000000000..d3809ecc0b6e --- /dev/null +++ b/basebmp/inc/basebmp/fillimage.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_FILLIMAGE_HXX +#define INCLUDED_BASEBMP_FILLIMAGE_HXX + +#include <vigra/tuple.hxx> +#include <vigra/iteratortraits.hxx> + +namespace basebmp +{ + +template< class DestIterator, class DestAccessor, typename T > +void fillImage( DestIterator begin, + DestIterator end, + DestAccessor ad, + T fillVal ) +{ + const int width ( end.x - begin.x ); + const int height( end.y - begin.y ); + + for( int y=0; y<height; ++y, ++begin.y ) + { + typename vigra::IteratorTraits<DestIterator>::row_iterator + rowIter( begin.rowIterator() ); + const typename vigra::IteratorTraits<DestIterator>::row_iterator + rowEnd( rowIter + width ); + + // TODO(P2): Provide specialized span fill methods on the + // iterator/accessor + while( rowIter != rowEnd ) + ad.set(fillVal, rowIter++); + } +} + +template< class DestIterator, class DestAccessor, typename T > +inline void fillImage( vigra::triple<DestIterator,DestIterator,DestAccessor> const& src, + T fillVal ) +{ + fillImage(src.first,src.second,src.third,fillVal); +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_FILLIMAGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/genericcolorimageaccessor.hxx b/basebmp/inc/basebmp/genericcolorimageaccessor.hxx new file mode 100644 index 000000000000..2fada3948faf --- /dev/null +++ b/basebmp/inc/basebmp/genericcolorimageaccessor.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_GENERICCOLORIMAGEACCESSOR_HXX +#define INCLUDED_BASEBMP_GENERICCOLORIMAGEACCESSOR_HXX + +#include <basebmp/color.hxx> +#include <basebmp/bitmapdevice.hxx> + +namespace basebmp +{ + /** Access a BitmapDevice generically + + This accessor deals with an opaque BitmapDevice generically, + via getPixel()/setPixel() at the published interface. + */ + class GenericColorImageAccessor + { + BitmapDeviceSharedPtr mpDevice; + DrawMode meDrawMode; + + public: + typedef Color value_type; + + explicit GenericColorImageAccessor( BitmapDeviceSharedPtr const& rTarget ) : + mpDevice(rTarget), + meDrawMode(DrawMode_PAINT) + {} + + GenericColorImageAccessor( BitmapDeviceSharedPtr const& rTarget, + DrawMode eDrawMode ) : + mpDevice(rTarget), + meDrawMode(eDrawMode) + {} + + template< typename Iterator > + Color operator()( Iterator const& i ) const + { return mpDevice->getPixel( basegfx::B2IPoint( i->x,i->y ) ); } + + template< typename Iterator, typename Difference > + Color operator()( Iterator const& i, Difference const& diff) const + { return mpDevice->getPixel( basegfx::B2IPoint( i[diff]->x, + i[diff]->y ) ); } + + template< typename Iterator > + void set(Color const& value, Iterator const& i) const + { return mpDevice->setPixel( basegfx::B2IPoint( i->x,i->y ), + value, meDrawMode ); } + + template< class Iterator, class Difference > + void set(value_type const& value, Iterator const& i, Difference const& diff) const + { return mpDevice->setPixel( basegfx::B2IPoint( i[diff]->x, + i[diff]->y ), + value, meDrawMode ); } + }; +} + +#endif /* INCLUDED_BASEBMP_GENERICCOLORIMAGEACCESSOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/greylevelformats.hxx b/basebmp/inc/basebmp/greylevelformats.hxx new file mode 100644 index 000000000000..111fcc7e12fd --- /dev/null +++ b/basebmp/inc/basebmp/greylevelformats.hxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_GREYLEVELFORMATS_HXX +#define INCLUDED_BASEBMP_GREYLEVELFORMATS_HXX + +#include <basebmp/color.hxx> +#include <basebmp/colortraits.hxx> +#include <basebmp/accessor.hxx> +#include <basebmp/pixeliterator.hxx> +#include <basebmp/packedpixeliterator.hxx> +#include <basebmp/pixelformatadapters.hxx> +#include <basebmp/metafunctions.hxx> + +#include <vigra/numerictraits.hxx> +#include <vigra/metaprogramming.hxx> + +#include <functional> + +namespace basebmp +{ + +template< typename PixelType, + typename ColorType, + int UsedRange > struct GreylevelGetter : + public std::unary_function<PixelType, ColorType> +{ + ColorType operator()( PixelType const& c ) const + { + return ColorTraits<ColorType>::fromGreyscale( + vigra::NumericTraits<PixelType>::toPromote(c) * + vigra::NumericTraits<PixelType>::maxConst / UsedRange ); + } +}; + +template< typename PixelType, + typename ColorType, + int UsedRange > struct GreylevelSetter : + public std::unary_function<ColorType, PixelType> +{ + PixelType operator()( ColorType const& c ) const + { + return vigra::NumericTraits<PixelType>::toPromote( + ColorTraits<ColorType>::toGreyscale(c)) * + UsedRange / + vigra::NumericTraits<PixelType>::maxConst; + } +}; + +//----------------------------------------------------------------------------- + +template< class Iterator, + class Accessor, + int UsedRange > struct PixelFormatTraitsTemplate_Greylevel +{ + typedef typename Iterator::value_type pixel_type; + + typedef GreylevelGetter<pixel_type, + Color, + UsedRange> getter_type; + typedef GreylevelSetter<pixel_type, + Color, + UsedRange> setter_type; + + typedef Iterator iterator_type; + typedef Accessor raw_accessor_type; + typedef AccessorSelector< + getter_type, + setter_type > accessor_selector; +}; + +template< int BitsPerPixel, + bool MsbFirst > struct PixelFormatTraitsTemplate_PackedGreylevel : + public PixelFormatTraitsTemplate_Greylevel< + PackedPixelIterator< sal_uInt8, + BitsPerPixel, + true >, + NonStandardAccessor< sal_uInt8 >, + (1UL << BitsPerPixel)-1 > +{}; + +//----------------------------------------------------------------------------- + +// 1bpp MSB +typedef PixelFormatTraitsTemplate_PackedGreylevel<1, true> PixelFormatTraits_GREY1_MSB; + +// 1bpp LSB +typedef PixelFormatTraitsTemplate_PackedGreylevel<1, false> PixelFormatTraits_GREY1_LSB; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_GREY1_MSB::getter_type, + PixelFormatTraits_GREY1_MSB::setter_type); + + +// 4bpp MSB +typedef PixelFormatTraitsTemplate_PackedGreylevel<4, true> PixelFormatTraits_GREY4_MSB; + +// 4bpp LSB +typedef PixelFormatTraitsTemplate_PackedGreylevel<4, false> PixelFormatTraits_GREY4_LSB; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_GREY4_MSB::getter_type, + PixelFormatTraits_GREY4_MSB::setter_type); + +// 8bpp +typedef PixelFormatTraitsTemplate_Greylevel< + PixelIterator< sal_uInt8 >, + StandardAccessor< sal_uInt8 >, + 255 > PixelFormatTraits_GREY8; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_GREY8::getter_type, + PixelFormatTraits_GREY8::setter_type); + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_GREYLEVELFORMATS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/iteratortraits.hxx b/basebmp/inc/basebmp/iteratortraits.hxx new file mode 100644 index 000000000000..ac76a3ebf783 --- /dev/null +++ b/basebmp/inc/basebmp/iteratortraits.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ITERATORTRAITS_HXX +#define INCLUDED_BASEBMP_ITERATORTRAITS_HXX + +#include <basebmp/accessor.hxx> +#include <basebmp/nonstandarditerator.hxx> + +namespace basebmp +{ + +template< class Iterator > struct IteratorTraits +{ + /// VigraTrueType, if iterator does not provide *operator()/operator[] methods + typedef typename vigra::IsDerivedFrom<Iterator,NonStandardIterator>::result + isNonStandardIterator; + + /// Retrieve default accessor for this iterator (and given value type) + template< typename ValueType > struct defaultAccessor : public + // select according to non-standardness of iterator type + vigra::If< isNonStandardIterator, + NonStandardAccessor< ValueType >, + StandardAccessor< ValueType > > + {}; + +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ITERATORTRAITS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/linerenderer.hxx b/basebmp/inc/basebmp/linerenderer.hxx new file mode 100644 index 000000000000..5e3d4df30b88 --- /dev/null +++ b/basebmp/inc/basebmp/linerenderer.hxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_LINERENDERER_HXX +#define INCLUDED_BASEBMP_LINERENDERER_HXX + +#include <basegfx/point/b2ipoint.hxx> + +#include <vigra/diff2d.hxx> +#include <vigra/iteratortraits.hxx> + + +/* Scan-converting lines */ + +namespace basebmp +{ + +/** Render line with Bresenham + + This function renders the line given by rPt1 and rPt2 using the + Bresenham algorithm with the specified color value. Make sure rPt1 + and rPt1 are valid coordinates in the image given by begin and + end, since no clipping takes place. + + @param aPt1 + Start point of the line + + @param aPt2 + End point of the line + + @param color + Color value to render the line with + + @param begin + left-top image iterator + + @param end + right-bottom image iterator + + @param acc + Image accessor + + @param bRoundTowardsPt2 + Rounding mode to use. Giving false here results in line pixel tend + towards pt1, i.e. when a pixel exactly hits the middle between two + pixel, the pixel closer to pt1 will be chosen. Giving true here + makes renderClippedLine() choose pt2 in those cases. + */ +template< class Iterator, class Accessor > +void renderLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + typename Accessor::value_type color, + Iterator begin, + Accessor acc, + bool bRoundTowardsPt2=false ) +{ + // code inspired by Paul Heckbert's Digital Line Drawing + // (Graphics Gems, Academic Press 1990) + const sal_Int32 x1 = rPt1.getX(); + const sal_Int32 x2 = rPt2.getX(); + const sal_Int32 y1 = rPt1.getY(); + const sal_Int32 y2 = rPt2.getY(); + + // TODO(E1): This might overflow + sal_Int32 adx = x2 - x1; + int sx = 1; + if( adx < 0 ) + { + adx *= -1; + sx = -1; + } + + // TODO(E1): This might overflow + sal_Int32 ady = y2 - y1; + int sy = 1; + if( ady < 0 ) + { + ady *= -1; + sy = -1; + } + + // TODO(P3): handle horizontal and vertical lines specially + sal_Int32 xs = x1; + sal_Int32 ys = y1; + if( adx >= ady ) + { + // semi-horizontal line + sal_Int32 rem = 2*ady - adx - !bRoundTowardsPt2; + adx *= 2; + ady *= 2; + + Iterator currIter( begin + vigra::Diff2D(0,ys) ); + typename vigra::IteratorTraits<Iterator>::row_iterator + rowIter( currIter.rowIterator() + xs ); + while(true) + { + acc.set(color, rowIter); + + if( xs == x2 ) + return; + + if( rem >= 0 ) + { + ys += sy; + xs += sx; + currIter.y += sy; + rowIter = currIter.rowIterator() + xs; + rem -= adx; + } + else + { + xs += sx; + rowIter += sx; + } + + rem += ady; + } + } + else + { + // semi-vertical line + sal_Int32 rem = 2*adx - ady - !bRoundTowardsPt2; + adx *= 2; + ady *= 2; + + Iterator currIter( begin + vigra::Diff2D(xs,0) ); + typename vigra::IteratorTraits<Iterator>::column_iterator + colIter( currIter.columnIterator() + ys ); + while(true) + { + acc.set(color, colIter); + + if( ys == y2 ) + return; + + if( rem >= 0 ) + { + xs += sx; + ys += sy; + currIter.x += sx; + colIter = currIter.columnIterator() + ys; + rem -= ady; + } + else + { + ys += sy; + colIter += sy; + } + + rem += adx; + } + } +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_LINERENDERER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/metafunctions.hxx b/basebmp/inc/basebmp/metafunctions.hxx new file mode 100644 index 000000000000..5f9f8a7ebf31 --- /dev/null +++ b/basebmp/inc/basebmp/metafunctions.hxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_METAFUNCTIONS_HXX +#define INCLUDED_BASEBMP_METAFUNCTIONS_HXX + +#include <boost/mpl/integral_c.hpp> +#include <vigra/metaprogramming.hxx> +#include <vigra/numerictraits.hxx> + +#include <functional> + +namespace basebmp +{ + +// TODO(Q3): move to generic place (o3tl?) + +/** template meta function: add const qualifier to 2nd type, if given + 1st type has it +*/ +template<typename A, typename B> struct clone_const +{ + typedef B type; +}; +template<typename A, typename B> struct clone_const<const A,B> +{ + typedef const B type; +}; + +/** template meta function: add const qualifier to plain type (if not + already there) + */ +template <typename T> struct add_const +{ + typedef const T type; +}; +template <typename T> struct add_const<const T> +{ + typedef const T type; +}; + +/// template meta function: remove const qualifier from plain type +template <typename T> struct remove_const +{ + typedef T type; +}; +template <typename T> struct remove_const<const T> +{ + typedef T type; +}; + +//-------------------------------------------------------------- + +/// Base class for an adaptable ternary functor +template< typename A1, typename A2, typename A3, typename R > struct TernaryFunctorBase +{ + typedef A1 first_argument_type; + typedef A2 second_argument_type; + typedef A3 third_argument_type; + typedef R result_type; +}; + +//-------------------------------------------------------------- + +/** template meta function: ensure that given integer type is unsigned + + If given integer type is already unsigned, return as-is - + otherwise, convert to unsigned type of same or greater range. + */ +template< typename T > struct make_unsigned; + +#define BASEBMP_MAKE_UNSIGNED(T,U) \ + template<> struct make_unsigned<T> { \ + typedef U type; \ + }; + +BASEBMP_MAKE_UNSIGNED(signed char,unsigned char) +BASEBMP_MAKE_UNSIGNED(unsigned char,unsigned char) +BASEBMP_MAKE_UNSIGNED(short,unsigned short) +BASEBMP_MAKE_UNSIGNED(unsigned short,unsigned short) +BASEBMP_MAKE_UNSIGNED(int,unsigned int) +BASEBMP_MAKE_UNSIGNED(unsigned int,unsigned int) +BASEBMP_MAKE_UNSIGNED(long,unsigned long) +BASEBMP_MAKE_UNSIGNED(unsigned long,unsigned long) + +#undef BASEBMP_MAKE_UNSIGNED + +/// cast integer to unsigned type of similar size +template< typename T > inline typename make_unsigned<T>::type unsigned_cast( T value ) +{ + return static_cast< typename make_unsigned<T>::type >(value); +} + +//-------------------------------------------------------------- + +/// returns true, if given number is strictly less than 0 +template< typename T > inline bool is_negative( T x ) +{ + return x < 0; +} + +/// Overload for ints (branch-free) +inline bool is_negative( int x ) +{ + // force logic shift (result for signed shift right is undefined) + return static_cast<unsigned int>(x) >> (sizeof(int)*8-1); +} + +//-------------------------------------------------------------- + +/// Results in VigraTrueType, if T is of integer type and scalar +template< typename T, typename trueCase, typename falseCase > +struct ifScalarIntegral +{ + typedef + typename vigra::If< + typename vigra::NumericTraits< T >::isIntegral, + typename vigra::If< + typename vigra::NumericTraits< T >::isScalar, + trueCase, + falseCase >::type, + falseCase >::type type; +}; + +/// Results in VigraTrueType, if T is of non-integer type and scalar +template< typename T, typename trueCase, typename falseCase > +struct ifScalarNonIntegral +{ + typedef + typename vigra::If< + typename vigra::NumericTraits< T >::isIntegral, + falseCase, + typename vigra::If< + typename vigra::NumericTraits< T >::isScalar, + trueCase, + falseCase >::type >::type type; +}; + +/// Results in VigraTrueType, if both T1 and T2 are of integer type and scalar +template< typename T1, typename T2, typename trueCase, typename falseCase > +struct ifBothScalarIntegral +{ + typedef + typename ifScalarIntegral< + T1, + typename ifScalarIntegral< + T2, + trueCase, + falseCase >::type, + falseCase >::type type; +}; + +//-------------------------------------------------------------- + +/// Count number of trailing zeros +template< unsigned int val > struct numberOfTrailingZeros +{ + enum { next = val >> 1 }; + enum { value = vigra::IfBool< (val & 1) == 0, + numberOfTrailingZeros<next>, + boost::mpl::integral_c< int,-1 > > ::type::value + 1 }; +}; + +template<> struct numberOfTrailingZeros<0> +{ + enum { value = 0 }; +}; + +//-------------------------------------------------------------- + +/// Count number of one bits +template< unsigned int val > struct bitcount +{ + enum { next = val >> 1 }; + enum { value = bitcount<next>::value + (val & 1) }; +}; + +template<> struct bitcount<0> +{ + enum { value = 0 }; +}; + +//-------------------------------------------------------------- + +/// Shift left for positive shift value, and right otherwise +template< typename T > inline T shiftLeft( T v, int shift ) +{ + return shift > 0 ? v << shift : v >> (-shift); +} + +/// Shift right for positive shift value, and left otherwise +template< typename T > inline T shiftRight( T v, int shift ) +{ + return shift > 0 ? v >> shift : v << (-shift); +} + +//-------------------------------------------------------------- + +/// Replace non-std project2nd from SGI extensions +template< typename T1, typename T2 > +struct project2nd : public std::binary_function<T1, T2, T2> +{ + T2 operator() (const T1&, const T2& v) const { return v; } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_METAFUNCTIONS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/nonstandarditerator.hxx b/basebmp/inc/basebmp/nonstandarditerator.hxx new file mode 100644 index 000000000000..090d15d41025 --- /dev/null +++ b/basebmp/inc/basebmp/nonstandarditerator.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_NONSTANDARDITERATOR_HXX +#define INCLUDED_BASEBMP_NONSTANDARDITERATOR_HXX + +#include <vigra/metaprogramming.hxx> + +namespace basebmp +{ + /// Base class defining pointer and reference types as VigraFalseType + struct NonStandardIterator + { + typedef vigra::VigraFalseType reference; + typedef vigra::VigraFalseType index_reference; + typedef vigra::VigraFalseType pointer; + }; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_NONSTANDARDITERATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/packedpixeliterator.hxx b/basebmp/inc/basebmp/packedpixeliterator.hxx new file mode 100644 index 000000000000..b98c8c8f9670 --- /dev/null +++ b/basebmp/inc/basebmp/packedpixeliterator.hxx @@ -0,0 +1,680 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX +#define INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX + +#include <basebmp/metafunctions.hxx> +#include <basebmp/stridedarrayiterator.hxx> +#include <basebmp/nonstandarditerator.hxx> +#include <basebmp/accessortraits.hxx> + +#include <boost/static_assert.hpp> +#include <vigra/metaprogramming.hxx> +#include <vigra/diff2d.hxx> + +namespace basebmp +{ + +/// Get bitmask for data at given intra-word position, for given bit depth +template< typename value_type, + int bits_per_pixel, + bool MsbFirst, + typename difference_type > +inline value_type get_mask( difference_type d ) +{ + BOOST_STATIC_ASSERT(bits_per_pixel > 0); + BOOST_STATIC_ASSERT(sizeof(value_type)*8 % bits_per_pixel == 0); + BOOST_STATIC_ASSERT(sizeof(value_type)*8 / bits_per_pixel > 1); + BOOST_STATIC_ASSERT(vigra::TypeTraits<value_type>::isPOD::asBool); + + const unsigned int nIntraWordPositions( sizeof(value_type)*8 / bits_per_pixel ); + + // create bits_per_pixel 1s shift to intra-word position + return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ? + (nIntraWordPositions-1 - (d % nIntraWordPositions)) : + (d % nIntraWordPositions))); +} + +template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder ) +{ + return bits_per_pixel*(MsbFirst ? + (num_intraword_positions - 1 - remainder) : + remainder); +} + +template< typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelColumnIterator : public NonStandardIterator +{ +public: + // no reference, no index_reference type here + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<value_type>::type mask_type; + typedef value_type* pointer; + typedef StridedArrayIterator< value_type > MoveY; + + enum { + /** The number of pixel within a single value_type value + */ + num_intraword_positions=sizeof(value_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + MoveY y; + mask_type mask_; + difference_type shift_; + + void inc() + { + ++y; + } + + void dec() + { + --y; + } + + bool equal( PackedPixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PackedPixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PackedPixelColumnIterator() : + y(0), + mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) ) + {} + + PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) : + y(base), + mask_( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) ) + {} + + PackedPixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PackedPixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PackedPixelColumnIterator operator+( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res += d; + return res; + } + + PackedPixelColumnIterator operator-( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res -= d; + return res; + } + + PackedPixelColumnIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelColumnIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelColumnIterator operator++(int) + { + PackedPixelColumnIterator res(*this); + inc(); + return res; + } + + PackedPixelColumnIterator operator--(int) + { + PackedPixelColumnIterator res(*this); + dec(); + return res; + } + + bool operator==(PackedPixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + bool operator>(PackedPixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + difference_type operator-(PackedPixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + return unsigned_cast<value_type>(*y() & mask_) >> shift_; + } + + value_type get(difference_type d) const + { + return unsigned_cast<value_type>(*y(d) & mask_) >> shift_; + } + + void set( value_type v ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y() = (*y() & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y(d) = (*y(d) & ~mask_) | pixel_value; + } +}; + +template< typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelRowIterator : public NonStandardIterator +{ +public: + // no reference, no index_reference type here + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<value_type>::type mask_type; + typedef value_type* pointer; + + enum { + /** The number of pixel within a single value_type value + */ + num_intraword_positions=sizeof(value_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + pointer data_; + mask_type mask_; + difference_type remainder_; + + void update_mask() + { + mask_ = get_mask<value_type, bits_per_pixel, MsbFirst>(remainder_); + } + + void inc() + { + const difference_type newValue( remainder_ + 1 ); + const difference_type data_offset( newValue / num_intraword_positions ); + + data_ += data_offset; + remainder_ = newValue % num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + unsigned_cast<mask_type>(mask_) >> bits_per_pixel : + mask_ << bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask << bits_per_pixel*(num_intraword_positions-1) : + bit_mask); + } + + void dec() + { + const difference_type newValue( remainder_ - 1 ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + const difference_type data_offset( newValue / num_intraword_positions - isNegative ); + data_ += data_offset; + remainder_ = newRemainder + isNegative*num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + mask_ << bits_per_pixel : + unsigned_cast<mask_type>(mask_) >> bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask : + bit_mask << bits_per_pixel*(num_intraword_positions-1)); + } + + bool equal( PackedPixelRowIterator const & rhs ) const + { + return rhs.data_ == data_ && rhs.remainder_ == remainder_; + } + + bool less( PackedPixelRowIterator const & rhs ) const + { + return data_ == rhs.data_ ? + (remainder_ < rhs.remainder_) : + (data_ < rhs.data_); + } + +public: + PackedPixelRowIterator() : + data_(0), + mask_( get_mask<value_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + explicit PackedPixelRowIterator( pointer base, int x ) : + data_(base), + mask_(0), + remainder_(x % num_intraword_positions) + { + update_mask(); + } + + PackedPixelRowIterator& operator+=( difference_type d ) + { + const difference_type newValue( remainder_ + d ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = newRemainder + num_intraword_positions; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + data_ += newValue / num_intraword_positions - isNegative; + remainder_ = newRemainder + isNegative*num_intraword_positions; + update_mask(); + + return *this; + } + + PackedPixelRowIterator& operator-=( difference_type d ) + { + // forward to operator+= - which has to cope with negative + // values, anyway. + return *this += -d; + } + + PackedPixelRowIterator operator+( difference_type d ) + { + PackedPixelRowIterator res(*this); + res += d; + return res; + } + + PackedPixelRowIterator operator-( difference_type d ) + { + PackedPixelRowIterator res(*this); + res -= d; + return res; + } + + PackedPixelRowIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelRowIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelRowIterator operator++(int) + { + PackedPixelRowIterator res(*this); + inc(); + return res; + } + + PackedPixelRowIterator operator--(int) + { + PackedPixelRowIterator res(*this); + dec(); + return res; + } + + bool operator==(PackedPixelRowIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelRowIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelRowIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelRowIterator const & rhs) const + { + return !rhs.less(*this); + } + + bool operator>(PackedPixelRowIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelRowIterator const & rhs) const + { + return !less(rhs); + } + + difference_type operator-(PackedPixelRowIterator const & rhs) const + { + return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_); + } + + value_type get() const + { + return unsigned_cast<value_type>(*data_ & mask_) >> + get_shift<num_intraword_positions, + bits_per_pixel, + MsbFirst>(remainder_); + } + + value_type get(difference_type d) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + return tmp.get(); + } + + void set( value_type v ) const + { + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_)) + & mask_ ); + *data_ = (*data_ & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + tmp.set(v); + } +}; + +/** 2D image iterator for packed pixel formats + + This iterator can be used for image formats that pack more than + one pixel into an machine data type (like one bit per pixel, eight + of which packed into one char) + */ +template< typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelIterator : public NonStandardIterator +{ +public: + // no reference, no index_reference type here + typedef Valuetype value_type; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef PackedPixelRowIterator<value_type, + bits_per_pixel, + MsbFirst> row_iterator; + typedef PackedPixelColumnIterator<value_type, + bits_per_pixel, + MsbFirst> column_iterator; + + typedef value_type* pointer; + typedef int MoveX; + typedef StridedArrayIterator< value_type > MoveY; + + enum { + /** The number of pixel within a single value_type value + */ + num_intraword_positions=sizeof(value_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + pointer current() const + { + return y() + (x / num_intraword_positions); + } + + pointer current(int dx, int dy) const + { + return y(dy) + ((x+dx)/num_intraword_positions); + } + + bool equal(PackedPixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + +public: + PackedPixelIterator() : + x(0), + y(0) + {} + + PackedPixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PackedPixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PackedPixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PackedPixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PackedPixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PackedPixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PackedPixelIterator operator+(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret += s; + return ret; + } + + PackedPixelIterator operator-(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(current(),x); + } + + column_iterator columnIterator() const + { + return column_iterator(MoveY(y, + x / num_intraword_positions), + x % num_intraword_positions); + } + + value_type get() const + { + const int remainder( x % num_intraword_positions ); + + return (unsigned_cast<value_type>(*current() & + get_mask<value_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + value_type get(difference_type const & d) const + { + const int remainder( x(d.x) % num_intraword_positions ); + + return (unsigned_cast<value_type>(*current(d.x,d.y) & + get_mask<value_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + void set( value_type v ) const + { + const int remainder( x % num_intraword_positions ); + const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(); + *p = (*p & ~mask) | pixel_value; + } + + void set( value_type v, difference_type const & d ) const + { + const int remainder( (x + d.x) % num_intraword_positions ); + const int mask( get_mask<value_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(d.x,d.y); + *p = (*p & ~mask) | pixel_value; + } +}; + +//----------------------------------------------------------------------------- + +// partial specialization for the accessor traits masked_accessor +// selector metafunction - can employ fast mask functor for the 1bpp +// case. +template< class Accessor, + class MaskAccessor, + class Iterator, + bool polarity, + bool MsbFirst > struct maskedAccessorSelector< Accessor, + MaskAccessor, + Iterator, + PackedPixelIterator< typename MaskAccessor::value_type, + 1, + MsbFirst >, + polarity > +{ + typedef TernarySetterFunctionAccessorAdapter< + Accessor, + MaskAccessor, + typename outputMaskFunctorSelector< + typename Accessor::value_type, + typename MaskAccessor::value_type, + polarity, + FastMask>::type > + type; +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/paletteformats.hxx b/basebmp/inc/basebmp/paletteformats.hxx new file mode 100644 index 000000000000..1cdfe30181d1 --- /dev/null +++ b/basebmp/inc/basebmp/paletteformats.hxx @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PACKEDPIXELFORMATS_HXX +#define INCLUDED_BASEBMP_PACKEDPIXELFORMATS_HXX + +#include <basebmp/color.hxx> +#include <basebmp/colortraits.hxx> +#include <basebmp/accessor.hxx> +#include <basebmp/pixeliterator.hxx> +#include <basebmp/packedpixeliterator.hxx> +#include <basebmp/pixelformatadapters.hxx> +#include <basebmp/paletteimageaccessor.hxx> +#include <basebmp/metafunctions.hxx> + +#include <vigra/numerictraits.hxx> +#include <vigra/metaprogramming.hxx> + +namespace basebmp +{ + +//----------------------------------------------------------------------------- + +/** Lookup index value for given color value in a PaletteImageAccessor + */ +template< class Accessor > struct ColorLookup +{ + typename Accessor::data_type operator()( const Accessor& acc, + typename Accessor::value_type v ) const + { + return acc.lookup(v); + } +}; + +//----------------------------------------------------------------------------- + +// partial specialization of AccessorTraits for PaletteAccessor +template< class Accessor, typename ColorType > struct AccessorTraits< + PaletteImageAccessor< Accessor, ColorType > > +{ + /// value type of described accessor + typedef typename PaletteImageAccessor< Accessor, ColorType >::value_type value_type; + + /// Retrieve stand-alone color lookup function for given Accessor type + typedef ColorLookup< PaletteImageAccessor< Accessor, ColorType > > color_lookup; + + /// Retrieve raw pixel data accessor for given Accessor type + typedef Accessor raw_accessor; + + /** accessor for XOR setter access is disabled, since the results + * are usually completely unintended - you'll usually want to + * wrap an xor_accessor with a PaletteAccessor, not the other way + * around. + */ + typedef vigra::VigraFalseType xor_accessor; + + /** accessor for masked setter access is disabled, since the + * results are usually completely unintended - you'll usually + * want to wrap a masked_accessor with a PaletteAccessor, not the + * other way around. + */ + template< class MaskAccessor, + class Iterator, + class MaskIterator > struct masked_accessor + { + typedef vigra::VigraFalseType type; + }; +}; + +//----------------------------------------------------------------------------- + +template< typename ColorType > struct PaletteAccessorSelector +{ + template< class Accessor > struct wrap_accessor + { + typedef PaletteImageAccessor< Accessor, ColorType > type; + }; +}; + +//----------------------------------------------------------------------------- + +template< class Iterator, + class Accessor > struct PixelFormatTraitsTemplate_Palette +{ + typedef typename Iterator::value_type pixel_type; + typedef Iterator iterator_type; + typedef Accessor raw_accessor_type; + typedef PaletteAccessorSelector<Color> accessor_selector; +}; + +template< int BitsPerPixel, + bool MsbFirst > struct PixelFormatTraitsTemplate_PackedPalette : + public PixelFormatTraitsTemplate_Palette< + PackedPixelIterator< sal_uInt8, + BitsPerPixel, + MsbFirst >, + NonStandardAccessor< sal_uInt8 > > +{}; + +//----------------------------------------------------------------------------- + +// 1bpp MSB +typedef PixelFormatTraitsTemplate_PackedPalette<1, true> PixelFormatTraits_PAL1_MSB; + +// 1bpp LSB +typedef PixelFormatTraitsTemplate_PackedPalette<1, false> PixelFormatTraits_PAL1_LSB; + +// 4bpp MSB +typedef PixelFormatTraitsTemplate_PackedPalette<4, true> PixelFormatTraits_PAL4_MSB; + +// 4bpp LSB +typedef PixelFormatTraitsTemplate_PackedPalette<4, false> PixelFormatTraits_PAL4_LSB; + +// 8bpp +typedef PixelFormatTraitsTemplate_Palette< + PixelIterator< sal_uInt8 >, + StandardAccessor< sal_uInt8 > > PixelFormatTraits_PAL8; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PACKEDPIXELFORMATS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/paletteimageaccessor.hxx b/basebmp/inc/basebmp/paletteimageaccessor.hxx new file mode 100644 index 000000000000..35a14d16dd36 --- /dev/null +++ b/basebmp/inc/basebmp/paletteimageaccessor.hxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX +#define INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX + +#include <basebmp/colortraits.hxx> +#include <basebmp/accessortraits.hxx> + +#include <vigra/numerictraits.hxx> +#include <vigra/metaprogramming.hxx> + +#include <algorithm> +#include <functional> + +namespace basebmp +{ + +/** Access pixel data via palette indirection + + @tpl Accessor + Raw accessor, to be used to actually access the pixel values + + @tpl ColorType + The color value type to use - e.g. the palette is an array of that + type + */ +template< class Accessor, typename ColorType > class PaletteImageAccessor +{ +public: + typedef typename Accessor::value_type data_type; + typedef ColorType value_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A, typename C> friend class PaletteImageAccessor; +#endif + + Accessor maAccessor; + const value_type* mpPalette; + std::size_t mnNumEntries; + +public: + PaletteImageAccessor() : + maAccessor(), + mpPalette(0), + mnNumEntries(0) + {} + + template< class A > explicit + PaletteImageAccessor( PaletteImageAccessor<A,ColorType> const& rSrc ) : + maAccessor( rSrc.maAccessor ), + mpPalette( rSrc.mpPalette ), + mnNumEntries( rSrc.mnNumEntries ) + {} + + PaletteImageAccessor( const value_type* pPalette, + std::size_t numEntries ) : + maAccessor(), + mpPalette(pPalette), + mnNumEntries(numEntries) + {} + + template< class T > PaletteImageAccessor( T accessor, + const value_type* pPalette, + std::size_t numEntries ) : + maAccessor(accessor), + mpPalette(pPalette), + mnNumEntries(numEntries) + {} + + // ------------------------------------------------------- + + Accessor const& getWrappedAccessor() const { return maAccessor; } + Accessor& getWrappedAccessor() { return maAccessor; } + + // ------------------------------------------------------- + + data_type lookup(value_type const& v) const + { + // TODO(P3): use table-based/octree approach here! + const value_type* best_entry; + const value_type* palette_end( mpPalette+mnNumEntries ); + if( (best_entry=std::find( mpPalette, palette_end, v)) != palette_end ) + return best_entry-mpPalette; + + const value_type* curr_entry( mpPalette ); + best_entry = curr_entry; + while( curr_entry != palette_end ) + { + if( ColorTraits<value_type>::distance(*curr_entry, + *best_entry) + > ColorTraits<value_type>::distance(*curr_entry, + v) ) + { + best_entry = curr_entry; + } + + ++curr_entry; + } + + return best_entry-mpPalette; + } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return mpPalette[ maAccessor(i) ]; + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return mpPalette[ maAccessor(i,diff) ]; + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + maAccessor.set( + lookup( + vigra::detail::RequiresExplicitCast<value_type>::cast(value) ), + i ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + maAccessor.set( + lookup( + vigra::detail::RequiresExplicitCast<value_type>::cast(value) ), + i, + diff ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/pixelformatadapters.hxx b/basebmp/inc/basebmp/pixelformatadapters.hxx new file mode 100644 index 000000000000..6ebf531fbbb4 --- /dev/null +++ b/basebmp/inc/basebmp/pixelformatadapters.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PIXELFORMATADAPTERS_HXX +#define INCLUDED_BASEBMP_PIXELFORMATADAPTERS_HXX + +#include <basebmp/accessortraits.hxx> +#include <basebmp/accessoradapters.hxx> + +#include <vigra/metaprogramming.hxx> + +namespace basebmp +{ + +// convenience functionality, providing everything necessary for a new +// pixel format. simply plug in two conversion functors from/to a +// common color format. + +/** Accessor selection metafunction, used to wrap a given accessor + with one converting between the pixel and color types + + Use the nested template's typedef type, to retrieve an + AccessorAdapter which operates on a pixel value accessor, and + provides color values to the outside. + + Nested like this, to avoid template template parameters at other + places: an instantiated version of AccessorSelector can be passed + to other templates, which in turn can invoke the nested meta + function. + */ +template< typename Getter, + typename Setter > struct AccessorSelector +{ + template< typename Accessor > struct wrap_accessor + { + typedef UnaryFunctionAccessorAdapter< Accessor, + Getter, + Setter > type; + }; +}; + +//----------------------------------------------------------------------------- + +/** Convert color value to pixel data type + */ +template< class Accessor, typename DataType > struct ColorConvert +{ + DataType operator()( const Accessor& acc, + typename Accessor::value_type v ) const + { + return acc.setter(v); + } +}; + +//----------------------------------------------------------------------------- + +/** Macro generates partial specialization for color-conversion + UnaryFunctionAccessorAdapter, and the given getter/setter functors + */ +#define BASEBMP_SPECIALIZE_ACCESSORTRAITS(Getter,Setter) \ +template< class Accessor > struct AccessorTraits< \ + UnaryFunctionAccessorAdapter< Accessor, \ + Getter, \ + Setter > > \ +{ \ + typedef typename Accessor::value_type data_type; \ + typedef UnaryFunctionAccessorAdapter< \ + Accessor, \ + Getter, \ + Setter > accessor_type; \ + typedef typename accessor_type::value_type value_type; \ + typedef ColorConvert< accessor_type, \ + data_type > color_lookup; \ + typedef Accessor raw_accessor; \ + typedef vigra::VigraFalseType xor_accessor; \ + template< class MaskAccessor, \ + class Iterator, \ + class MaskIterator > struct masked_accessor\ + { typedef vigra::VigraFalseType type; }; \ +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PIXELFORMATADAPTERS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/pixeliterator.hxx b/basebmp/inc/basebmp/pixeliterator.hxx new file mode 100644 index 000000000000..6e5ca4394a01 --- /dev/null +++ b/basebmp/inc/basebmp/pixeliterator.hxx @@ -0,0 +1,358 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PIXELITERATOR_HXX +#define INCLUDED_BASEBMP_PIXELITERATOR_HXX + +#include <basebmp/metafunctions.hxx> +#include <basebmp/stridedarrayiterator.hxx> + +#include <vigra/metaprogramming.hxx> +#include <vigra/diff2d.hxx> + +namespace basebmp +{ + +template< typename Valuetype > class PixelColumnIterator +{ +public: + typedef Valuetype value_type; + typedef Valuetype& reference; + typedef reference index_reference; + typedef Valuetype* pointer; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef StridedArrayIterator< value_type > MoveY; + +private: + MoveY y; + + bool equal( PixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PixelColumnIterator() : + y(0) + {} + + explicit PixelColumnIterator( const MoveY& pos ) : + y(pos) + {} + + PixelColumnIterator( const MoveY& pos, int x ) : + y(pos,x) + {} + + PixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PixelColumnIterator operator+( difference_type d ) + { + PixelColumnIterator res(*this); + res += d; + return res; + } + + PixelColumnIterator operator-( difference_type d ) + { + PixelColumnIterator res(*this); + res -= d; + return res; + } + + PixelColumnIterator& operator++() + { + ++y; + return *this; + } + + PixelColumnIterator& operator--() + { + --y; + return *this; + } + + PixelColumnIterator operator++(int) + { + PixelColumnIterator res(*this); + ++y; + return res; + } + + PixelColumnIterator operator--(int) + { + PixelColumnIterator res(*this); + --y; + return res; + } + + bool operator==(PixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + bool operator>(PixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + difference_type operator-(PixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + return *y(); + } + + value_type get(difference_type d) const + { + return *y(d); + } + + void set( value_type v ) const + { + *y() = v; + } + + void set( value_type v, difference_type d ) const + { + *y(d) = v; + } + + reference operator*() const + { + return *y(); + } + + pointer operator->() const + { + return y(); + } + + reference operator[](difference_type d) const + { + return *y(d); + } + + reference operator()(int dy) const + { + return *y(dy); + } +}; + +template< typename Valuetype > class PixelIterator +{ +public: + typedef Valuetype value_type; + typedef Valuetype& reference; + typedef reference index_reference; + typedef Valuetype* pointer; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef pointer row_iterator; + typedef PixelColumnIterator<value_type> column_iterator; + + typedef int MoveX; + typedef StridedArrayIterator< value_type > MoveY; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + bool equal(PixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + + pointer current() const + { + return y() + x; + } + + pointer current(int dx, int dy) const + { + return y(dy) + x+dx; + } + +public: + PixelIterator() : + x(0), + y(0) + {} + + PixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PixelIterator operator+(difference_type const & s) const + { + PixelIterator ret(*this); + ret += s; + return ret; + } + + PixelIterator operator-(difference_type const & s) const + { + PixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(y()+x); + } + + column_iterator columnIterator() const + { + return column_iterator(y,x); + } + + value_type get() const + { + return *current(); + } + + value_type get(difference_type const & d) const + { + return *current(d.y, d.x); + } + + void set( value_type v ) const + { + *current() = v; + } + + void set( value_type v, difference_type const & d ) const + { + *current(d.y,d.x) = v; + } + + reference operator*() const + { + return *current(); + } + + pointer operator->() const + { + return current(); + } + + reference operator[]( const vigra::Diff2D& d ) const + { + return *current(d.x,d.y); + } + + reference operator()(int dx, int dy) const + { + return *current(dx,dy); + } + + pointer operator[](int dy) const + { + return y(dy) + x; + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PIXELITERATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/polypolygonrenderer.hxx b/basebmp/inc/basebmp/polypolygonrenderer.hxx new file mode 100644 index 000000000000..6a7c391f31d0 --- /dev/null +++ b/basebmp/inc/basebmp/polypolygonrenderer.hxx @@ -0,0 +1,369 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_POLYPOLYGONRENDERER_HXX +#define INCLUDED_BASEBMP_POLYPOLYGONRENDERER_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygonfillrule.hxx> +#include <basegfx/numeric/ftools.hxx> + +#include <vigra/diff2d.hxx> +#include <vigra/iteratortraits.hxx> + +#include <vector> + + +namespace basebmp +{ + namespace detail + { + /// convert int32 to 32:32 fixed point + inline sal_Int64 toFractional( sal_Int32 v ) { return (sal_Int64)v << 32; } + /// convert double to 32:32 fixed point + inline sal_Int64 toFractional( double v ) { return (sal_Int64)(v*SAL_MAX_UINT32 + (v < 0.0 ? -0.5 : 0.5 )); } + /// convert 32:32 fixed point to int32 (truncate) + inline sal_Int32 toInteger( sal_Int64 v ) { return (sal_Int32)(v < 0 ? ~((~v) >> 32) : v >> 32); } + /// convert 32:32 fixed point to int32 (properly rounded) + inline sal_Int32 toRoundedInteger( sal_Int64 v ) { return toInteger(v) + (sal_Int32)((v&0x80000000) >> 31); } + + /** internal vertex store - + + Different from B2DPoint, since we don't need floating + point coords, but orientation of vertex and y counter + */ + struct Vertex + { + sal_Int32 mnYCounter; + sal_Int64 mnX; + sal_Int64 mnXDelta; + + bool mbDownwards; // needed for nonzero winding rule + // fills + + Vertex() : + mnYCounter(0), + mnX(0), + mnXDelta(0), + mbDownwards(true) + {} + Vertex( basegfx::B2DPoint const& rPt1, + basegfx::B2DPoint const& rPt2, + bool bDownwards ) : + mnYCounter( basegfx::fround(rPt2.getY()) - + basegfx::fround(rPt1.getY()) ), + mnX( toFractional( basegfx::fround(rPt1.getX()) )), + mnXDelta( toFractional( + ((rPt2.getX() - rPt1.getX()) / + (double)mnYCounter) )), + mbDownwards(bDownwards) + {} + }; + + typedef std::vector< std::vector<Vertex> > VectorOfVectorOfVertices; + typedef std::vector< Vertex* > VectorOfVertexPtr; + + /// non-templated setup of GET + sal_uInt32 setupGlobalEdgeTable( VectorOfVectorOfVertices& rGET, + basegfx::B2DPolyPolygon const& rPoly, + sal_Int32 nMinY ); + /// sort rAETSrc, copy not-yet-ended edges over to rAETDest + void sortAET( VectorOfVertexPtr& rAETSrc, + VectorOfVertexPtr& rAETDest ); + + /// For the STL algorithms + struct RasterConvertVertexComparator + { + RasterConvertVertexComparator() {} + + bool operator()( const Vertex& rLHS, + const Vertex& rRHS ) const + { + return rLHS.mnX < rRHS.mnX; + } + + bool operator()( const Vertex* pLHS, + const Vertex* pRHS ) const + { + return pLHS->mnX < pRHS->mnX; + } + }; + + } // namespace detail + + + /** Raster-convert a poly-polygon. + + This algorithm does not perform antialiasing, and thus + internally works with integer vertex coordinates. + + @param begin + Left, top edge of the destination bitmap. This position is + considered (0,0) relative to all polygon vertices + + @param ad + Accessor to set pixel values + + @param fillColor + Color to use for filling + + @param rClipRect + Clipping rectangle, relative to the begin iterator. No pixel outside + this clip rect will be modified. + + @param rPoly + Polygon to fill + */ + template< class DestIterator, class DestAccessor, typename T > + void renderClippedPolyPolygon( DestIterator begin, + DestAccessor ad, + T fillColor, + const basegfx::B2IRange& rClipRect, + basegfx::B2DPolyPolygon const& rPoly, + basegfx::FillRule eFillRule ) + { + const sal_Int32 nClipX1( std::max((sal_Int32)0,rClipRect.getMinX()) ); + const sal_Int32 nClipX2( rClipRect.getMaxX() ); + const sal_Int32 nClipY1( std::max((sal_Int32)0,rClipRect.getMinY()) ); + const sal_Int32 nClipY2( rClipRect.getMaxY() ); + const sal_Int64 nClipX1_frac( detail::toFractional(nClipX1) ); + const sal_Int64 nClipX2_frac( detail::toFractional(nClipX2) ); + + basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(rPoly) ); + + const sal_Int32 nMinY( basegfx::fround(aPolyBounds.getMinY()) ); + const sal_Int32 nMaxY( + std::min( + nClipY2-1, + basegfx::fround(aPolyBounds.getMaxY()))); + + if( nMinY > nMaxY ) + return; // really, nothing to do then. + + detail::VectorOfVectorOfVertices aGET; // the Global Edge Table + aGET.resize( nMaxY - nMinY + 1 ); + + sal_uInt32 const nVertexCount( + detail::setupGlobalEdgeTable( aGET, rPoly, nMinY ) ); + + + // Perform actual scan conversion + //---------------------------------------------------------------------- + + if( aGET.empty() ) + return; + + detail::VectorOfVertexPtr aAET1; // the Active Edge Table + detail::VectorOfVertexPtr aAET2; + detail::VectorOfVertexPtr* pAET = &aAET1; + detail::VectorOfVertexPtr* pAETOther = &aAET2; + aAET1.reserve( nVertexCount ); + aAET2.reserve( nVertexCount ); + + // current scanline - initially, points to first scanline + // within the clip rect, or to the polygon's first scanline + // (whichever is greater) + DestIterator aScanline( begin + + vigra::Diff2D( + 0, + std::max(nMinY, + nClipY1)) ); + detail::RasterConvertVertexComparator aComp; + + + // now process each of the nMaxY - nMinY + 1 scanlines + // ------------------------------------------------------------ + + for( sal_Int32 y=nMinY; y <= nMaxY; ++y ) + { + if( !aGET[y-nMinY].empty() ) + { + // merge AET with current scanline's new vertices (both + // are already correctly sorted) + detail::VectorOfVectorOfVertices::value_type::iterator vertex=aGET[y-nMinY].begin(); + detail::VectorOfVectorOfVertices::value_type::iterator const end=aGET[y-nMinY].end(); + while( vertex != end ) + { + // find insertion pos by binary search, and put ptr + // into active edge vector + pAET->insert( std::lower_bound( pAET->begin(), + pAET->end(), + &(*vertex), + aComp ), + &(*vertex) ); + + ++vertex; + } + } + + // with less than two active edges, no fill visible + if( pAET->size() >= 2 ) + { + typename vigra::IteratorTraits<DestIterator>::row_iterator + rowIter( aScanline.rowIterator() ); + + // process each span in current scanline, with + // even-odd fill rule + detail::VectorOfVertexPtr::iterator currVertex( pAET->begin() ); + detail::VectorOfVertexPtr::iterator const lastVertex( pAET->end()-1 ); + sal_uInt32 nCrossedEdges(0); + sal_Int32 nWindingNumber(0); + while( currVertex != lastVertex ) + { + // TODO(P1): might be worth a try to extend the + // size()==2 case also to the actual filling + // here. YMMV. + detail::Vertex& rV1( **currVertex ); + detail::Vertex const& rV2( **++currVertex ); + + nWindingNumber += -1 + 2*rV1.mbDownwards; + + // calc fill status for both rules. might save a + // few percent runtime to specialize here... + const bool bEvenOddFill( + eFillRule == basegfx::FillRule_EVEN_ODD && !(nCrossedEdges & 0x01) ); + const bool bNonZeroWindingFill( + eFillRule == basegfx::FillRule_NONZERO_WINDING_NUMBER && nWindingNumber != 0 ); + + // is span visible? + if( (bEvenOddFill || bNonZeroWindingFill) && + y >= nClipY1 && + rV1.mnX < nClipX2_frac && + rV2.mnX > nClipX1_frac ) + { + // clip span to horizontal bounds + sal_Int32 const nStartX( + std::max( nClipX1, + std::min( nClipX2-1, + detail::toRoundedInteger(rV1.mnX) ))); + sal_Int32 const nEndX( + std::max( nClipX1, + std::min( nClipX2, + detail::toRoundedInteger(rV2.mnX) ))); + + typename vigra::IteratorTraits<DestIterator>::row_iterator + currPix( rowIter + nStartX); + typename vigra::IteratorTraits<DestIterator>::row_iterator + rowEnd( rowIter + nEndX ); + + // TODO(P2): Provide specialized span fill methods on the + // iterator/accessor + while( currPix != rowEnd ) + ad.set(fillColor, currPix++); + } + + // step vertices + rV1.mnX += rV1.mnXDelta; + --rV1.mnYCounter; + + ++nCrossedEdges; + } + + // step vertex also for the last one + detail::Vertex& rLastV( **currVertex ); + rLastV.mnX += rLastV.mnXDelta; + --rLastV.mnYCounter; + + + // prune AET from ended edges, and keep it sorted + // --------------------------------------------------------- + + pAETOther->clear(); + if( pAET->size() == 2 ) + { + // the case of exactly two active edges is both + // sufficiently common (all 'simple' polygons have + // it), and further more would complicate the + // generic case below (which works with a sliding + // triple of vertices). + if( !aComp(*(*pAET)[0], *(*pAET)[1]) ) + std::swap(*(*pAET)[0], *(*pAET)[1]); + + if( (*pAET)[0]->mnYCounter > 0 ) + pAETOther->push_back( (*pAET)[0] ); + if( (*pAET)[1]->mnYCounter > 0 ) + pAETOther->push_back( (*pAET)[1] ); + } + else + { + bool bFallbackTaken(false); + currVertex = pAET->begin(); + detail::VectorOfVertexPtr::iterator prevVertex( currVertex ); + while( currVertex != lastVertex ) + { + // try to get away with one linear swoop and + // simple neighbor swapping. this is an + // overwhelmingly common case - polygons with + // excessively crisscrossing edges (which on + // top of that cross more than one other edge + // per scanline) are seldom. And even if we + // get such a beast here, this extra loop has + // still only linear cost + if( aComp(**(currVertex+1),**currVertex) ) + { + std::swap(*currVertex, *(currVertex+1)); + + if( aComp(**currVertex,**prevVertex) ) + { + // one swap was not sufficient - + // fallback to generic sort algo, then + detail::sortAET(*pAET, *pAETOther); + bFallbackTaken = true; + break; + } + } + + if( (*currVertex)->mnYCounter > 0 ) + pAETOther->push_back( *currVertex ); + + prevVertex = currVertex++; + } + + // don't forget to add last vertex (loop above + // only deals with n-1 vertices) + if( !bFallbackTaken && (*currVertex)->mnYCounter > 0 ) + pAETOther->push_back( *currVertex ); + } + + std::swap( pAET, pAETOther ); + } + + if( y >= nClipY1 ) + ++aScanline.y; + } + } + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_POLYPOLYGONRENDERER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/rgb24pixelformats.hxx b/basebmp/inc/basebmp/rgb24pixelformats.hxx new file mode 100644 index 000000000000..91d374efd7e9 --- /dev/null +++ b/basebmp/inc/basebmp/rgb24pixelformats.hxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_RGB24PIXELFORMATS_HXX +#define INCLUDED_BASEBMP_RGB24PIXELFORMATS_HXX + +#include <basebmp/color.hxx> +#include <basebmp/accessor.hxx> +#include <basebmp/pixeliterator.hxx> +#include <basebmp/pixelformatadapters.hxx> + +#include <vigra/rgbvalue.hxx> + +#include <functional> + +namespace basebmp +{ + +template< typename PixelType, typename ColorType > struct RGBValueGetter : + public std::unary_function<PixelType, ColorType> +{ + ColorType operator()( PixelType const& c ) const + { + return ColorType(c.red(),c.green(),c.blue()); + } +}; + +template< typename PixelType, typename ColorType > struct RGBValueSetter : + public std::unary_function<ColorType, PixelType> +{ + PixelType operator()( ColorType const& c ) const + { + PixelType res; + res.setRed(c.getRed()); + res.setGreen(c.getGreen()); + res.setBlue(c.getBlue()); + return res; + } +}; + +//----------------------------------------------------------------------------- + +template< typename PixelType > struct PixelFormatTraitsTemplate_RGBValue +{ + typedef PixelType pixel_type; + + typedef RGBValueGetter<pixel_type, + Color> getter_type; + typedef RGBValueSetter<pixel_type, + Color> setter_type; + + typedef PixelIterator<pixel_type> iterator_type; + typedef StandardAccessor<pixel_type> raw_accessor_type; + typedef AccessorSelector< + getter_type, setter_type> accessor_selector; +}; + +//----------------------------------------------------------------------------- + +// 24bpp RGB +typedef PixelFormatTraitsTemplate_RGBValue< + vigra::RGBValue<sal_uInt8> > PixelFormatTraits_RGB24; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB24::getter_type, + PixelFormatTraits_RGB24::setter_type); + +// 24bpp BGR +typedef PixelFormatTraitsTemplate_RGBValue< + vigra::RGBValue<sal_uInt8,2,1,0> > PixelFormatTraits_BGR24; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_BGR24::getter_type, + PixelFormatTraits_BGR24::setter_type); + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_RGB24PIXELFORMATS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/rgbmaskpixelformats.hxx b/basebmp/inc/basebmp/rgbmaskpixelformats.hxx new file mode 100644 index 000000000000..47f7c2bf6199 --- /dev/null +++ b/basebmp/inc/basebmp/rgbmaskpixelformats.hxx @@ -0,0 +1,292 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX +#define INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX + +#include <basebmp/color.hxx> +#include <basebmp/colortraits.hxx> +#include <basebmp/accessor.hxx> +#include <basebmp/pixeliterator.hxx> +#include <basebmp/pixelformatadapters.hxx> +#include <basebmp/metafunctions.hxx> +#include <basebmp/endian.hxx> + +#include <vigra/numerictraits.hxx> +#include <vigra/metaprogramming.hxx> + +#include <functional> + +namespace basebmp +{ + +/** Base class operating on RGB truecolor mask pixel + + Use this template, if you have an (integer) pixel type, and three + bitmasks denoting where the channel bits are. + + @tpl PixelType + Input pixel type to operate on + + @tpl ColorType + Underlying color type, to convert the pixel values into + + @tpl RedMask + Bitmask, to access the red bits in the data type + + @tpl GreenMask + Bitmask, to access the green bits in the data type + + @tpl BlueMask + Bitmask, to access the blue bits in the data type + + @tpl SwapBytes + When true, the final pixel values will be byte-swapped before + passed on. + */ +template< typename PixelType, + typename ColorType, + unsigned int RedMask, + unsigned int GreenMask, + unsigned int BlueMask, + bool SwapBytes > struct RGBMaskFunctorBase +{ + typedef PixelType pixel_type; + typedef ColorType color_type; + typedef typename make_unsigned<pixel_type>::type unsigned_pixel_type; + typedef typename ColorTraits<ColorType>::component_type component_type; + + // calc corrective shifts for all three channels in advance + enum { + red_shift = numberOfTrailingZeros<RedMask>::value, + green_shift = numberOfTrailingZeros<GreenMask>::value, + blue_shift = numberOfTrailingZeros<BlueMask>::value, + + red_bits = bitcount<RedMask>::value, + green_bits = bitcount<GreenMask>::value, + blue_bits = bitcount<BlueMask>::value + }; +}; + +template< typename PixelType, + typename ColorType, + unsigned int RedMask, + unsigned int GreenMask, + unsigned int BlueMask, + bool SwapBytes > struct RGBMaskGetter : + public RGBMaskFunctorBase<PixelType, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes>, + public std::unary_function<PixelType, ColorType> +{ + typedef RGBMaskFunctorBase<PixelType, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes> base_type; + + ColorType operator()( PixelType v ) const + { + v = SwapBytes ? byteSwap(v) : v; + + const typename base_type::unsigned_pixel_type red (v & RedMask); + const typename base_type::unsigned_pixel_type green(v & GreenMask); + const typename base_type::unsigned_pixel_type blue (v & BlueMask); + + // shift color nibbles to right-aligend position. ORing it + // channel value shifted twice the number of channel bits, to + // spread the value into the component_type range + ColorType res( (shiftRight(red, + base_type::red_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::red_bits)) | + (shiftRight(red, + base_type::red_shift-8* + (signed)sizeof(typename base_type::component_type)+ + 2*base_type::red_bits)), + + (shiftRight(green, + base_type::green_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::green_bits)) | + (shiftRight(green, + base_type::green_shift-8* + (signed)sizeof(typename base_type::component_type)+ + 2*base_type::green_bits)), + + (shiftRight(blue, + base_type::blue_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::blue_bits)) | + (shiftRight(blue, + base_type::blue_shift-8* + (signed)sizeof(typename base_type::component_type)+ + 2*base_type::blue_bits)) ); + return res; + } +}; + +template< typename PixelType, + typename ColorType, + unsigned int RedMask, + unsigned int GreenMask, + unsigned int BlueMask, + bool SwapBytes > struct RGBMaskSetter : + public RGBMaskFunctorBase<PixelType, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes>, + public std::unary_function<ColorType, PixelType> +{ + typedef RGBMaskFunctorBase<PixelType, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes> base_type; + + PixelType operator()( ColorType const& c ) const + { + const typename base_type::unsigned_pixel_type red (c.getRed()); + const typename base_type::unsigned_pixel_type green(c.getGreen()); + const typename base_type::unsigned_pixel_type blue (c.getBlue()); + + typename base_type::unsigned_pixel_type res( + (shiftLeft(red, + base_type::red_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::red_bits) & RedMask) | + (shiftLeft(green, + base_type::green_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::green_bits) & GreenMask) | + (shiftLeft(blue, + base_type::blue_shift-8* + (signed)sizeof(typename base_type::component_type)+ + base_type::blue_bits) & BlueMask) ); + + return SwapBytes ? byteSwap(res) : res; + } +}; + +//----------------------------------------------------------------------------- + +template< typename PixelType, + unsigned int RedMask, + unsigned int GreenMask, + unsigned int BlueMask, + bool SwapBytes > struct PixelFormatTraitsTemplate_RGBMask +{ + typedef PixelType pixel_type; + + typedef RGBMaskGetter<pixel_type, + Color, + RedMask, + GreenMask, + BlueMask, + SwapBytes> getter_type; + typedef RGBMaskSetter<pixel_type, + Color, + RedMask, + GreenMask, + BlueMask, + SwapBytes> setter_type; + + typedef PixelIterator<pixel_type> iterator_type; + typedef StandardAccessor<pixel_type> raw_accessor_type; + typedef AccessorSelector< + getter_type, setter_type> accessor_selector; +}; + +//----------------------------------------------------------------------------- + +#ifdef OSL_LITENDIAN +# define BASEBMP_TRUECOLORMASK_LSB_SWAP false +# define BASEBMP_TRUECOLORMASK_MSB_SWAP true +#else +# ifdef OSL_BIGENDIAN +# define BASEBMP_TRUECOLORMASK_LSB_SWAP true +# define BASEBMP_TRUECOLORMASK_MSB_SWAP false +# else +# error Undetermined endianness! +# endif +#endif + +//----------------------------------------------------------------------------- + +// 16bpp MSB RGB +typedef PixelFormatTraitsTemplate_RGBMask< + sal_uInt16, + 0xF800, + 0x07E0, + 0x001F, + BASEBMP_TRUECOLORMASK_MSB_SWAP > PixelFormatTraits_RGB16_565_MSB; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_MSB::getter_type, + PixelFormatTraits_RGB16_565_MSB::setter_type); + +// 16bpp LSB RGB +typedef PixelFormatTraitsTemplate_RGBMask< + sal_uInt16, + 0xF800, + 0x07E0, + 0x001F, + BASEBMP_TRUECOLORMASK_LSB_SWAP > PixelFormatTraits_RGB16_565_LSB; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB16_565_LSB::getter_type, + PixelFormatTraits_RGB16_565_LSB::setter_type); + +// 32bpp endian-sensitive RGB +typedef PixelFormatTraitsTemplate_RGBMask< + sal_uInt32, + 0xFF0000, + 0x00FF00, + 0x0000FF, + BASEBMP_TRUECOLORMASK_LSB_SWAP > PixelFormatTraits_RGB32_888; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_RGB32_888::getter_type, + PixelFormatTraits_RGB32_888::setter_type); + +// 32bpp endian-sensitive BGR +typedef PixelFormatTraitsTemplate_RGBMask< + sal_uInt32, + 0xFF0000, + 0x00FF00, + 0x0000FF, + BASEBMP_TRUECOLORMASK_MSB_SWAP > PixelFormatTraits_BGR32_888; +BASEBMP_SPECIALIZE_ACCESSORTRAITS(PixelFormatTraits_BGR32_888::getter_type, + PixelFormatTraits_BGR32_888::setter_type); + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_RGBMASKPIXELFORMATS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/scaleimage.hxx b/basebmp/inc/basebmp/scaleimage.hxx new file mode 100644 index 000000000000..a8fd83e2cd94 --- /dev/null +++ b/basebmp/inc/basebmp/scaleimage.hxx @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_SCALEIMAGE_HXX +#define INCLUDED_BASEBMP_SCALEIMAGE_HXX + +#include <osl/diagnose.h> + +#include <vigra/tuple.hxx> +#include <vigra/copyimage.hxx> +#include <vigra/basicimage.hxx> +#include <vigra/iteratortraits.hxx> + +namespace basebmp +{ + +template< class SourceIter, class SourceAcc, + class DestIter, class DestAcc > +void scaleLine( SourceIter s_begin, + SourceIter s_end, + SourceAcc s_acc, + DestIter d_begin, + DestIter d_end, + DestAcc d_acc ) +{ + const int src_width = s_end - s_begin; + const int dest_width = d_end - d_begin; + + OSL_ASSERT( src_width > 0 && dest_width > 0 ); + + if( src_width >= dest_width ) + { + // shrink + int rem = 0; + while( s_begin != s_end ) + { + if( rem >= 0 ) + { + d_acc.set( s_acc(s_begin), d_begin ); + + rem -= src_width; + ++d_begin; + } + + rem += dest_width; + ++s_begin; + } + } + else + { + // enlarge + int rem = -dest_width; + while( d_begin != d_end ) + { + if( rem >= 0 ) + { + rem -= dest_width; + ++s_begin; + } + + d_acc.set( s_acc(s_begin), d_begin ); + + rem += src_width; + ++d_begin; + } + } +} + +/** Scale an image using zero order interpolation (pixel replication) + + Source and destination range must be at least one pixel wide and + high. + + @param s_begin + Start iterator for source image + + @param s_end + End iterator for source image + + @param s_acc + Source accessor + + @param d_begin + Start iterator for destination image + + @param d_end + End iterator for destination image + + @param d_acc + Destination accessor + + @param bMustCopy + When true, scaleImage always copies source, even when doing 1:1 + copy + */ +template< class SourceIter, class SourceAcc, + class DestIter, class DestAcc > +void scaleImage( SourceIter s_begin, + SourceIter s_end, + SourceAcc s_acc, + DestIter d_begin, + DestIter d_end, + DestAcc d_acc, + bool bMustCopy=false ) +{ + const int src_width ( s_end.x - s_begin.x ); + const int src_height( s_end.y - s_begin.y ); + + const int dest_width ( d_end.x - d_begin.x ); + const int dest_height( d_end.y - d_begin.y ); + + if( !bMustCopy && + src_width == dest_width && + src_height == dest_height ) + { + // no scaling involved, can simply copy + vigra::copyImage( s_begin, s_end, s_acc, + d_begin, d_acc ); + return; + } + + typedef vigra::BasicImage<typename SourceAcc::value_type> TmpImage; + typedef typename TmpImage::traverser TmpImageIter; + + TmpImage tmp_image(src_width, + dest_height); + TmpImageIter t_begin = tmp_image.upperLeft(); + + // scale in y direction + for( int x=0; x<src_width; ++x, ++s_begin.x, ++t_begin.x ) + { + typename SourceIter::column_iterator s_cbegin = s_begin.columnIterator(); + typename TmpImageIter::column_iterator t_cbegin = t_begin.columnIterator(); + + scaleLine(s_cbegin, s_cbegin+src_height, s_acc, + t_cbegin, t_cbegin+dest_height, tmp_image.accessor()); + } + + t_begin = tmp_image.upperLeft(); + + // scale in x direction + for( int y=0; y<dest_height; ++y, ++d_begin.y, ++t_begin.y ) + { + typename DestIter::row_iterator d_rbegin = d_begin.rowIterator(); + typename TmpImageIter::row_iterator t_rbegin = t_begin.rowIterator(); + + scaleLine(t_rbegin, t_rbegin+src_width, tmp_image.accessor(), + d_rbegin, d_rbegin+dest_width, d_acc); + } +} + +/** Scale an image, range tuple version + + @param bMustCopy + When true, scaleImage always copies source, even when doing 1:1 + copy + */ +template< class SourceIter, class SourceAcc, + class DestIter, class DestAcc > +inline void scaleImage( vigra::triple<SourceIter,SourceIter,SourceAcc> const& src, + vigra::triple<DestIter,DestIter,DestAcc> const& dst, + bool bMustCopy=false ) +{ + scaleImage(src.first,src.second,src.third, + dst.first,dst.second,dst.third, + bMustCopy); +} + +} + +#endif /* INCLUDED_BASEBMP_SCALEIMAGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/scanlineformats.hxx b/basebmp/inc/basebmp/scanlineformats.hxx new file mode 100644 index 000000000000..ee466f21b5c9 --- /dev/null +++ b/basebmp/inc/basebmp/scanlineformats.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_SCANLINEFORMATS_HXX +#define INCLUDED_BASEBMP_SCANLINEFORMATS_HXX + +#include <sal/types.h> + +/* Definition of Scanline formats */ + +namespace basebmp { namespace Format +{ + static const sal_Int32 NONE = 0; + static const sal_Int32 ONE_BIT_MSB_GREY = (sal_Int32)0x01; + static const sal_Int32 ONE_BIT_LSB_GREY = (sal_Int32)0x02; + static const sal_Int32 ONE_BIT_MSB_PAL = (sal_Int32)0x03; + static const sal_Int32 ONE_BIT_LSB_PAL = (sal_Int32)0x04; + static const sal_Int32 FOUR_BIT_MSB_GREY = (sal_Int32)0x05; + static const sal_Int32 FOUR_BIT_LSB_GREY = (sal_Int32)0x06; + static const sal_Int32 FOUR_BIT_MSB_PAL = (sal_Int32)0x07; + static const sal_Int32 FOUR_BIT_LSB_PAL = (sal_Int32)0x08; + static const sal_Int32 EIGHT_BIT_PAL = (sal_Int32)0x09; + static const sal_Int32 EIGHT_BIT_GREY = (sal_Int32)0x0A; + static const sal_Int32 SIXTEEN_BIT_LSB_TC_MASK = (sal_Int32)0x0B; + static const sal_Int32 SIXTEEN_BIT_MSB_TC_MASK = (sal_Int32)0x0C; + static const sal_Int32 TWENTYFOUR_BIT_TC_MASK = (sal_Int32)0x0D; + static const sal_Int32 THIRTYTWO_BIT_TC_MASK = (sal_Int32)0x0E; + static const sal_Int32 THIRTYTWO_BIT_TC_MASK_ARGB = (sal_Int32)0x0F; + static const sal_Int32 MAX = (sal_Int32)0x0F; +} } + +#endif /* INCLUDED_BASEBMP_SCANLINEFORMATS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/stridedarrayiterator.hxx b/basebmp/inc/basebmp/stridedarrayiterator.hxx new file mode 100644 index 000000000000..422269cb70e4 --- /dev/null +++ b/basebmp/inc/basebmp/stridedarrayiterator.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX +#define INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX + +#include <basebmp/metafunctions.hxx> + +namespace basebmp +{ + +/** Like vigra::StridedArrayIterator + + Changed semantics re. DirectionSelector<StridedArrayTag>: stride + now counts in <em>raw</em> bytes + + Adapts given ptr, in a way that iterator increments move forward + in strided steps. Stride can, by the way, also be negative + */ +template< typename T > class StridedArrayIterator +{ +public: + typedef typename clone_const<T, unsigned char>::type internal_type; + + /** Create iterator + + @param stride + + Stride in bytes. Given value should better match memory layout + of T, as memory gets reinterpret-casted. + */ + explicit StridedArrayIterator(int stride, T* ptr = 0) : + stride_(stride), + current_(reinterpret_cast<internal_type*>(ptr)) + {} + + /** Copy from other StridedArrayIterator, plus given offset + + @param offset + Offset in bytes + */ + StridedArrayIterator( StridedArrayIterator const& rSrc, + int offset ) : + stride_(rSrc.stride_), + current_(reinterpret_cast<internal_type*>( + reinterpret_cast<T*>(rSrc.current_)+offset)) + {} + + void operator++() {current_ += stride_; } + void operator++(int) {current_ += stride_; } + void operator--() {current_ -= stride_; } + void operator--(int) {current_ -= stride_; } + void operator+=(int dy) {current_ += dy*stride_; } + void operator-=(int dy) {current_ -= dy*stride_; } + + int operator-(StridedArrayIterator const & rhs) const + { return (current_ - rhs.current_) / stride_; } + + bool operator==(StridedArrayIterator const & rhs) const + { return current_ == rhs.current_; } + + bool operator!=(StridedArrayIterator const & rhs) const + { return current_ != rhs.current_; } + + bool operator<(StridedArrayIterator const & rhs) const + { return *this - rhs < 0; } + + bool operator<=(StridedArrayIterator const & rhs) const + { return *this - rhs <= 0; } + + bool operator>(StridedArrayIterator const & rhs) const + { return *this - rhs > 0; } + + bool operator>=(StridedArrayIterator const & rhs) const + { return *this - rhs >= 0; } + + T* operator()() const + { return reinterpret_cast<T*>(current_); } + + T* operator()(int d) const + { return reinterpret_cast<T*>(current_ + d*stride_); } + +private: + int stride_; + internal_type* current_; +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/tools.hxx b/basebmp/inc/basebmp/tools.hxx new file mode 100644 index 000000000000..0b5fcb87a693 --- /dev/null +++ b/basebmp/inc/basebmp/tools.hxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_TOOLS_HXX +#define INCLUDED_BASEBMP_TOOLS_HXX + +#include <basegfx/range/b2irange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <vigra/tuple.hxx> +#include <vigra/diff2d.hxx> + +namespace basebmp +{ + inline vigra::Diff2D topLeft( const basegfx::B2IRange& rRange ) + { return vigra::Diff2D(rRange.getMinX(),rRange.getMinY()); } + + inline vigra::Diff2D bottomRight( const basegfx::B2IRange& rRange ) + { return vigra::Diff2D(rRange.getMaxX(),rRange.getMaxY()); } + + template< class Iterator, class Accessor > + inline vigra::triple<Iterator,Iterator,Accessor> + destIterRange(Iterator const& begin, + Accessor const& accessor, + const basegfx::B2IRange& rRange) + { + return vigra::triple<Iterator,Iterator,Accessor>( + begin + topLeft(rRange), + begin + bottomRight(rRange), + accessor); + } + + template< class Iterator, class Accessor > + inline vigra::triple<Iterator,Iterator,Accessor> + srcIterRange(Iterator const& begin, + Accessor const& accessor, + const basegfx::B2IRange& rRange) + { + return vigra::triple<Iterator,Iterator,Accessor>( + begin + topLeft(rRange), + begin + bottomRight(rRange), + accessor); + } + + template< class Iterator, class Accessor > + inline vigra::pair<Iterator,Accessor> + srcIter(Iterator const& begin, + Accessor const& accessor, + const basegfx::B2IPoint& rPt) + { + return vigra::pair<Iterator,Accessor>( + begin + vigra::Diff2D(rPt.getX(),rPt.getY()), + accessor); + } + + template< class Iterator, class Accessor > + inline vigra::pair<Iterator,Accessor> + destIter(Iterator const& begin, + Accessor const& accessor, + const basegfx::B2IPoint& rPt) + { + return vigra::pair<Iterator,Accessor>( + begin + vigra::Diff2D(rPt.getX(),rPt.getY()), + accessor); + } +} + +#endif /* INCLUDED_BASEBMP_TOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/inc/basebmp/truecolormaskaccessor.hxx b/basebmp/inc/basebmp/truecolormaskaccessor.hxx new file mode 100644 index 000000000000..79693a7b0ebb --- /dev/null +++ b/basebmp/inc/basebmp/truecolormaskaccessor.hxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX +#define INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX + +#include <basebmp/colortraits.hxx> +#include <basebmp/accessortraits.hxx> +#include <basebmp/metafunctions.hxx> +#include <basebmp/endian.hxx> + +#include <vigra/numerictraits.hxx> +#include <vigra/metaprogramming.hxx> + +namespace basebmp +{ + +namespace +{ + /// Shift left for positive shift value, and right otherwise + template< typename T > inline T shiftLeft( T v, int shift ) + { + return shift > 0 ? v << shift : v >> (-shift); + } + + /// Shift right for positive shift value, and left otherwise + template< typename T > inline T shiftRight( T v, int shift ) + { + return shift > 0 ? v >> shift : v << (-shift); + } +} + +/** Access true color data, which is pixel-packed into a POD. + + @tpl Accessor + Wrapped accessor, used to access the actual pixel values + + @tpl ColorType + Underlying color type, to convert the pixel values into + + @tpl RedMask + Bitmask, to access the red bits in the data type + + @tpl GreenMask + Bitmask, to access the green bits in the data type + + @tpl BlueMask + Bitmask, to access the blue bits in the data type + + @tpl SwapBytes + When true, the final pixel values will be byte-swapped before + passed to/from the iterator. + */ +template< class Accessor, + typename ColorType, + int RedMask, + int GreenMask, + int BlueMask, + bool SwapBytes > class TrueColorMaskAccessor +{ +public: + typedef typename Accessor::value_type data_type; + typedef ColorType value_type; + typedef typename make_unsigned<data_type>::type unsigned_data_type; + typedef typename ColorTraits<ColorType>::component_type component_type; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +// making all members public, if no member template friends +private: + template<class A, typename C, int R, int G, int B, bool S> friend class TrueColorMaskAccessor; +#endif + + Accessor maAccessor; + +public: + // calc corrective shifts for all three channels in advance + enum { + red_shift = numberOfTrailingZeros<RedMask>::value, + green_shift = numberOfTrailingZeros<GreenMask>::value, + blue_shift = numberOfTrailingZeros<BlueMask>::value, + + red_bits = bitcount<RedMask>::value, + green_bits = bitcount<GreenMask>::value, + blue_bits = bitcount<BlueMask>::value + }; + + // ------------------------------------------------------- + + TrueColorMaskAccessor() : + maAccessor() + {} + + template< class A > explicit + TrueColorMaskAccessor( TrueColorMaskAccessor< A, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes > const& rSrc ) : + maAccessor( rSrc.maAccessor ) + {} + + template< class T > explicit TrueColorMaskAccessor( T accessor ) : + maAccessor(accessor) + {} + + // ------------------------------------------------------- + + Accessor const& getWrappedAccessor() const { return maAccessor; } + Accessor& getWrappedAccessor() { return maAccessor; } + + // ------------------------------------------------------- + + value_type toValue( unsigned_data_type v ) const + { + v = SwapBytes ? byteSwap(v) : v; + + const unsigned_data_type red (v & RedMask); + const unsigned_data_type green(v & GreenMask); + const unsigned_data_type blue (v & BlueMask); + + value_type res( (shiftRight(red, + red_shift-8*sizeof(component_type)+red_bits)) | + (shiftRight(red, + red_shift-8*sizeof(component_type)+2*red_bits)), + + (shiftRight(green, + green_shift-8*sizeof(component_type)+green_bits)) | + (shiftRight(green, + green_shift-8*sizeof(component_type)+2*green_bits)), + + (shiftRight(blue, + blue_shift-8*sizeof(component_type)+blue_bits)) | + (shiftRight(blue, + blue_shift-8*sizeof(component_type)+2*blue_bits)) ); + return res; + } + + data_type toPacked( value_type v ) const + { + const unsigned_data_type red (v.getRed()); + const unsigned_data_type green(v.getGreen()); + const unsigned_data_type blue (v.getBlue()); + + unsigned_data_type res( + (shiftLeft(red, + red_shift-8*sizeof(component_type)+red_bits) & RedMask) | + (shiftLeft(green, + green_shift-8*sizeof(component_type)+green_bits) & GreenMask) | + (shiftLeft(blue, + blue_shift-8*sizeof(component_type)+blue_bits) & BlueMask) ); + + return SwapBytes ? byteSwap(res) : res; + } + + // ------------------------------------------------------- + + template< class Iterator > + value_type operator()(Iterator const& i) const + { + return toValue( + unsigned_cast<data_type>( maAccessor(i)) ); + } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return toValue( + unsigned_cast<data_type>( maAccessor(i,diff)) ); + } + + // ------------------------------------------------------- + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + maAccessor.set( + toPacked( + vigra::detail::RequiresExplicitCast<value_type>::cast( + value) ), + i); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + maAccessor.set( + toPacked( + vigra::detail::RequiresExplicitCast<value_type>::cast( + value)), + i, + diff ); + } +}; + +//----------------------------------------------------------------------------- + +/** Convert Color to packed true color value for TrueColorMaskAccessor + */ +template< class Accessor > struct ColorConvert +{ + typename Accessor::data_type operator()( const Accessor& acc, + typename Accessor::value_type v ) + { + return acc.toPacked(v); + } +}; + +//----------------------------------------------------------------------------- + +// partial specialization for TrueColorMaskAccessor +template< class Accessor, + typename ColorType, + int RedMask, + int GreenMask, + int BlueMask, + bool SwapBytes > struct AccessorTraits< + TrueColorMaskAccessor< Accessor, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes > > +{ + /// value type of described accessor + typedef typename TrueColorMaskAccessor< Accessor, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes >::value_type value_type; + + /// Retrieve stand-alone color lookup function for given Accessor type + typedef ColorConvert< TrueColorMaskAccessor< Accessor, + ColorType, + RedMask, + GreenMask, + BlueMask, + SwapBytes > > color_lookup; + + /// Retrieve raw pixel data accessor for given Accessor type + typedef Accessor raw_accessor; + + /** accessor for XOR setter access is disabled, since the results + * are usually completely unintended - you'll usually want to + * wrap an xor_accessor with a TrueColorMaskAccessor, not the + * other way around. + */ + typedef vigra::VigraFalseType xor_accessor; + + /** accessor for masked setter access is disabled, since the + * results are usually completely unintended - you'll usually + * want to wrap a masked_accessor with a TrueColorMaskAccessor, + * not the other way around. + */ + template< class MaskAccessor, + class Iterator, + class MaskIterator > struct masked_accessor + { + typedef vigra::VigraFalseType type; + }; +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_TRUECOLORMASKACCESSOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/prj/build.lst b/basebmp/prj/build.lst new file mode 100644 index 000000000000..2b0fa1e0f72a --- /dev/null +++ b/basebmp/prj/build.lst @@ -0,0 +1,2 @@ +bx basebmp : sal VIGRA:vigra basegfx BOOST:boost NULL +bx basebmp\prj nmake - all bx_prj NULL diff --git a/basebmp/prj/d.lst b/basebmp/prj/d.lst new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/basebmp/prj/d.lst diff --git a/basebmp/prj/makefile.mk b/basebmp/prj/makefile.mk new file mode 100644 index 000000000000..d4cf94ec9f4e --- /dev/null +++ b/basebmp/prj/makefile.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. +TARGET=prj + +.INCLUDE : settings.mk + +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s +.ENDIF + +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(GMAKE_MODULE_PARALLELISM) $(gb_MAKETARGET) && $(GNUMAKE) $(VERBOSEFLAG) -r deliverlog diff --git a/basebmp/source/bitmapdevice.cxx b/basebmp/source/bitmapdevice.cxx new file mode 100644 index 000000000000..a483197aa54d --- /dev/null +++ b/basebmp/source/bitmapdevice.cxx @@ -0,0 +1,2103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// FIXME: in vigra +#if defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x580) +#include <math.h> // needed for fabs, hypot +#endif +#include "basebmp/bitmapdevice.hxx" + +#include "basebmp/compositeiterator.hxx" +#include "basebmp/iteratortraits.hxx" + +#include "basebmp/accessor.hxx" +#include "basebmp/accessortraits.hxx" +#include "basebmp/accessoradapters.hxx" +#include "basebmp/colorblendaccessoradapter.hxx" + +#include "basebmp/color.hxx" +#include "basebmp/colormisc.hxx" +#include "basebmp/colortraits.hxx" + +#include "basebmp/greylevelformats.hxx" +#include "basebmp/paletteformats.hxx" +#include "basebmp/rgbmaskpixelformats.hxx" +#include "basebmp/rgb24pixelformats.hxx" + +#include "basebmp/scanlineformats.hxx" +#include "basebmp/fillimage.hxx" +#include "basebmp/scaleimage.hxx" +#include "basebmp/clippedlinerenderer.hxx" +#include "basebmp/polypolygonrenderer.hxx" +#include "basebmp/genericcolorimageaccessor.hxx" + +#include "basebmp/tools.hxx" +#include "intconversion.hxx" + +#include <rtl/alloc.h> +#include <rtl/memory.h> +#include <osl/diagnose.h> + +#include <basegfx/tools/tools.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/vector/b2ivector.hxx> + +#include <vigra/iteratortraits.hxx> +#include <vigra/rgbvalue.hxx> +#include <vigra/copyimage.hxx> +#include <vigra/tuple.hxx> + + +namespace vigra +{ + +/// componentwise xor of an RGBValue (missing from rgbvalue.hxx) +template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex > +inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex> +operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs, + RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs ) +{ + RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res( + lhs[0] ^ rhs[0], + lhs[1] ^ rhs[1], + lhs[2] ^ rhs[2]); + return res; +} +} + +namespace basebmp +{ + +namespace +{ + /** Create the type for an accessor that takes the (mask,bitmap) + input value generated from a JoinImageAccessorAdapter, and + pipe that through a mask functor. + + @tpl DestAccessor + Destination bitmap accessor + + @tpl JoinedAccessor + Input accessor, is expected to generate a std::pair as the + value type + + @tpl MaskFunctorMode + Either FastMask or NoFastMask, depending on whether the mask + is guaranteed to contain only 0s and 1s. + */ + template< class DestAccessor, + class JoinedAccessor, + bool polarity, + typename MaskFunctorMode > struct masked_input_splitting_accessor + { + typedef BinarySetterFunctionAccessorAdapter< + DestAccessor, + BinaryFunctorSplittingWrapper< + typename outputMaskFunctorSelector< + typename JoinedAccessor::value_type::first_type, + typename JoinedAccessor::value_type::second_type, + polarity, + MaskFunctorMode >::type > > type; + }; + + + + // Actual BitmapDevice implementation (templatized by accessor and iterator) + //-------------------------------------------------------------------------- + + /** Implementation of the BitmapDevice interface + + @tpl DestIterator + Iterator to access bitmap memory + + @tpl RawAccessor + Raw accessor, to access pixel values directly + + @tpl AccessorSelector + Accessor adapter selector, which, when applying the nested + template metafunction wrap_accessor to one of the raw bitmap + accessors, yields a member type named 'type', which is a + wrapped accessor that map color values. + + @tpl Masks + Traits template, containing nested traits + clipmask_format_traits and alphamask_format_traits, which + determine what specialized formats are to be used for clip and + alpha masks. With those mask formats, clipping and alpha + blending is handled natively. + */ + template< class DestIterator, + class RawAccessor, + class AccessorSelector, + class Masks > class BitmapRenderer : + public BitmapDevice + { + public: + typedef DestIterator dest_iterator_type; + typedef RawAccessor raw_accessor_type; + typedef AccessorSelector accessor_selector; + + typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type; + typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type; + typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type; + + typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type; + typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type; + typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type; + + typedef typename AccessorSelector::template wrap_accessor< + raw_accessor_type >::type dest_accessor_type; + + typedef AccessorTraits< dest_accessor_type > accessor_traits; + typedef CompositeIterator2D< dest_iterator_type, + mask_iterator_type > composite_iterator_type; + typedef CompositeIterator2D< vigra::Diff2D, + vigra::Diff2D > generic_composite_iterator_type; + + typedef BitmapRenderer<mask_iterator_type, + mask_rawaccessor_type, + mask_accessorselector_type, + Masks> mask_bitmap_type; + typedef BitmapRenderer<alphamask_iterator_type, + alphamask_rawaccessor_type, + alphamask_accessorselector_type, + Masks> alphamask_bitmap_type; + + // ------------------------------------------------------- + + typedef AccessorTraits< raw_accessor_type > raw_accessor_traits; + typedef typename uInt32Converter< + typename raw_accessor_type::value_type>::to to_uint32_functor; + + // ------------------------------------------------------- + + typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type; + typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits; + typedef typename accessor_selector::template wrap_accessor< + raw_xor_accessor_type >::type xor_accessor_type; + typedef AccessorTraits<xor_accessor_type> xor_accessor_traits; + + // ------------------------------------------------------- + + typedef typename raw_accessor_traits::template masked_accessor< + mask_rawaccessor_type, + dest_iterator_type, + mask_iterator_type, + Masks::clipmask_polarity>::type raw_maskedaccessor_type; + typedef typename accessor_selector::template wrap_accessor< + raw_maskedaccessor_type >::type masked_accessor_type; + typedef typename AccessorTraits< + raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type; + typedef typename accessor_selector::template wrap_accessor< + raw_maskedxor_accessor_type >::type masked_xoraccessor_type; + + // ------------------------------------------------------- + + // ((iter,mask),mask) special case (e.g. for clipped + // drawMaskedColor()) + typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits; + typedef typename raw_maskedaccessor_traits::template masked_accessor< + mask_rawaccessor_type, + composite_iterator_type, + mask_iterator_type, + Masks::clipmask_polarity>::type raw_maskedmask_accessor_type; + + typedef CompositeIterator2D< + composite_iterator_type, + mask_iterator_type> composite_composite_mask_iterator_type; + + // ------------------------------------------------------- + + typedef ConstantColorBlendSetterAccessorAdapter< + dest_accessor_type, + typename alphamask_rawaccessor_type::value_type, + Masks::alphamask_polarity> colorblend_accessor_type; + typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits; + typedef typename colorblend_accessor_traits::template masked_accessor< + mask_rawaccessor_type, + dest_iterator_type, + mask_iterator_type, + Masks::clipmask_polarity>::type masked_colorblend_accessor_type; + + // ------------------------------------------------------- + + typedef ConstantColorBlendSetterAccessorAdapter< + dest_accessor_type, + Color, + Masks::alphamask_polarity> colorblend_generic_accessor_type; + typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits; + typedef typename colorblend_generic_accessor_traits::template masked_accessor< + mask_rawaccessor_type, + dest_iterator_type, + mask_iterator_type, + Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type; + + // ------------------------------------------------------- + + typedef JoinImageAccessorAdapter< dest_accessor_type, + mask_rawaccessor_type > joined_image_accessor_type; + typedef JoinImageAccessorAdapter< GenericColorImageAccessor, + GenericColorImageAccessor > joined_generic_image_accessor_type; + + // ------------------------------------------------------- + + dest_iterator_type maBegin; + typename accessor_traits::color_lookup maColorLookup; + BitmapDeviceDamageTracker *mpDamage; + to_uint32_functor maToUInt32Converter; + dest_accessor_type maAccessor; + colorblend_accessor_type maColorBlendAccessor; + colorblend_generic_accessor_type maGenericColorBlendAccessor; + raw_accessor_type maRawAccessor; + xor_accessor_type maXorAccessor; + raw_xor_accessor_type maRawXorAccessor; + masked_accessor_type maMaskedAccessor; + masked_colorblend_accessor_type maMaskedColorBlendAccessor; + masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor; + masked_xoraccessor_type maMaskedXorAccessor; + raw_maskedaccessor_type maRawMaskedAccessor; + raw_maskedxor_accessor_type maRawMaskedXorAccessor; + raw_maskedmask_accessor_type maRawMaskedMaskAccessor; + + + // ------------------------------------------------------- + + BitmapRenderer( const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + dest_iterator_type begin, + raw_accessor_type rawAccessor, + dest_accessor_type accessor, + const RawMemorySharedArray& rMem, + const PaletteMemorySharedVector& rPalette, + BitmapDeviceDamageTracker* pDamage ) : + BitmapDevice( rBounds, nScanlineFormat, + nScanlineStride, pFirstScanline, rMem, rPalette, + pDamage ), + maBegin( begin ), + maColorLookup(), + mpDamage( pDamage ), + maToUInt32Converter(), + maAccessor( accessor ), + maColorBlendAccessor( accessor ), + maGenericColorBlendAccessor( accessor ), + maRawAccessor( rawAccessor ), + maXorAccessor( accessor ), + maRawXorAccessor( rawAccessor ), + maMaskedAccessor( accessor ), + maMaskedColorBlendAccessor( maColorBlendAccessor ), + maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ), + maMaskedXorAccessor( accessor ), + maRawMaskedAccessor( rawAccessor ), + maRawMaskedXorAccessor( rawAccessor ), + maRawMaskedMaskAccessor( rawAccessor ) + {} + + private: + + void damaged( const basegfx::B2IRange& rDamageRect ) const + { + if( mpDamage ) + mpDamage->damaged( rDamageRect ); + } + + void damagedPointSize( const basegfx::B2IPoint& rPoint, + const basegfx::B2IRange& rSize ) const + { + if( mpDamage ) { + basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(), + rPoint.getY() + rSize.getHeight() ); + damaged( basegfx::B2IRange( rPoint, aLower ) ); + } + } + + void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const + { + if( !mpDamage ) + return; + basegfx::B2IPoint aEnd( rDamagePoint.getX() + 1, + rDamagePoint.getY() + 1 ); + damaged( basegfx::B2IRange( rDamagePoint, aEnd ) ); + } + + boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const + { + return boost::dynamic_pointer_cast< BitmapRenderer >( bmp ); + } + + virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const + { + // TODO(P1): dynamic_cast usually called twice for + // compatible formats + return getCompatibleBitmap(bmp).get() != NULL; + } + + boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const + { + boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp )); + + if( !pMask ) + return pMask; + + if( pMask->getSize() != getSize() ) + pMask.reset(); + + return pMask; + } + + virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const + { + // TODO(P1): dynamic_cast usually called twice for + // compatible formats + return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL; + } + + boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const + { + return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp ); + } + + virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const + { + // TODO(P1): dynamic_cast usually called twice for + // compatible formats + return getCompatibleAlphaMask( bmp ).get() != NULL; + } + + virtual void clear_i( Color fillColor, + const basegfx::B2IRange& rBounds ) + { + fillImage(destIterRange(maBegin, + maRawAccessor, + rBounds), + maColorLookup( + maAccessor, + fillColor) ); + damaged( rBounds ); + } + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode ) + { + const DestIterator pixel( maBegin + + vigra::Diff2D(rPt.getX(), + rPt.getY()) ); + if( drawMode == DrawMode_XOR ) + maXorAccessor.set( pixelColor, + pixel ); + else + maAccessor.set( pixelColor, + pixel ); + damagedPixel(rPt); + } + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) ); + OSL_ASSERT( pMask ); + + const vigra::Diff2D offset(rPt.getX(), + rPt.getY()); + + const composite_iterator_type aIter( + maBegin + offset, + pMask->maBegin + offset ); + + if( drawMode == DrawMode_XOR ) + maMaskedXorAccessor.set( pixelColor, + aIter ); + else + maMaskedAccessor.set( pixelColor, + aIter ); + damagedPixel(rPt); + } + + virtual Color getPixel_i(const basegfx::B2IPoint& rPt ) + { + const DestIterator pixel( maBegin + + vigra::Diff2D(rPt.getX(), + rPt.getY()) ); + return maAccessor(pixel); + } + + virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt ) + { + const DestIterator pixel( maBegin + + vigra::Diff2D(rPt.getX(), + rPt.getY()) ); + return maToUInt32Converter(maRawAccessor(pixel)); + } + + template< typename Iterator, typename Col, typename RawAcc > + void implRenderLine2( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Col col, + const Iterator& begin, + const RawAcc& rawAcc ) + { + renderClippedLine( rPt1, + rPt2, + rBounds, + col, + begin, + rawAcc ); + // FIXME: perhaps this needs pushing up the stack a bit + // to make more complex polygons more efficient ... + damaged( basegfx::B2IRange( rPt1, rPt2 ) ); + } + + template< typename Iterator, typename Accessor, typename RawAcc > + void implRenderLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color col, + const Iterator& begin, + const Accessor& acc, + const RawAcc& rawAcc ) + { + implRenderLine2( rPt1,rPt2,rBounds, + maColorLookup( acc, + col ), + begin, + rawAcc ); + } + + template< typename Iterator, typename RawAcc, typename XorAcc > + void implDrawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color col, + const Iterator& begin, + const RawAcc& rawAcc, + const XorAcc& xorAcc, + DrawMode drawMode ) + { + if( drawMode == DrawMode_XOR ) + implRenderLine( rPt1, rPt2, rBounds, col, + begin, maAccessor, xorAcc ); + else + implRenderLine( rPt1, rPt2, rBounds, col, + begin, maAccessor, rawAcc ); + } + + virtual void drawLine_i(const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode ) + { + implDrawLine(rPt1,rPt2,rBounds,lineColor, + maBegin, + maRawAccessor,maRawXorAccessor,drawMode); + } + + composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const + { + boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) ); + OSL_ASSERT( pMask ); + + return composite_iterator_type( maBegin, + pMask->maBegin ); + } + + virtual void drawLine_i(const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + implDrawLine(rPt1,rPt2,rBounds,lineColor, + getMaskedIter(rClip), + maRawMaskedAccessor, + maRawMaskedXorAccessor,drawMode); + } + + template< typename Iterator, typename RawAcc > + void implDrawPolygon( const basegfx::B2DPolygon& rPoly, + const basegfx::B2IRange& rBounds, + Color col, + const Iterator& begin, + const RawAcc& acc ) + { + basegfx::B2DPolygon aPoly( rPoly ); + if( rPoly.areControlPointsUsed() ) + aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly ); + + const typename dest_iterator_type::value_type colorIndex( maColorLookup( + maAccessor, + col)); + const sal_uInt32 nVertices( aPoly.count() ); + for( sal_uInt32 i=1; i<nVertices; ++i ) + implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)), + basegfx::fround(aPoly.getB2DPoint(i)), + rBounds, + colorIndex, + begin, + acc ); + + if( nVertices > 1 && aPoly.isClosed() ) + implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)), + basegfx::fround(aPoly.getB2DPoint(0)), + rBounds, + colorIndex, + begin, + acc ); + } + + virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode ) + { + if( drawMode == DrawMode_XOR ) + implDrawPolygon( rPoly, rBounds, lineColor, + maBegin, + maRawXorAccessor ); + else + implDrawPolygon( rPoly, rBounds, lineColor, + maBegin, + maRawAccessor ); + } + + virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, + const basegfx::B2IRange& rBounds, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + if( drawMode == DrawMode_XOR ) + implDrawPolygon( rPoly, rBounds, lineColor, + getMaskedIter(rClip), + maRawMaskedXorAccessor ); + else + implDrawPolygon( rPoly, rBounds, lineColor, + getMaskedIter(rClip), + maRawMaskedAccessor ); + } + + template< typename Iterator, typename RawAcc > + void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color col, + const Iterator& begin, + const RawAcc& acc, + const basegfx::B2IRange& rBounds ) + { + basegfx::B2DPolyPolygon aPoly( rPoly ); + if( rPoly.areControlPointsUsed() ) + aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly ); + + renderClippedPolyPolygon( begin, + acc, + maColorLookup( maAccessor, + col), + rBounds, + aPoly, + basegfx::FillRule_EVEN_ODD ); + + if( mpDamage ) + { + basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) ); + damaged( basegfx::fround( aPolyBounds ) ); + } + } + + virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds ) + { + if( drawMode == DrawMode_XOR ) + implFillPolyPolygon( rPoly, fillColor, + maBegin, + maRawXorAccessor, + rBounds ); + else + implFillPolyPolygon( rPoly, fillColor, + maBegin, + maRawAccessor, + rBounds ); + } + + virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds, + const BitmapDeviceSharedPtr& rClip ) + { + if( drawMode == DrawMode_XOR ) + implFillPolyPolygon( rPoly, fillColor, + getMaskedIter(rClip), + maRawMaskedXorAccessor, + rBounds ); + else + implFillPolyPolygon( rPoly, fillColor, + getMaskedIter(rClip), + maRawMaskedAccessor, + rBounds ); + } + + template< typename Iterator, typename RawAcc > + void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + const Iterator& begin, + const RawAcc& acc) + { + boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) ); + OSL_ASSERT( pSrcBmp ); + + scaleImage( + srcIterRange(pSrcBmp->maBegin, + pSrcBmp->maRawAccessor, + rSrcRect), + destIterRange(begin, + acc, + rDstRect), + rSrcBitmap.get() == this ); + damaged( rDstRect ); + } + + template< typename Iterator, typename Acc > + void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + const Iterator& begin, + const Acc& acc) + { + GenericColorImageAccessor aSrcAcc( rSrcBitmap ); + + scaleImage( + srcIterRange(vigra::Diff2D(), + aSrcAcc, + rSrcRect), + destIterRange(begin, + acc, + rDstRect)); + damaged( rDstRect ); + } + + virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) + { + if( isCompatibleBitmap( rSrcBitmap ) ) + { + if( drawMode == DrawMode_XOR ) + implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, + maBegin, + maRawXorAccessor); + else + implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, + maBegin, + maRawAccessor); + } + else + { + if( drawMode == DrawMode_XOR ) + implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, + maBegin, + maXorAccessor); + else + implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, + maBegin, + maAccessor); + } + damaged( rDstRect ); + } + + virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + if( isCompatibleBitmap( rSrcBitmap ) ) + { + if( drawMode == DrawMode_XOR ) + implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, + getMaskedIter(rClip), + maRawMaskedXorAccessor); + else + implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect, + getMaskedIter(rClip), + maRawMaskedAccessor); + } + else + { + if( drawMode == DrawMode_XOR ) + implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedXorAccessor); + else + implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedAccessor); + } + damaged( rDstRect ); + } + + virtual void drawMaskedColor_i(Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ) + { + boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) ); + boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) ); + + if( pAlpha ) + { + maColorBlendAccessor.setColor( aSrcColor ); + + vigra::copyImage( srcIterRange(pAlpha->maBegin, + pAlpha->maRawAccessor, + rSrcRect), + destIter(maBegin, + maColorBlendAccessor, + rDstPoint) ); + } + else if( pMask ) + { + const composite_iterator_type aBegin( + maBegin + vigra::Diff2D(rDstPoint.getX(), + rDstPoint.getY()), + pMask->maBegin + topLeft(rSrcRect) ); + + fillImage(aBegin, + aBegin + vigra::Diff2D(rSrcRect.getWidth(), + rSrcRect.getHeight()), + maRawMaskedAccessor, + maColorLookup( + maAccessor, + aSrcColor) ); + } + else + { + GenericColorImageAccessor aSrcAcc( rAlphaMask ); + maGenericColorBlendAccessor.setColor( aSrcColor ); + + vigra::copyImage( srcIterRange(vigra::Diff2D(), + aSrcAcc, + rSrcRect), + destIter(maBegin, + maGenericColorBlendAccessor, + rDstPoint) ); + } + damagedPointSize( rDstPoint, rSrcRect ); + } + + virtual void drawMaskedColor_i(Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) + { + boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) ); + boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) ); + + if( pAlpha ) + { + const composite_iterator_type aBegin( getMaskedIter(rClip) ); + maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( + aSrcColor ); + + vigra::copyImage( srcIterRange(pAlpha->maBegin, + pAlpha->maRawAccessor, + rSrcRect), + destIter(aBegin, + maMaskedColorBlendAccessor, + rDstPoint) ); + } + else if( pMask ) + { + boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) ); + OSL_ASSERT( pClipMask ); + + // setup a ((iter,mask),clipMask) composite composite + // iterator, to pass both masks (clip and alpha mask) + // to the algorithm + const composite_composite_mask_iterator_type aBegin( + composite_iterator_type( + maBegin + vigra::Diff2D(rDstPoint.getX(), + rDstPoint.getY()), + pMask->maBegin + topLeft(rSrcRect)), + pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(), + rDstPoint.getY()) ); + + fillImage(aBegin, + aBegin + vigra::Diff2D(rSrcRect.getWidth(), + rSrcRect.getHeight()), + maRawMaskedMaskAccessor, + maColorLookup( + maAccessor, + aSrcColor) ); + } + else + { + GenericColorImageAccessor aSrcAcc( rAlphaMask ); + const composite_iterator_type aBegin( getMaskedIter(rClip) ); + maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( + aSrcColor ); + + vigra::copyImage( srcIterRange(vigra::Diff2D(), + aSrcAcc, + rSrcRect), + destIter(aBegin, + maGenericMaskedColorBlendAccessor, + rDstPoint) ); + } + damagedPointSize( rDstPoint, rSrcRect ); + } + + template< typename Iterator, typename Acc > + void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + const Iterator& begin, + const Acc& acc) + { + boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) ); + boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) ); + OSL_ASSERT( pMask && pSrcBmp ); + + scaleImage( + srcIterRange(composite_iterator_type( + pSrcBmp->maBegin, + pMask->maBegin), + joined_image_accessor_type( + pSrcBmp->maAccessor, + pMask->maRawAccessor), + rSrcRect), + destIterRange(begin, + typename masked_input_splitting_accessor< + Acc, + joined_image_accessor_type, + Masks::clipmask_polarity, + FastMask >::type(acc), + rDstRect), + rSrcBitmap.get() == this); + damaged( rDstRect ); + } + + template< typename Iterator, typename Acc > + void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + const Iterator& begin, + const Acc& acc) + { + GenericColorImageAccessor aSrcAcc( rSrcBitmap ); + GenericColorImageAccessor aMaskAcc( rMask ); + + const vigra::Diff2D aTopLeft(rSrcRect.getMinX(), + rSrcRect.getMinY()); + const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(), + rSrcRect.getMaxY()); + scaleImage( + vigra::make_triple( + generic_composite_iterator_type( + aTopLeft,aTopLeft), + generic_composite_iterator_type( + aBottomRight,aBottomRight), + joined_generic_image_accessor_type( + aSrcAcc, + aMaskAcc)), + destIterRange(begin, + typename masked_input_splitting_accessor< + Acc, + joined_generic_image_accessor_type, + Masks::clipmask_polarity, + NoFastMask >::type(acc), + rDstRect)); + damaged( rDstRect ); + } + + virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) + { + if( isCompatibleClipMask(rMask) && + isCompatibleBitmap(rSrcBitmap) ) + { + if( drawMode == DrawMode_XOR ) + implDrawMaskedBitmap(rSrcBitmap, rMask, + rSrcRect, rDstRect, + maBegin, + maXorAccessor); + else + implDrawMaskedBitmap(rSrcBitmap, rMask, + rSrcRect, rDstRect, + maBegin, + maAccessor); + } + else + { + if( drawMode == DrawMode_XOR ) + implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, + rSrcRect, rDstRect, + maBegin, + maXorAccessor); + else + implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, + rSrcRect, rDstRect, + maBegin, + maAccessor); + } + damaged( rDstRect ); + } + + virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + if( isCompatibleClipMask(rMask) && + isCompatibleBitmap(rSrcBitmap) ) + { + if( drawMode == DrawMode_XOR ) + implDrawMaskedBitmap(rSrcBitmap, rMask, + rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedXorAccessor); + else + implDrawMaskedBitmap(rSrcBitmap, rMask, + rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedAccessor); + } + else + { + if( drawMode == DrawMode_XOR ) + implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, + rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedXorAccessor); + else + implDrawMaskedBitmapGeneric(rSrcBitmap, rMask, + rSrcRect, rDstRect, + getMaskedIter(rClip), + maMaskedAccessor); + } + damaged( rDstRect ); + } + }; +} // namespace + +struct ImplBitmapDevice +{ + /** Bitmap memory plus deleter. + + Always points to the start of the mem + */ + RawMemorySharedArray mpMem; + + BitmapDeviceDamageTracker *mpDamage; + + /// Palette memory plus deleter (might be NULL) + PaletteMemorySharedVector mpPalette; + + /** Bounds of the device. + + maBounds.getWidth()/getHeight() yield the true size of the + device (i.e. the rectangle given by maBounds covers the device + area under the excluding-bottommost-and-rightmost-pixels fill + rule) + */ + basegfx::B2IRange maBounds; + + /** Bounds of the device. + + maBounds.getWidth()/getHeight() yield the true size of the + device minus 1 (i.e. the rectangle given by maBounds covers + the device area under the + including-the-bottommost-and-rightmost-pixels fill rule). + + The member is used to clip line stroking against the device + bounds. + */ + basegfx::B2IRange maLineClipRect; + + /// Scanline format, as provided at the constructor + sal_Int32 mnScanlineFormat; + + /// Scanline stride. Negative for bottom-to-top formats + sal_Int32 mnScanlineStride; + + /// raw ptr to 0th scanline. used for cloning a generic renderer + sal_uInt8* mpFirstScanline; + + /** (Optional) device sharing the same memory, and used for input + clip masks/alpha masks/bitmaps that don't match our exact + bitmap format. + + This is to avoid the combinatorical explosion when dealing + with n bitmap formats, which could be combined with n clip + masks, alpha masks and bitmap masks (yielding a total of n^4 + combinations). Since each BitmapRenderer is specialized for + one specific combination of said formats, a lot of duplicate + code would be generated, most of which probably never + used. Therefore, only the most common combinations are + specialized templates, the remainder gets handled by this + generic renderer (via runtime polymorphism). + */ + BitmapDeviceSharedPtr mpGenericRenderer; +}; + + +BitmapDevice::BitmapDevice( const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + const RawMemorySharedArray& rMem, + const PaletteMemorySharedVector& rPalette, + BitmapDeviceDamageTracker* pDamage ) : + mpImpl( new ImplBitmapDevice ) +{ + mpImpl->mpMem = rMem; + mpImpl->mpDamage = pDamage; + mpImpl->mpPalette = rPalette; + mpImpl->maBounds = rBounds; + mpImpl->maLineClipRect = basegfx::B2IRange( rBounds.getMinX(), + rBounds.getMinY(), + rBounds.getMaxX()-1, + rBounds.getMaxY()-1 ); + mpImpl->mnScanlineFormat = nScanlineFormat; + mpImpl->mnScanlineStride = nScanlineStride; + mpImpl->mpFirstScanline = pFirstScanline; +} + +BitmapDevice::~BitmapDevice() +{ + // outline, because of internal ImplBitmapDevice +} + +basegfx::B2IVector BitmapDevice::getSize() const +{ + return basegfx::B2IVector( + mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(), + mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() ); +} + +bool BitmapDevice::isTopDown() const +{ + return mpImpl->mnScanlineStride >= 0; +} + +sal_Int32 BitmapDevice::getScanlineFormat() const +{ + return mpImpl->mnScanlineFormat; +} + +sal_Int32 BitmapDevice::getScanlineStride() const +{ + return mpImpl->mnScanlineStride < 0 ? + -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride; +} + +RawMemorySharedArray BitmapDevice::getBuffer() const +{ + return mpImpl->mpMem; +} + +PaletteMemorySharedVector BitmapDevice::getPalette() const +{ + return mpImpl->mpPalette; +} + +BitmapDeviceDamageTracker *BitmapDevice::getDamageTracker() const +{ + return mpImpl->mpDamage; +} + +sal_Int32 BitmapDevice::getPaletteEntryCount() const +{ + return mpImpl->mpPalette ? mpImpl->mpPalette->size() : 0; +} + +void BitmapDevice::clear( Color fillColor ) +{ + clear_i( fillColor, mpImpl->maBounds ); +} + +void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode ) +{ + if( mpImpl->maLineClipRect.isInside(rPt) ) + setPixel_i(rPt,lineColor,drawMode); +} + +void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + setPixel(rPt,lineColor,drawMode); + return; + } + + if( mpImpl->maLineClipRect.isInside(rPt) ) + { + if( isCompatibleClipMask( rClip ) ) + setPixel_i(rPt,lineColor,drawMode,rClip); + else + getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip ); + } +} + +Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt ) +{ + if( mpImpl->maLineClipRect.isInside(rPt) ) + return getPixel_i(rPt); + + return Color(); +} + +sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt ) +{ + if( mpImpl->maLineClipRect.isInside(rPt) ) + return getPixelData_i(rPt); + + return 0; +} + +void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode ) +{ + drawLine_i( rPt1, + rPt2, + mpImpl->maLineClipRect, + lineColor, + drawMode ); +} + +void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + drawLine(rPt1,rPt2,lineColor,drawMode); + return; + } + + if( isCompatibleClipMask( rClip ) ) + drawLine_i( rPt1, + rPt2, + mpImpl->maLineClipRect, + lineColor, + drawMode, + rClip ); + else + getGenericRenderer()->drawLine( rPt1, rPt2, lineColor, + drawMode, rClip ); +} + +void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ) +{ + const sal_uInt32 numVertices( rPoly.count() ); + if( numVertices ) + drawPolygon_i( rPoly, + mpImpl->maLineClipRect, + lineColor, drawMode ); +} + +void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + drawPolygon(rPoly,lineColor,drawMode); + return; + } + + const sal_uInt32 numVertices( rPoly.count() ); + if( numVertices ) + { + if( isCompatibleClipMask( rClip ) ) + drawPolygon_i( rPoly, + mpImpl->maLineClipRect, + lineColor, drawMode, rClip ); + else + getGenericRenderer()->drawPolygon( rPoly, lineColor, + drawMode, rClip ); + } +} + +void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode ) +{ + fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds ); +} + +void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + fillPolyPolygon(rPoly,fillColor,drawMode); + return; + } + + if( isCompatibleClipMask( rClip ) ) + fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip ); + else + getGenericRenderer()->fillPolyPolygon( rPoly, fillColor, + drawMode, rClip ); +} + + +namespace +{ + void assertImagePoint( const basegfx::B2IPoint& rPt, + const basegfx::B2IRange& rPermittedRange ) + { + (void)rPt; (void)rPermittedRange; + OSL_ASSERT( rPermittedRange.isInside(rPt) ); + } + + void assertImageRange( const basegfx::B2IRange& rRange, + const basegfx::B2IRange& rPermittedRange ) + { +#if OSL_DEBUG_LEVEL > 0 + basegfx::B2IRange aRange( rRange ); + aRange.intersect( rPermittedRange ); + + OSL_ASSERT( aRange == rRange ); +#else + (void)rRange; (void)rPermittedRange; +#endif + } + + // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down + // to basegfx, and use here! + bool clipAreaImpl( ::basegfx::B2IRange& io_rSourceArea, + ::basegfx::B2IPoint& io_rDestPoint, + const ::basegfx::B2IRange& rSourceBounds, + const ::basegfx::B2IRange& rDestBounds ) + { + const ::basegfx::B2IPoint aSourceTopLeft( + io_rSourceArea.getMinimum() ); + + ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea ); + + // clip source area (which must be inside rSourceBounds) + aLocalSourceArea.intersect( rSourceBounds ); + + if( aLocalSourceArea.isEmpty() ) + return false; + + // calc relative new source area points (relative to orig + // source area) + const ::basegfx::B2IVector aUpperLeftOffset( + aLocalSourceArea.getMinimum()-aSourceTopLeft ); + const ::basegfx::B2IVector aLowerRightOffset( + aLocalSourceArea.getMaximum()-aSourceTopLeft ); + + ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset, + io_rDestPoint + aLowerRightOffset ); + + // clip dest area (which must be inside rDestBounds) + aLocalDestArea.intersect( rDestBounds ); + + if( aLocalDestArea.isEmpty() ) + return false; + + // calc relative new dest area points (relative to orig + // source area) + const ::basegfx::B2IVector aDestUpperLeftOffset( + aLocalDestArea.getMinimum()-io_rDestPoint ); + const ::basegfx::B2IVector aDestLowerRightOffset( + aLocalDestArea.getMaximum()-io_rDestPoint ); + + io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset, + aSourceTopLeft + aDestLowerRightOffset ); + io_rDestPoint = aLocalDestArea.getMinimum(); + + return true; + } + + // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down + // to basegfx, and use here! + bool clipAreaImpl( ::basegfx::B2IRange& io_rDestArea, + ::basegfx::B2IRange& io_rSourceArea, + const ::basegfx::B2IRange& rDestBounds, + const ::basegfx::B2IRange& rSourceBounds ) + { + // extract inherent scale + const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() ); + const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() ); + + // extract range origins + const basegfx::B2IPoint aDestTopLeft( + io_rDestArea.getMinimum() ); + const ::basegfx::B2IPoint aSourceTopLeft( + io_rSourceArea.getMinimum() ); + + ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea ); + + // clip source area (which must be inside rSourceBounds) + aLocalSourceArea.intersect( rSourceBounds ); + + if( aLocalSourceArea.isEmpty() ) + return false; + + // calc relative new source area points (relative to orig + // source area) + const ::basegfx::B2IVector aUpperLeftOffset( + aLocalSourceArea.getMinimum()-aSourceTopLeft ); + const ::basegfx::B2IVector aLowerRightOffset( + aLocalSourceArea.getMaximum()-aSourceTopLeft ); + + ::basegfx::B2IRange aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()), + basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()), + basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()), + basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) ); + + // clip dest area (which must be inside rDestBounds) + aLocalDestArea.intersect( rDestBounds ); + + if( aLocalDestArea.isEmpty() ) + return false; + + // calc relative new dest area points (relative to orig + // source area) + const ::basegfx::B2IVector aDestUpperLeftOffset( + aLocalDestArea.getMinimum()-aDestTopLeft ); + const ::basegfx::B2IVector aDestLowerRightOffset( + aLocalDestArea.getMaximum()-aDestTopLeft ); + + io_rSourceArea = ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX), + basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY), + basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX), + basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) ); + io_rDestArea = aLocalDestArea; + + // final source area clip (chopping round-offs) + io_rSourceArea.intersect( rSourceBounds ); + + if( io_rSourceArea.isEmpty() ) + return false; + + + return true; + } +} + +void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) +{ + const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IRange aDestRange( rDstRect ); + + if( clipAreaImpl( aDestRange, + aSrcRange, + mpImpl->maBounds, + aSrcBounds )) + { + assertImageRange(aDestRange,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode ); + } +} + +void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode); + return; + } + + const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IRange aDestRange( rDstRect ); + + if( clipAreaImpl( aDestRange, + aSrcRange, + mpImpl->maBounds, + aSrcBounds )) + { + assertImageRange(aDestRange,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + if( isCompatibleClipMask( rClip ) ) + { + drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip ); + } + else + { + getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect, + rDstRect, drawMode, rClip ); + } + } +} + +void BitmapDevice::drawMaskedColor( Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ) +{ + const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IPoint aDestPoint( rDstPoint ); + + if( clipAreaImpl( aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + assertImagePoint(aDestPoint,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + if( rAlphaMask.get() == this ) + { + // src == dest, copy rAlphaMask beforehand + // --------------------------------------------------- + + const basegfx::B2ITuple aSize( aSrcRange.getWidth(), + aSrcRange.getHeight() ); + BitmapDeviceSharedPtr pAlphaCopy( + cloneBitmapDevice( aSize, + shared_from_this()) ); + basegfx::B2ITuple aGcc3WorkaroundTemporary; + const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary, + aSize ); + pAlphaCopy->drawBitmap(rAlphaMask, + aSrcRange, + aAlphaRange, + DrawMode_PAINT); + drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint ); + } + else + { + drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint ); + } + } +} + +void BitmapDevice::drawMaskedColor( Color aSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint); + return; + } + + const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IPoint aDestPoint( rDstPoint ); + + if( clipAreaImpl( aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + assertImagePoint(aDestPoint,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + if( isCompatibleClipMask( rClip ) ) + { + if( rAlphaMask.get() == this ) + { + // src == dest, copy rAlphaMask beforehand + // --------------------------------------------------- + + const basegfx::B2ITuple aSize( aSrcRange.getWidth(), + aSrcRange.getHeight() ); + BitmapDeviceSharedPtr pAlphaCopy( + cloneBitmapDevice( aSize, + shared_from_this()) ); + basegfx::B2ITuple aGcc3WorkaroundTemporary; + const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary, + aSize ); + pAlphaCopy->drawBitmap(rAlphaMask, + aSrcRange, + aAlphaRange, + DrawMode_PAINT); + drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip ); + } + else + { + drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip ); + } + } + else + { + getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask, + rSrcRect, rDstPoint, rClip ); + } + } +} + +void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) +{ + OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() ); + + const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IRange aDestRange( rDstRect ); + + if( clipAreaImpl( aDestRange, + aSrcRange, + mpImpl->maBounds, + aSrcBounds )) + { + assertImageRange(aDestRange,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode ); + } +} + +void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( !rClip ) + { + drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode); + return; + } + + OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() ); + + const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IRange aDestRange( rDstRect ); + + if( clipAreaImpl( aDestRange, + aSrcRange, + mpImpl->maBounds, + aSrcBounds )) + { + assertImageRange(aDestRange,mpImpl->maBounds); + assertImageRange(aSrcRange,aSrcBounds); + + if( isCompatibleClipMask( rClip ) ) + { + drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip ); + } + else + { + getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect, + rDstRect, drawMode, rClip ); + } + } +} + + +//---------------------------------------------------------------------------------- + +/** Standard clip and alpha masks + */ +struct StdMasks +{ + typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits; + typedef PixelFormatTraits_GREY8 alphamask_format_traits; + + /// Clipmask: 0 means opaque + static const bool clipmask_polarity = false; + + /// Alpha mask: 0 means fully transparent + static const bool alphamask_polarity = true; +}; + +//---------------------------------------------------------------------------------- + +// Some compilers don't like the nested template wrap_accessor +// reference in the parameter list - being slightly less type safe, +// then. +#ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER + +/// Produces a specialized renderer for the given pixel format +template< class FormatTraits, class MaskTraits > +BitmapDeviceSharedPtr createRenderer( + const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + typename FormatTraits::raw_accessor_type const& rRawAccessor, + typename FormatTraits::accessor_selector::template wrap_accessor< + typename FormatTraits::raw_accessor_type>::type const& rAccessor, + boost::shared_array< sal_uInt8 > pMem, + const PaletteMemorySharedVector& pPal, + BitmapDeviceDamageTracker* pDamage ) +#else + +template< class FormatTraits, class MaskTraits, class Accessor > +BitmapDeviceSharedPtr createRenderer( + const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + typename FormatTraits::raw_accessor_type const& rRawAccessor, + Accessor const& rAccessor, + boost::shared_array< sal_uInt8 > pMem, + const PaletteMemorySharedVector& pPal, + BitmapDeviceDamageTracker* pDamage ) + +#endif +{ + typedef typename FormatTraits::iterator_type Iterator; + typedef BitmapRenderer< Iterator, + typename FormatTraits::raw_accessor_type, + typename FormatTraits::accessor_selector, + MaskTraits > Renderer; + + return BitmapDeviceSharedPtr( + new Renderer( rBounds, + nScanlineFormat, + nScanlineStride, + pFirstScanline, + Iterator( + reinterpret_cast<typename Iterator::value_type*>( + pFirstScanline), + nScanlineStride), + rRawAccessor, + rAccessor, + pMem, + pPal, + pDamage )); +} + +/// Create standard grey level palette +PaletteMemorySharedVector createStandardPalette( + const PaletteMemorySharedVector& pPal, + sal_Int32 nNumEntries ) +{ + if( pPal || nNumEntries <= 0 ) + return pPal; + + boost::shared_ptr< std::vector<Color> > pLocalPal( + new std::vector<Color>(nNumEntries) ); + + const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries ); + --nNumEntries; + for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement ) + pLocalPal->at(i) = Color(0xFF000000 | c); + + pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF); + + return pLocalPal; +} + +template< class FormatTraits, class MaskTraits > +BitmapDeviceSharedPtr createRenderer( + const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + boost::shared_array< sal_uInt8 > pMem, + const PaletteMemorySharedVector& pPal, + BitmapDeviceDamageTracker* pDamage ) +{ + return createRenderer<FormatTraits, + MaskTraits>(rBounds, + nScanlineFormat, + nScanlineStride, + pFirstScanline, + typename FormatTraits::raw_accessor_type(), + typename FormatTraits::accessor_selector::template + wrap_accessor< + typename FormatTraits::raw_accessor_type>::type(), + pMem, + pPal, + pDamage); +} + +template< class FormatTraits, class MaskTraits > +BitmapDeviceSharedPtr createRenderer( + const basegfx::B2IRange& rBounds, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + sal_uInt8* pFirstScanline, + boost::shared_array< sal_uInt8 > pMem, + PaletteMemorySharedVector pPal, + int nBitsPerPixel, + BitmapDeviceDamageTracker* pDamage ) +{ + pPal = createStandardPalette(pPal, + 1UL << nBitsPerPixel); + + OSL_ASSERT(pPal); + return createRenderer<FormatTraits, + MaskTraits>(rBounds, + nScanlineFormat, + nScanlineStride, + pFirstScanline, + typename FormatTraits::raw_accessor_type(), + typename FormatTraits::accessor_selector::template + wrap_accessor< + typename FormatTraits::raw_accessor_type>::type( + &pPal->at(0), + pPal->size()), + pMem, + pPal, + pDamage); +} + +//---------------------------------------------------------------------------------- + +// TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this +// to o3tl or sal/bithacks.hxx ... + +/** Compute the next highest power of 2 of a 32-bit value + + Code devised by Sean Anderson, in good ole HAKMEM + tradition. + + @return 1 << (lg(x - 1) + 1) +*/ +inline sal_uInt32 nextPow2( sal_uInt32 x ) +{ + --x; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return ++x; +} + +//---------------------------------------------------------------------------------- + +namespace +{ +BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + boost::shared_array< sal_uInt8 > pMem, + PaletteMemorySharedVector pPal, + const basegfx::B2IRange* pSubset, + BitmapDeviceDamageTracker* pDamage ) +{ + if( nScanlineFormat <= Format::NONE || + nScanlineFormat > Format::MAX ) + return BitmapDeviceSharedPtr(); + + static const sal_uInt8 bitsPerPixel[] = + { + 0, // NONE + 1, // ONE_BIT_MSB_GREY + 1, // ONE_BIT_LSB_GREY + 1, // ONE_BIT_MSB_PAL + 1, // ONE_BIT_LSB_PAL + 4, // FOUR_BIT_MSB_GREY + 4, // FOUR_BIT_LSB_GREY + 4, // FOUR_BIT_MSB_PAL + 4, // FOUR_BIT_LSB_PAL + 8, // EIGHT_BIT_PAL + 8, // EIGHT_BIT_GREY + 16, // SIXTEEN_BIT_LSB_TC_MASK + 16, // SIXTEEN_BIT_MSB_TC_MASK + 24, // TWENTYFOUR_BIT_TC_MASK + 32, // THIRTYTWO_BIT_TC_MASK + 32, // THIRTYTWO_BIT_TC_MASK_ARGB + }; + + sal_Int32 nScanlineStride(0); + + // round up to full 8 bit, divide by 8 + nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3; + + // rounded up to next full power-of-two number of bytes + const sal_uInt32 bytesPerPixel = nextPow2( + (bitsPerPixel[nScanlineFormat] + 7) >> 3); + + // now make nScanlineStride a multiple of bytesPerPixel + nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel; + + // factor in bottom-up scanline order case + nScanlineStride *= bTopDown ? 1 : -1; + + const std::size_t nMemSize( + (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() ); + + if( !pMem ) + { + pMem.reset( + reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )), + &rtl_freeMemory ); + rtl_zeroMemory(pMem.get(),nMemSize); + } + + sal_uInt8* pFirstScanline = nScanlineStride < 0 ? + pMem.get() + nMemSize + nScanlineStride : pMem.get(); + + // shrink render area to given subset, if given + basegfx::B2IRange aBounds(0,0,rSize.getX(),rSize.getY()); + if( pSubset ) + aBounds.intersect( *pSubset ); + + switch( nScanlineFormat ) + { + // ---------------------------------------------------------------------- + // one bit formats + + case Format::ONE_BIT_MSB_GREY: + return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::ONE_BIT_LSB_GREY: + return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::ONE_BIT_MSB_PAL: + return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, + bitsPerPixel[nScanlineFormat], pDamage ); + + case Format::ONE_BIT_LSB_PAL: + return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, + bitsPerPixel[nScanlineFormat], pDamage ); + + + // ---------------------------------------------------------------------- + // four bit formats + + case Format::FOUR_BIT_MSB_GREY: + return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::FOUR_BIT_LSB_GREY: + return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::FOUR_BIT_MSB_PAL: + return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, + bitsPerPixel[nScanlineFormat], pDamage ); + + case Format::FOUR_BIT_LSB_PAL: + return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, + bitsPerPixel[nScanlineFormat], pDamage ); + + + // ---------------------------------------------------------------------- + // eight bit formats + + case Format::EIGHT_BIT_GREY: + return createRenderer<PixelFormatTraits_GREY8,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::EIGHT_BIT_PAL: + return createRenderer<PixelFormatTraits_PAL8,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, + bitsPerPixel[nScanlineFormat], pDamage ); + + + // ---------------------------------------------------------------------- + // sixteen bit formats + + case Format::SIXTEEN_BIT_LSB_TC_MASK: + return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::SIXTEEN_BIT_MSB_TC_MASK: + return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + + // ---------------------------------------------------------------------- + // twentyfour bit formats + case Format::TWENTYFOUR_BIT_TC_MASK: + return createRenderer<PixelFormatTraits_BGR24,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + + // ---------------------------------------------------------------------- + // thirtytwo bit formats + + case Format::THIRTYTWO_BIT_TC_MASK: + return createRenderer<PixelFormatTraits_RGB32_888,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + + case Format::THIRTYTWO_BIT_TC_MASK_ARGB: + return createRenderer<PixelFormatTraits_BGR32_888,StdMasks>( + aBounds, nScanlineFormat, nScanlineStride, + pFirstScanline, pMem, pPal, pDamage ); + } + + // TODO(F3): other formats not yet implemented + return BitmapDeviceSharedPtr(); +} +} // namespace + + +BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + BitmapDeviceDamageTracker* pDamage ) +{ + return createBitmapDeviceImpl( rSize, + bTopDown, + nScanlineFormat, + boost::shared_array< sal_uInt8 >(), + PaletteMemorySharedVector(), + NULL, + pDamage ); +} + +BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + const PaletteMemorySharedVector& rPalette ) +{ + return createBitmapDeviceImpl( rSize, + bTopDown, + nScanlineFormat, + boost::shared_array< sal_uInt8 >(), + rPalette, + NULL, + NULL ); +} + +BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + const RawMemorySharedArray& rMem, + const PaletteMemorySharedVector& rPalette ) +{ + return createBitmapDeviceImpl( rSize, + bTopDown, + nScanlineFormat, + rMem, + rPalette, + NULL, + NULL ); +} + +BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto, + const basegfx::B2IRange& rSubset ) +{ + return createBitmapDeviceImpl( rProto->getSize(), + rProto->isTopDown(), + rProto->getScanlineFormat(), + rProto->getBuffer(), + rProto->getPalette(), + &rSubset, + rProto->getDamageTracker() ); +} + +BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize, + const BitmapDeviceSharedPtr& rProto ) +{ + return createBitmapDeviceImpl( rSize, + rProto->isTopDown(), + rProto->getScanlineFormat(), + boost::shared_array< sal_uInt8 >(), + rProto->getPalette(), + NULL, + rProto->getDamageTracker() ); +} + +//---------------------------------------------------------------------------------- + +/// Clone our device, with GenericImageAccessor to handle all formats +BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const +{ + return mpImpl->mpGenericRenderer; +} + +} // namespace basebmp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/source/debug.cxx b/basebmp/source/debug.cxx new file mode 100644 index 000000000000..4e7abb0d613b --- /dev/null +++ b/basebmp/source/debug.cxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <osl/diagnose.h> + +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/vector/b2ivector.hxx> + +#include <basebmp/scanlineformats.hxx> +#include <basebmp/color.hxx> +#include <basebmp/bitmapdevice.hxx> +#include <basebmp/debug.hxx> + +#include <iomanip> + +namespace basebmp +{ + namespace + { + static const char* getFormatString( sal_Int32 nScanlineFormat ) + { + switch( nScanlineFormat ) + { + case Format::ONE_BIT_MSB_GREY: + return "ONE_BIT_MSB_GREY"; + case Format::ONE_BIT_LSB_GREY: + return "ONE_BIT_LSB_GREY"; + case Format::ONE_BIT_MSB_PAL: + return "ONE_BIT_MSB_PAL"; + case Format::ONE_BIT_LSB_PAL: + return "ONE_BIT_LSB_PAL"; + case Format::FOUR_BIT_MSB_GREY: + return "FOUR_BIT_MSB_GREY"; + case Format::FOUR_BIT_LSB_GREY: + return "FOUR_BIT_LSB_GREY"; + case Format::FOUR_BIT_MSB_PAL: + return "FOUR_BIT_MSB_PAL"; + case Format::FOUR_BIT_LSB_PAL: + return "FOUR_BIT_LSB_PAL"; + case Format::EIGHT_BIT_PAL: + return "EIGHT_BIT_PAL"; + case Format::EIGHT_BIT_GREY: + return "EIGHT_BIT_GREY"; + case Format::SIXTEEN_BIT_LSB_TC_MASK: + return "SIXTEEN_BIT_LSB_TC_MASK"; + case Format::SIXTEEN_BIT_MSB_TC_MASK: + return "SIXTEEN_BIT_MSB_TC_MASK"; + case Format::TWENTYFOUR_BIT_TC_MASK: + return "TWENTYFOUR_BIT_TC_MASK"; + case Format::THIRTYTWO_BIT_TC_MASK: + return "THIRTYTWO_BIT_TC_MASK"; + default: + return "<unknown>"; + } + } + } + + void debugDump( const BitmapDeviceSharedPtr& rDevice, + std::ostream& rOutputStream ) + { + const basegfx::B2IVector aSize( rDevice->getSize() ); + const bool bTopDown( rDevice->isTopDown() ); + const sal_Int32 nScanlineFormat( rDevice->getScanlineFormat() ); + + rOutputStream + << "/* basebmp::BitmapDevice content dump */" << std::endl + << "/* Width = " << aSize.getX() << " */" << std::endl + << "/* Height = " << aSize.getY() << " */" << std::endl + << "/* TopDown = " << bTopDown << " */" << std::endl + << "/* Format = " << getFormatString(nScanlineFormat) << " */" << std::endl + << "/* (dumped entries are already mapped RGBA color values) */" << std::endl + << std::endl; + + rOutputStream << std::hex; + for( int y=0; y<aSize.getY(); ++y ) + { + for( int x=0; x<aSize.getX(); ++x ) + rOutputStream << std::setw(8) << (sal_uInt32)rDevice->getPixel( basegfx::B2IPoint(x,y) ).toInt32() << " "; + rOutputStream << std::endl; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/source/intconversion.hxx b/basebmp/source/intconversion.hxx new file mode 100644 index 000000000000..407948e80c28 --- /dev/null +++ b/basebmp/source/intconversion.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_INTCONVERSION_HXX +#define INCLUDED_BASEBMP_INTCONVERSION_HXX + +#include <vigra/rgbvalue.hxx> +#include <functional> + +namespace basebmp +{ + // metafunctions to retrieve correct POD from/to basebmp::Color + //------------------------------------------------------------------------ + + /// type-safe conversion from RgbValue to packed int32 + template< class RgbVal > struct UInt32FromRgbValue + { + sal_uInt32 operator()( RgbVal const& c ) const + { + return (c[0] << 16) | (c[1] << 8) | c[2]; + } + }; + + /// type-safe conversion from packed int32 to RgbValue + template< class RgbVal > struct RgbValueFromUInt32 + { + RgbVal operator()( sal_uInt32 c ) const + { + return RgbVal((c >> 16) & 0xFF, + (c >> 8) & 0xFF, + c & 0xFF); + } + }; + + //Current c++0x draft (apparently) has std::identity, but not operator() + template<typename T> struct SGI_identity : public std::unary_function<T,T> + { + T& operator()(T& x) const { return x; } + const T& operator()(const T& x) const { return x; } + }; + + /// Get converter from given data type to sal_uInt32 + template< typename DataType > struct uInt32Converter + { + typedef SGI_identity<DataType> to; + typedef SGI_identity<DataType> from; + }; + template< unsigned int RedIndex, + unsigned int GreenIndex, + unsigned int BlueIndex > struct uInt32Converter< + vigra::RGBValue< sal_uInt8, + RedIndex, + GreenIndex, + BlueIndex > > + { + typedef UInt32FromRgbValue< + vigra::RGBValue< sal_uInt8, + RedIndex, + GreenIndex, + BlueIndex > > + to; + typedef RgbValueFromUInt32< + vigra::RGBValue< sal_uInt8, + RedIndex, + GreenIndex, + BlueIndex > > + from; + }; +} + +#endif /* INCLUDED_BASEBMP_INTCONVERSION_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/source/polypolygonrenderer.cxx b/basebmp/source/polypolygonrenderer.cxx new file mode 100644 index 000000000000..ea561533f2de --- /dev/null +++ b/basebmp/source/polypolygonrenderer.cxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "basebmp/polypolygonrenderer.hxx" + +#include <algorithm> + + +namespace basebmp +{ +namespace detail +{ + sal_uInt32 setupGlobalEdgeTable( VectorOfVectorOfVertices& rGET, + basegfx::B2DPolyPolygon const& rPolyPoly, + sal_Int32 nMinY ) + { + sal_Int32 const nNumScanlines( (sal_Int32)rGET.size() ); + + // add all polygons to GET + for( sal_uInt32 i(0), nCount(rPolyPoly.count()); + i<nCount; + ++i ) + { + // add all vertices to GET + const basegfx::B2DPolygon& rPoly( rPolyPoly.getB2DPolygon(i) ); + for( sal_uInt32 k(0), nVertices(rPoly.count()); + k<nVertices; + ++k ) + { + const basegfx::B2DPoint& rP1( rPoly.getB2DPoint(k) ); + const basegfx::B2DPoint& rP2( rPoly.getB2DPoint( (k + 1) % nVertices ) ); + + const sal_Int32 nVertexYP1( basegfx::fround(rP1.getY()) ); + const sal_Int32 nVertexYP2( basegfx::fround(rP2.getY()) ); + + // insert only vertices which are not strictly + // horizontal. Strictly horizontal vertices don't add + // any information that is not already present - due + // to their adjacent vertices. + if(nVertexYP1 != nVertexYP2) + { + if( nVertexYP2 < nVertexYP1 ) + { + const sal_Int32 nStartScanline(nVertexYP2 - nMinY); + + // edge direction is upwards - add with swapped vertices + if( nStartScanline < nNumScanlines ) + rGET[ nStartScanline ].push_back( Vertex(rP2, rP1, false) ); + } + else + { + const sal_Int32 nStartScanline(nVertexYP1 - nMinY); + + if( nStartScanline < nNumScanlines ) + rGET[ nStartScanline ].push_back( Vertex(rP1, rP2, true) ); + } + } + } + } + + // now sort all scanlines individually, with increasing x + // coordinates + VectorOfVectorOfVertices::iterator aIter( rGET.begin() ); + const VectorOfVectorOfVertices::iterator aEnd( rGET.end() ); + sal_uInt32 nVertexCount(0); + RasterConvertVertexComparator aComp; + while( aIter != aEnd ) + { + std::sort( aIter->begin(), + aIter->end(), + aComp ); + nVertexCount += aIter->size(); + + ++aIter; + } + + return nVertexCount; + } + + void sortAET( VectorOfVertexPtr& rAETSrc, + VectorOfVertexPtr& rAETDest ) + { + static RasterConvertVertexComparator aComp; + + rAETDest.clear(); + + // prune AET from ended edges + VectorOfVertexPtr::iterator iter( rAETSrc.begin() ); + VectorOfVertexPtr::iterator const end( rAETSrc.end() ); + while( iter != end ) + { + if( (*iter)->mnYCounter > 0 ) + rAETDest.push_back( *iter ); + ++iter; + } + + // stable sort is necessary, to avoid segment crossing where + // none was intended. + std::stable_sort( rAETDest.begin(), rAETDest.end(), aComp ); + } + +} // namespace detail +} // namespace basebmp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/basebmp_cppunittester_all.cxx b/basebmp/test/basebmp_cppunittester_all.cxx new file mode 100644 index 000000000000..53a8113cfda6 --- /dev/null +++ b/basebmp/test/basebmp_cppunittester_all.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org 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 Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +************************************************************************/ + +#include "sal/config.h" + +#include <cstdlib> +#include <iostream> +#include <limits> +#include <string> +#include "protectorfactory.hxx" +#include "osl/module.h" +#include "osl/module.hxx" +#include "osl/thread.h" +#include "rtl/process.h" +#include "rtl/string.h" +#include "rtl/string.hxx" +#include "rtl/textcvt.h" +#include "rtl/ustring.hxx" +#include "sal/main.h" +#include "sal/types.h" + +#include "cppunit/CompilerOutputter.h" +#include "cppunit/TestResult.h" +#include "cppunit/TestResultCollector.h" +#include "cppunit/TestRunner.h" +#include "cppunit/plugin/TestPlugIn.h" +#include "cppunit/plugin/PlugInParameters.h" +#include "cppunit/extensions/TestFactoryRegistry.h" +#include "cppunit/portability/Stream.h" + +#include "boost/noncopyable.hpp" + +namespace { + +void usageFailure() { + std::cerr + << ("Usage: cppunittester (--protector <shared-library-path>" + " <function-symbol>)* <shared-library-path>") + << std::endl; + std::exit(EXIT_FAILURE); +} + +rtl::OUString getArgument(sal_Int32 index) { + rtl::OUString arg; + rtl_getAppCommandArg(index, &arg.pData); + return arg; +} + +std::string convertLazy(rtl::OUString const & s16) { + rtl::OString s8(rtl::OUStringToOString(s16, osl_getThreadTextEncoding())); + return std::string( + s8.getStr(), + ((static_cast< sal_uInt32 >(s8.getLength()) + > (std::numeric_limits< std::string::size_type >::max)()) + ? (std::numeric_limits< std::string::size_type >::max)() + : static_cast< std::string::size_type >(s8.getLength()))); +} + +//Allow the whole uniting testing framework to be run inside a "Protector" +//which knows about uno exceptions, so it can print the content of the +//exception before falling over and dying +class CPPUNIT_API ProtectedFixtureFunctor : public CppUnit::Functor, private boost::noncopyable +{ +private: + const std::string &args; + CppUnit::TestResult &result; +public: + ProtectedFixtureFunctor(const std::string &args_, CppUnit::TestResult &result_) + : args(args_) + , result(result_) + { + } + bool run() const + { + CppUnit::TestRunner runner; + runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); + CppUnit::TestResultCollector collector; + result.addListener(&collector); + runner.run(result); + CppUnit::CompilerOutputter(&collector, CppUnit::stdCErr()).write(); + return collector.wasSuccessful(); + } + virtual bool operator()() const + { + return run(); + } +}; +} + +extern "C" CppUnitTestPlugIn + *cppunitTest_basebmp(void); + +SAL_IMPLEMENT_MAIN() { + TestPlugInSignature plugs[] = { + cppunitTest_basebmp, + NULL + }; + CppUnit::TestResult result; + std::string args; + bool ok = false; + for (TestPlugInSignature *plug = plugs; *plug != NULL; plug++) { + CppUnitTestPlugIn *iface; + iface = (*plug)(); + iface->initialize(&CppUnit::TestFactoryRegistry::getRegistry(), CppUnit::PlugInParameters()); + } + ProtectedFixtureFunctor tests(args, result); + ok = tests.run(); + + return ok ? EXIT_SUCCESS : EXIT_FAILURE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/basictest.cxx b/basebmp/test/basictest.cxx new file mode 100644 index 000000000000..a24852992f53 --- /dev/null +++ b/basebmp/test/basictest.cxx @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifdef IOS +#define CPPUNIT_PLUGIN_EXPORTED_NAME cppunitTest_basebmp +#endif + +// autogenerated file with codegen.pl + +#include <sal/cppunit.h> +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class BasicTest : public CppUnit::TestFixture +{ +public: + void colorTest() + { + Color aTestColor; + + aTestColor = Color(0xDEADBEEF); + CPPUNIT_ASSERT_MESSAGE("unary constructor", + aTestColor.toInt32() == 0xDEADBEEF ); + + aTestColor = Color( 0x10, 0x20, 0xFF ); + CPPUNIT_ASSERT_MESSAGE("ternary constructor", + aTestColor.toInt32() == 0x001020FF ); + + aTestColor.setRed( 0x0F ); + CPPUNIT_ASSERT_MESSAGE("setRed()", + aTestColor.toInt32() == 0x00F20FF ); + + aTestColor.setGreen( 0x0F ); + CPPUNIT_ASSERT_MESSAGE("setGreen()", + aTestColor.toInt32() == 0x00F0FFF ); + + aTestColor.setBlue( 0x10 ); + CPPUNIT_ASSERT_MESSAGE("setBlue()", + aTestColor.toInt32() == 0x00F0F10 ); + + aTestColor.setGrey( 0x13 ); + CPPUNIT_ASSERT_MESSAGE("setGrey()", + aTestColor.toInt32() == 0x00131313 ); + + aTestColor = Color( 0x10, 0x20, 0xFF ); + CPPUNIT_ASSERT_MESSAGE("getRed()", + aTestColor.getRed() == 0x10 ); + CPPUNIT_ASSERT_MESSAGE("getGreen()", + aTestColor.getGreen() == 0x20 ); + CPPUNIT_ASSERT_MESSAGE("getBlue()", + aTestColor.getBlue() == 0xFF ); + + } + + void testConstruction() + { + const basegfx::B2ISize aSize(101,101); + basegfx::B2ISize aSize2(aSize); + BitmapDeviceSharedPtr pDevice( createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL )); + CPPUNIT_ASSERT_MESSAGE("right size", + pDevice->getSize() == aSize2 ); + CPPUNIT_ASSERT_MESSAGE("Top down format", + pDevice->isTopDown() == true ); + CPPUNIT_ASSERT_MESSAGE("Scanline format", + pDevice->getScanlineFormat() == Format::ONE_BIT_MSB_PAL ); + CPPUNIT_ASSERT_MESSAGE("Scanline len", + pDevice->getScanlineStride() == (aSize2.getY() + 7)/8 ); + CPPUNIT_ASSERT_MESSAGE("Palette existence", + pDevice->getPalette() ); + CPPUNIT_ASSERT_MESSAGE("Palette entry 0 is black", + (*pDevice->getPalette())[0] == Color(0) ); + CPPUNIT_ASSERT_MESSAGE("Palette entry 1 is white", + (*pDevice->getPalette())[1] == Color(0xFFFFFFFF) ); + } + + void testPixelFuncs() + { + // 1bpp + const basegfx::B2ISize aSize(64,64); + BitmapDeviceSharedPtr pDevice( createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL )); + + const basegfx::B2IPoint aPt(3,3); + const Color aCol(0xFFFFFFFF); + pDevice->setPixel( aPt, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #1", + pDevice->getPixel(aPt) == aCol); + + const basegfx::B2IPoint aPt2(0,0); + const Color aCol2(0xFFFFFFFF); + pDevice->setPixel( aPt2, aCol2, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #2", + pDevice->getPixel(aPt2) == aCol2); + + const basegfx::B2IPoint aPt3(aSize.getX()-1,aSize.getY()-1); + const Color aCol3(0x00000000); + pDevice->setPixel( aPt3, aCol3, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #3", + pDevice->getPixel(aPt3) == aCol3); + + pDevice->setPixel( aPt3, aCol2, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #3.5", + pDevice->getPixel(aPt3) == aCol2); + + const basegfx::B2IPoint aPt4(-100000,-100000); + pDevice->setPixel( aPt4, aCol3, DrawMode_PAINT ); + const basegfx::B2IPoint aPt5(100000,100000); + pDevice->setPixel( aPt5, aCol3, DrawMode_PAINT ); + + sal_Int32 nPixel(countPixel(pDevice, aCol2)); + const basegfx::B2IPoint aPt6(aSize.getX(),aSize.getY()); + pDevice->setPixel( aPt6, aCol2, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("setPixel clipping", + countPixel(pDevice, aCol2) == nPixel); + + CPPUNIT_ASSERT_MESSAGE("raw pixel value #1", + pDevice->getBuffer()[0] == 0x80); + + // 1bit LSB + { + pDevice = createBitmapDevice( aSize, + true, + Format::ONE_BIT_LSB_PAL ); + + pDevice->setPixel( aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #4", + pDevice->getPixel(aPt2) == aCol); + + const basegfx::B2IPoint aPt222(1,1); + pDevice->setPixel( aPt222, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #5", + pDevice->getPixel(aPt222) == aCol); + + pDevice->setPixel( aPt3, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #6", + pDevice->getPixel(aPt3) == aCol); + + CPPUNIT_ASSERT_MESSAGE("raw pixel value #2", + pDevice->getBuffer()[0] == 0x01); + CPPUNIT_ASSERT_MESSAGE("raw pixel value #3", + pDevice->getBuffer()[8] == 0x02); + } + + // 8bit alpha + { + pDevice = createBitmapDevice( aSize, + true, + Format::EIGHT_BIT_GREY ); + + const Color aCol4(0x010101); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #4", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x0F0F0F); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #5", + pDevice->getPixel(aPt2) == aCol5); + + const Color aCol6(0xFFFFFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #6", + pDevice->getPixel(aPt3) == aCol6); + } + + // 16bpp + { + pDevice = createBitmapDevice( aSize, + true, + Format::SIXTEEN_BIT_LSB_TC_MASK ); + const Color aCol7(0); + pDevice->clear( aCol7 ); + + const Color aCol4(0x00101010); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #7", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x00F0F0F0); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #8", + pDevice->getPixel(aPt2) != aCol7); + + const Color aCol6(0x00FFFFFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #9", + pDevice->getPixel(aPt3) == aCol6); + } + + // 24bpp + { + pDevice = createBitmapDevice( aSize, + true, + Format::TWENTYFOUR_BIT_TC_MASK ); + + const Color aCol4(0x01010101); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #10", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x0F3F2F1F); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #11", + pDevice->getPixel(aPt2) == aCol5); + + const Color aCol6(0xFFFFFFFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #12", + pDevice->getPixel(aPt3) == aCol6); + + CPPUNIT_ASSERT_MESSAGE("raw pixel value #4", + pDevice->getBuffer()[2] == 0x3F + && pDevice->getBuffer()[1] == 0x2F + && pDevice->getBuffer()[0] == 0x1F); + } + + // 32bpp + { + pDevice = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + const Color aCol4(0x01010101); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #13", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x0F0F0F0F); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #14", + pDevice->getPixel(aPt2) == aCol5); + + const Color aCol6(0xFFFFFFFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #15", + pDevice->getPixel(aPt3) == aCol6); + } + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(BasicTest); + CPPUNIT_TEST(colorTest); + CPPUNIT_TEST(testConstruction); + CPPUNIT_TEST(testPixelFuncs); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BasicTest); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/bmpdemo.cxx b/basebmp/test/bmpdemo.cxx new file mode 100644 index 000000000000..effce214bb2f --- /dev/null +++ b/basebmp/test/bmpdemo.cxx @@ -0,0 +1,1252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _USE_MATH_DEFINES +#define _USE_MATH_DEFINES // needed by Visual C++ for math constants +#endif +#include <math.h> + +#include <comphelper/processfactory.hxx> +#include <comphelper/regpathhelper.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> + +#include <ucbhelper/contentbroker.hxx> +#include <ucbhelper/configurationkeys.hxx> + +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/unowrap.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/bmpacc.hxx> + +#include <basegfx/polygon/b2dlinegeometry.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include <basebmp/debug.hxx> + +#include <rtl/bootstrap.hxx> + +#include <vigra/metaprogramming.hxx> +#include <vigra/static_assert.hxx> +#include <vigra/basicimageview.hxx> + +#include <boost/static_assert.hpp> +#include <algorithm> + +using namespace ::com::sun::star; + + +namespace +{ + +/// template meta function: add const qualifier, if given 2nd type has it +template<typename A, typename B> struct clone_const +{ + typedef B type; +}; +template<typename A, typename B> struct clone_const<const A,B> +{ + typedef const B type; +}; + +template< class DestIterator, class DestAccessor > class Renderer : + public basegfx::B2DPolyPolygonRasterConverter +{ +private: + typename DestIterator::value_type fillColor_; + typename DestIterator::value_type clearColor_; + DestIterator begin_; + DestAccessor accessor_; + +public: + Renderer(const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + typename DestIterator::value_type clearColor, + DestIterator begin, + DestIterator end, + DestAccessor accessor ) : + B2DPolyPolygonRasterConverter(rPolyPolyRaster, + basegfx::B2DRange(0,0, + end.x - end.x, + begin.y - begin.y )), + fillColor_( fillColor ), + clearColor_( clearColor ), + begin_( begin ), + accessor_( accessor ) + { + } + + virtual void span(const double& rfXLeft, + const double& rfXRight, + sal_Int32 nY, + bool bOn ) + { + DestIterator currIter( begin_ + vigra::Diff2D(0,nY) ); + typename DestIterator::row_iterator rowIter( currIter.rowIterator() + + basegfx::fround(rfXLeft) ); + typename DestIterator::row_iterator rowEnd( currIter.rowIterator() + + basegfx::fround(rfXRight) ); + if( bOn ) + while( rowIter != rowEnd ) + { + accessor_.set(fillColor_, rowIter); + ++rowIter; + } + else + while( rowIter != rowEnd ) + { + accessor_.set(accessor_(rowIter)*clearColor_, rowIter); + ++rowIter; + } + } +}; + +template< class DestIterator, class DestAccessor > + std::auto_ptr< Renderer< DestIterator, DestAccessor > > makeRenderer( + const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + typename DestIterator::value_type clearColor, + vigra::triple<DestIterator, DestIterator, DestAccessor> dest ) +{ + return std::auto_ptr< Renderer< DestIterator, DestAccessor > >( + new Renderer< DestIterator, DestAccessor >(rPolyPolyRaster, + fillColor, + clearColor, + dest.first, + dest.second, + dest.third)); +} + + +// changed semantics re. DirectionSelector<StridedArrayTag>: stride +// now counts in <em>raw</em> bytes! +template< typename T > class StridedArrayIterator +{ +public: + typedef typename clone_const<T, unsigned char>::type internal_type; + + StridedArrayIterator(int stride, T* ptr = 0) : + stride_(stride), + current_(reinterpret_cast<internal_type*>(ptr)) + {} + + /// Copy from other StridedArrayIterator, plus given offset + StridedArrayIterator( StridedArrayIterator const& rSrc, + int offset ) : + stride_(rSrc.stride_), + current_(reinterpret_cast<internal_type*>( + reinterpret_cast<T*>(rSrc.current_)+offset)) + {} + + void operator++() {current_ += stride_; } + void operator++(int) {current_ += stride_; } + void operator--() {current_ -= stride_; } + void operator--(int) {current_ -= stride_; } + void operator+=(int dy) {current_ += dy*stride_; } + void operator-=(int dy) {current_ -= dy*stride_; } + + bool operator==(StridedArrayIterator const & rhs) const + { return (current_ == rhs.current_); } + + bool operator!=(StridedArrayIterator const & rhs) const + { return (current_ != rhs.current_); } + + bool operator<(StridedArrayIterator const & rhs) const + { return (current_ < rhs.current_); } + + bool operator<=(StridedArrayIterator const & rhs) const + { return (current_ <= rhs.current_); } + + bool operator>(StridedArrayIterator const & rhs) const + { return (current_ > rhs.current_); } + + bool operator>=(StridedArrayIterator const & rhs) const + { return (current_ >= rhs.current_); } + + int operator-(StridedArrayIterator const & rhs) const + { return (current_ - rhs.current_) / stride_; } + + T* operator()() const + { return reinterpret_cast<T*>(current_); } + + T* operator()(int d) const + { return reinterpret_cast<T*>(current_ + d*stride_); } + + int stride_; + internal_type* current_; +}; + +/// template meta function: remove const qualifier from plain type +template <typename T> struct remove_const +{ + typedef T type; +}; +template <typename T> struct remove_const<const T> +{ + typedef T type; +}; + +/// returns true, if given number is strictly less than 0 +template< typename T > inline bool is_negative( T x ) +{ + return x < 0; +} + +/// Overload for ints (branch-free) +inline bool is_negative( int x ) +{ + // force logic shift (result for signed shift right is undefined) + return static_cast<unsigned int>(x) >> (sizeof(int)*8-1); +} + +/// Get bitmask for data at given intra-word position, for given bit depth +template< typename data_type, int bits_per_pixel, bool MsbFirst, typename difference_type > inline data_type get_mask( difference_type d ) +{ + BOOST_STATIC_ASSERT(bits_per_pixel > 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 % bits_per_pixel == 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 / bits_per_pixel > 1); + BOOST_STATIC_ASSERT(vigra::TypeTraits<data_type>::isPOD::asBool); + + const unsigned int nIntraWordPositions( sizeof(data_type)*8 / bits_per_pixel ); + + // create bits_per_pixel 1s shift to intra-word position + return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ? + (nIntraWordPositions-1 - (d % nIntraWordPositions)) : + (d % nIntraWordPositions))); +} + +template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder ) +{ + return bits_per_pixel*(MsbFirst ? + (num_intraword_positions - 1 - remainder) : + remainder); +} + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelColumnIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + MoveY y; + mask_type mask_; + difference_type shift_; + + void inc() + { + ++y; + } + + void dec() + { + --y; + } + + bool equal( PackedPixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PackedPixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PackedPixelColumnIterator() : + y(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) ) + {} + + PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) : + y(base), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) ) + {} + + PackedPixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PackedPixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PackedPixelColumnIterator operator+( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res += d; + return res; + } + + PackedPixelColumnIterator operator-( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res -= d; + return res; + } + + PackedPixelColumnIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelColumnIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelColumnIterator operator++(int) + { + PackedPixelColumnIterator res(*this); + res.inc(); + return res; + } + + PackedPixelColumnIterator operator--(int) + { + PackedPixelColumnIterator res(*this); + res.dec(); + return res; + } + + bool operator==(PackedPixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y() & mask_) >> shift_; + } + + value_type get(difference_type d) const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y(d) & mask_) >> shift_; + } + + void set( value_type v ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y() = (*y() & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y(d) = (*y(d) & ~mask_) | pixel_value; + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelRowIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + pointer data_; + mask_type mask_; + difference_type remainder_; + + void update_mask() + { + mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_); + } + + void inc() + { + const difference_type newValue( remainder_ + 1 ); + const difference_type data_offset( newValue / num_intraword_positions ); + + data_ += data_offset; + remainder_ = newValue % num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel : + mask_ << bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask << bits_per_pixel*(num_intraword_positions-1) : + bit_mask); + } + + void dec() + { + const difference_type newValue( remainder_ - 1 ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + const difference_type data_offset( newValue / num_intraword_positions - isNegative ); + data_ += data_offset; + remainder_ = newRemainder + isNegative*num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + mask_ << bits_per_pixel : + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask : + bit_mask << bits_per_pixel*(num_intraword_positions-1)); + } + + bool equal( PackedPixelRowIterator const & rhs ) const + { + return rhs.data_ == data_ && rhs.remainder_ == remainder_; + } + + bool less( PackedPixelRowIterator const & rhs ) const + { + return data_ == rhs.data_ ? + (remainder_ < rhs.remainder_) : + (data_ < rhs.data_); + } + +public: + PackedPixelRowIterator() : + data_(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + explicit PackedPixelRowIterator( pointer base ) : + data_(base), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + PackedPixelRowIterator& operator+=( difference_type d ) + { + const difference_type newValue( remainder_ + d ); + + data_ += newValue / num_intraword_positions; + remainder_ = newValue % num_intraword_positions; + update_mask(); + + return *this; + } + + PackedPixelRowIterator& operator-=( difference_type d ) + { + const difference_type newValue( remainder_ - d ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + data_ += newValue / num_intraword_positions - isNegative; + remainder_ = newRemainder + isNegative*(num_intraword_positions - 2*newRemainder); + update_mask(); + + return *this; + } + + PackedPixelRowIterator operator+( difference_type d ) + { + PackedPixelRowIterator res(*this); + res += d; + return res; + } + + PackedPixelRowIterator operator-( difference_type d ) + { + PackedPixelRowIterator res(*this); + res -= d; + return res; + } + + PackedPixelRowIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelRowIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelRowIterator operator++(int) + { + PackedPixelRowIterator res(*this); + res.inc(); + return res; + } + + PackedPixelRowIterator operator--(int) + { + PackedPixelRowIterator res(*this); + res.dec(); + return res; + } + + bool operator==(PackedPixelRowIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelRowIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelRowIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelRowIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelRowIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelRowIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelRowIterator const & rhs) const + { + return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_); + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*data_ & mask_) >> + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_); + } + + value_type get(difference_type d) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + return tmp.get(); + } + + void set( value_type v ) const + { + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_)) + & mask_ ); + *data_ = (*data_ & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + tmp.set(v); + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef PackedPixelRowIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> row_iterator; + typedef PackedPixelColumnIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> column_iterator; + + typedef data_type* pointer; + typedef int MoveX; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + pointer current() const + { + return y() + (x / num_intraword_positions); + } + + pointer current(int dx, int dy) const + { + return y(dy) + ((x+dx)/num_intraword_positions); + } + + bool equal(PackedPixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + +public: + PackedPixelIterator() : + x(0), + y(0) + {} + + PackedPixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PackedPixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PackedPixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PackedPixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PackedPixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PackedPixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PackedPixelIterator operator+(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret += s; + return ret; + } + + PackedPixelIterator operator-(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(current()); + } + + column_iterator columnIterator() const + { + return column_iterator(MoveY(y, + x / num_intraword_positions), + x % num_intraword_positions); + } + + value_type get() const + { + const int remainder( x() % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return (static_cast<unsigned int>(*current() & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> (MsbFirst ? + (num_intraword_positions - remainder) : + remainder)); + } + + value_type get(difference_type const & d) const + { + const int remainder( x(d.x) % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return (static_cast<unsigned int>(*current(d.x,d.y) & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + void set( value_type v ) const + { + const int remainder( x() % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(); + *p = (*p & ~mask) | pixel_value; + } + + void set( value_type v, difference_type const & d ) const + { + const int remainder( x(d.x) % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(d.x,d.y); + *p = (*p & ~mask) | pixel_value; + } +}; + + +/** Access (possibly packed-pixel) data via palette indirection + */ +template< typename Valuetype, typename Datatype > class PaletteImageAccessor +{ + public: + typedef Valuetype value_type; + typedef Datatype data_type; + typedef typename remove_const<data_type>::type count_type; + + +private: + const BitmapColor* palette; + count_type num_entries; + + double norm( BitmapColor const& rLHS, + BitmapColor const& rRHS ) const + { + // convert RGBValue's linear space to a normed linear space + return sqrt( + vigra::sq(rLHS.GetRed()-rRHS.GetRed()) + + vigra::sq(rLHS.GetGreen()-rRHS.GetGreen()) + + vigra::sq(rLHS.GetBlue()-rRHS.GetBlue()) ); + } + + data_type find_best_match(value_type const& v) const + { + // TODO(F3): not generic!!! + const BitmapColor aTmpCol(v.red(), + v.green(), + v.blue()); + + // TODO(P3): use table-based/octree approach here! + const BitmapColor* best_entry; + const BitmapColor* palette_end( palette+num_entries ); + if( (best_entry=std::find( palette, palette_end, aTmpCol)) != palette_end ) + return best_entry-palette; + + // TODO(F3): HACK. Need palette traits, and an error function + // here. We blatantly assume value_type is a normed linear + // space. + const BitmapColor* curr_entry( palette ); + best_entry = curr_entry; + while( curr_entry != palette_end ) + { + if( norm(*curr_entry,*best_entry) > norm(*curr_entry,aTmpCol) ) + best_entry = curr_entry; + + ++curr_entry; + } + + return best_entry-palette; + } + + value_type toCol( BitmapColor const& rCol ) const + { + return value_type(rCol.GetRed(),rCol.GetGreen(),rCol.GetBlue()); + } + +public: + PaletteImageAccessor() : + palette(0), + num_entries(0) + {} + + PaletteImageAccessor( const BitmapColor* pPalette, + data_type entries ) : + palette(pPalette), + num_entries(entries) + {} + + template< class Iterator > + value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); } + value_type operator()(data_type const* i) const { return toCol(palette[*i]); } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return toCol(palette[i.get(diff)]); + } + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value) )); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value)), + diff ); + } +}; + +} + + +class TestApp : public Application +{ +public: + virtual void Main(); + virtual USHORT Exception( USHORT nError ); +}; + +class TestWindow : public Dialog +{ + public: + TestWindow() : Dialog( (Window *) NULL ) + { + SetText( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VIGRA test" )) ); + SetSizePixel( Size( 1024, 1024 ) ); + EnablePaint( true ); + Show(); + } + virtual ~TestWindow() {} + virtual void MouseButtonUp( const MouseEvent& /*rMEvt*/ ) + { + //TODO: do something cool + EndDialog(); + } + virtual void Paint( const Rectangle& rRect ); +}; + + +static basegfx::B2IPoint project( const basegfx::B2IPoint& rPoint ) +{ + const double angle_x = M_PI / 6.0; + const double angle_z = M_PI / 6.0; + + // transform planar coordinates to 3d + double x = rPoint.getX(); + double y = rPoint.getY(); + //double z = 0; + + // rotate around X axis + double x1 = x; + double y1 = y * cos( angle_x ); + double z1 = y * sin( angle_x ); + + // rotate around Z axis + double x2 = x1 * cos( angle_z ) + y1 * sin( angle_z ); + //double y2 = y1 * cos( angle_z ) - x1 * sin( angle_z ); + double z2 = z1; + + //return basegfx::B2IPoint( (sal_Int32)3*x2, (sal_Int32)3*z2 ); + return basegfx::B2IPoint( (sal_Int32)(6*x2), (sal_Int32)(6*z2) ); +} + +static basebmp::Color approachColor( const basebmp::Color& rFrom, const basebmp::Color& rTo ) +{ + basebmp::Color aColor; + UINT8 nDiff; + // approach red + if( rFrom.getRed() < rTo.getRed() ) + { + nDiff = rTo.getRed() - rFrom.getRed(); + aColor.setRed( rFrom.getRed() + ( nDiff < 10 ? nDiff : 10 ) ); + } + else if( rFrom.getRed() > rTo.getRed() ) + { + nDiff = rFrom.getRed() - rTo.getRed(); + aColor.setRed( rFrom.getRed() - ( nDiff < 10 ? nDiff : 10 ) ); + } + else + aColor.setRed( rFrom.getRed() ); + + // approach Green + if( rFrom.getGreen() < rTo.getGreen() ) + { + nDiff = rTo.getGreen() - rFrom.getGreen(); + aColor.setGreen( rFrom.getGreen() + ( nDiff < 10 ? nDiff : 10 ) ); + } + else if( rFrom.getGreen() > rTo.getGreen() ) + { + nDiff = rFrom.getGreen() - rTo.getGreen(); + aColor.setGreen( rFrom.getGreen() - ( nDiff < 10 ? nDiff : 10 ) ); + } + else + aColor.setGreen( rFrom.getGreen() ); + + // approach blue + if( rFrom.getBlue() < rTo.getBlue() ) + { + nDiff = rTo.getBlue() - rFrom.getBlue(); + aColor.setBlue( rFrom.getBlue() + ( nDiff < 10 ? nDiff : 10 ) ); + } + else if( rFrom.getBlue() > rTo.getBlue() ) + { + nDiff = rFrom.getBlue() - rTo.getBlue(); + aColor.setBlue( rFrom.getBlue() - ( nDiff < 10 ? nDiff : 10 ) ); + } + else + aColor.setBlue( rFrom.getBlue() ); + + return aColor; +} + +#define DELTA 5.0 + + + +void TestWindow::Paint( const Rectangle& /*rRect*/ ) +{ + basegfx::B2ISize aTestSize(1000,1000); + basebmp::BitmapDeviceSharedPtr pDevice( basebmp::createBitmapDevice( aTestSize, + false, + basebmp::Format::THIRTYTWO_BIT_TC_MASK )); + + { + ::rtl::OUString aSvg; + basegfx::B2DPolyPolygon aPoly; + + basegfx::tools::importFromSvgD( aPoly, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "m0 0 h7 v7 h-7 z" )) ); + basegfx::tools::importFromSvgD( aPoly, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "m2 2 h3 v3 h-3 z" )) ); + + pDevice->fillPolyPolygon( + aPoly, + basebmp::Color(0xFFFFFFFF), + basebmp::DrawMode_PAINT ); + } + + { + basebmp::BitmapDeviceSharedPtr pMask( basebmp::createBitmapDevice( aTestSize, + false, + basebmp::Format::ONE_BIT_MSB_GREY )); + + const basegfx::B2IPoint aPt111(10,10); + const basegfx::B2IPoint aPt222(0,10); + const basebmp::Color aCol333(0xFFFFFFFF); + pMask->drawLine( aPt111, aPt222, aCol333, basebmp::DrawMode_PAINT ); + + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0 h5 l5 5 v5 h-5 l-5-5 z" )); + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + pMask->clear(basebmp::Color(0xFFFFFFFF)); + pMask->drawPolygon( + aPoly.getB2DPolygon(0), + basebmp::Color(0), + basebmp::DrawMode_PAINT ); + + basebmp::BitmapDeviceSharedPtr pSubsetDevice = + basebmp::subsetBitmapDevice( pDevice, + basegfx::B2IRange(3,3,7,7) ); + + const basegfx::B2IPoint aPt1(0,0); + const basegfx::B2IPoint aPt2(1,9); + const basebmp::Color aCol(0xFFFFFFFF); + pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT, pMask ); + } + + { + const basebmp::Color aCol(0xFFFFFFFF); + basegfx::B2DPolygon aRect = basegfx::tools::createPolygonFromRect( + basegfx::B2DRange( 0,0,1001,1001 )); + pDevice->drawPolygon( aRect, aCol, basebmp::DrawMode_PAINT ); + + const basegfx::B2IPoint aPt1(0,0); + const basegfx::B2IPoint aPt2(0,800); + pDevice->drawLine( aPt1, aPt2, aCol, basebmp::DrawMode_PAINT ); + + const basegfx::B2IPoint aPt3(0,1001); + pDevice->drawLine( aPt1, aPt3, aCol, basebmp::DrawMode_PAINT ); + } + + { + pDevice->clear(basebmp::Color(0)); + + basegfx::B2IPoint aCenter( aTestSize.getX()/2, + aTestSize.getY()/2 ); + //basegfx::B2IPoint aP1( aTestSize.getX()/48, 0), aP2( aTestSize.getX()/40, 0 ), aPoint; + //basegfx::B2IPoint aP1( aTestSize.getX()/7, 0), aP2( aTestSize.getX()/6, 0 ), aPoint; + //basegfx::B2IPoint aP1( aTestSize.getX()/5, 0), aP2( aTestSize.getX()/4, 0 ), aPoint; + basegfx::B2IPoint aP1( aTestSize.getX()/12, 0), aP2( aTestSize.getX()/11, 0 ), aPoint; + + double sind = sin( DELTA*M_PI/180.0 ); + double cosd = cos( DELTA*M_PI/180.0 ); + double factor = 1 + (DELTA/1000.0); + int n=0; + basebmp::Color aLineColor( 0, 0, 0 ); + basebmp::Color aApproachColor( 0, 0, 200 ); + while ( aP2.getX() < aCenter.getX() && n++ < 680 ) + { + aLineColor = approachColor( aLineColor, aApproachColor ); + + // switch aproach color + if( aApproachColor == aLineColor ) + { + if( aApproachColor.getRed() ) + aApproachColor = basebmp::Color( 0, 0, 200 ); + else if( aApproachColor.getGreen() ) + aApproachColor = basebmp::Color( 200, 0, 0 ); + else + aApproachColor = basebmp::Color( 0, 200, 0 ); + } + + basegfx::B2DPolygon aPoly; + aPoly.append( basegfx::B2DPoint(project( aP1 ) + aCenter) ); + aPoly.append( basegfx::B2DPoint(project( aP2 ) + aCenter) ); + pDevice->fillPolyPolygon( + basegfx::tools::createAreaGeometry( + aPoly, +// std::max(1,n/30), +// std::max(1,n/60), + std::max(1,n/30), + basegfx::B2DLINEJOIN_NONE), + aLineColor, + basebmp::DrawMode_PAINT); + + aPoint.setX( (int)((((double)aP1.getX())*cosd - ((double)aP1.getY())*sind)*factor) ); + aPoint.setY( (int)((((double)aP1.getY())*cosd + ((double)aP1.getX())*sind)*factor) ); + aP1 = aPoint; + aPoint.setX( (int)((((double)aP2.getX())*cosd - ((double)aP2.getY())*sind)*factor) ); + aPoint.setY( (int)((((double)aP2.getY())*cosd + ((double)aP2.getX())*sind)*factor) ); + aP2 = aPoint; + } + } + + Bitmap aBitmap( Size(aTestSize.getX(), + aTestSize.getY()), 24 ); + + // Fill bitmap with generated content + { + Bitmap::ScopedWriteAccess pWriteAccess( aBitmap ); + for( int y=0; y<aTestSize.getY(); ++y ) + for( int x=0; x<aTestSize.getX(); ++x ) + pWriteAccess->SetPixel(y,x, + Color(pDevice->getPixelData(basegfx::B2IPoint(x,y))) ); + } + + DrawBitmap( Point(), aBitmap ); +} + +USHORT TestApp::Exception( USHORT nError ) +{ + switch( nError & EXC_MAJORTYPE ) + { + case EXC_RSCNOTLOADED: + Abort( String::CreateFromAscii( "Error: could not load language resources.\nPlease check your installation.\n" ) ); + break; + } + return 0; +} + +void TestApp::Main() +{ + //------------------------------------------------- + // create the global service-manager + //------------------------------------------------- + uno::Reference< lang::XMultiServiceFactory > xFactory; + try + { + uno::Reference< uno::XComponentContext > xCtx = ::cppu::defaultBootstrap_InitialComponentContext(); + xFactory = uno::Reference< lang::XMultiServiceFactory >( xCtx->getServiceManager(), + uno::UNO_QUERY ); + if( xFactory.is() ) + ::comphelper::setProcessServiceFactory( xFactory ); + } + catch( uno::Exception& ) + { + } + + if( !xFactory.is() ) + { + OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting.\n" ); + exit( 1 ); + } + + // Create UCB. + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[ 0 ] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( UCB_CONFIGURATION_KEY1_LOCAL )); + aArgs[ 1 ] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( UCB_CONFIGURATION_KEY2_OFFICE )); + ::ucbhelper::ContentBroker::initialize( xFactory, aArgs ); + + TestWindow pWindow; + pWindow.Execute(); + + // clean up UCB + ::ucbhelper::ContentBroker::deinitialize(); +} + +TestApp aDemoApp; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/bmpmasktest.cxx b/basebmp/test/bmpmasktest.cxx new file mode 100644 index 000000000000..5ba477484903 --- /dev/null +++ b/basebmp/test/bmpmasktest.cxx @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class BmpMaskTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpMaskBmp1bpp; + BitmapDeviceSharedPtr mpBmp1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + BitmapDeviceSharedPtr mpBmp32bpp; + + void implTestBmpBasics(const BitmapDeviceSharedPtr& rDevice, + const BitmapDeviceSharedPtr& rBmp) + { + rDevice->clear(Color(0)); + const Color aCol(0xFFFFFFFF); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IRange aDestAll(0,0,10,10); + + rDevice->drawMaskedBitmap( + rBmp, + mpMaskBmp1bpp, + aSourceRect, + aDestAll, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 30", + countPixel( rDevice, aCol ) == 30); + } + + void implTestBmpScaledClip(const BitmapDeviceSharedPtr& rDevice, + const BitmapDeviceSharedPtr& rBmp) + { + rDevice->clear(Color(0)); + const Color aCol(0xFFFFFFFF); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IRange aDestLeftTop(0,0,6,6); + + rDevice->drawMaskedBitmap( + rBmp, + mpMaskBmp1bpp, + aSourceRect, + aDestLeftTop, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 12", + countPixel( rDevice, aCol ) == 12); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(10,10); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + mpMaskBmp1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_GREY ); + + mpBmp1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpBmp32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0h5v10h5v-5h-10z" )); + + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + const Color aColWhite(0xFFFFFFFF); + const Color aColBlack(0); + mpBmp1bpp->fillPolyPolygon( + aPoly, + aColWhite, + DrawMode_PAINT ); + mpBmp32bpp->fillPolyPolygon( + aPoly, + aColWhite, + DrawMode_PAINT ); + + aSvg = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "m 0 0 h6 v10 h-6z" )); + + aPoly.clear(); + basegfx::tools::importFromSvgD( aPoly, aSvg ); + mpMaskBmp1bpp->clear(aColWhite); + mpMaskBmp1bpp->fillPolyPolygon( + aPoly, + aColBlack, + DrawMode_PAINT ); + } + + void testBmpBasics() + { + implTestBmpBasics( mpDevice1bpp, mpBmp1bpp ); + implTestBmpBasics( mpDevice32bpp, mpBmp32bpp ); + } + + void testBmpClip() + { + implTestBmpScaledClip( mpDevice1bpp, mpBmp1bpp ); + implTestBmpScaledClip( mpDevice32bpp, mpBmp32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(BmpMaskTest); + CPPUNIT_TEST(testBmpBasics); + CPPUNIT_TEST(testBmpClip); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BmpMaskTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/bmptest.cxx b/basebmp/test/bmptest.cxx new file mode 100644 index 000000000000..7b3a2cbcb18f --- /dev/null +++ b/basebmp/test/bmptest.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class BmpTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpBmp1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + BitmapDeviceSharedPtr mpBmp32bpp; + + void implTestBmpBasics(const BitmapDeviceSharedPtr& rDevice, + const BitmapDeviceSharedPtr& rBmp) + { + rDevice->clear(Color(0)); + const Color aCol(0xFFFFFFFF); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IRange aDestLeftTop(0,0,4,4); + const basegfx::B2IRange aDestRightTop(6,0,10,4); + const basegfx::B2IRange aDestLeftBottom(0,6,4,10); + const basegfx::B2IRange aDestRightBottom(6,6,10,10); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestLeftTop, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 8", + countPixel( rDevice, aCol ) == 8); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestRightTop, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 16", + countPixel( rDevice, aCol ) == 16); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestLeftBottom, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 24", + countPixel( rDevice, aCol ) == 24); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestRightBottom, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 32", + countPixel( rDevice, aCol ) == 32); + } + + void implTestBmpClip(const BitmapDeviceSharedPtr& rDevice, + const BitmapDeviceSharedPtr& rBmp) + { + rDevice->clear(Color(0)); + const Color aCol(0xFFFFFFFF); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IRange aDestLeftTop(-2,-2,2,2); + const basegfx::B2IRange aDestRightTop(8,-2,12,2); + const basegfx::B2IRange aDestLeftBottom(-2,8,2,12); + const basegfx::B2IRange aDestRightBottom(8,8,12,12); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestLeftTop, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 4", + countPixel( rDevice, aCol ) == 4); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestLeftBottom, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 4(c)", + countPixel( rDevice, aCol ) == 4); + + rDevice->drawBitmap( + rBmp, + aSourceRect, + aDestRightBottom, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 8", + countPixel( rDevice, aCol ) == 8); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(10,10); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + mpBmp1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpBmp32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0h5v10h5v-5h-10z" )); + + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + const Color aCol(0xFFFFFFFF); + mpBmp1bpp->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + mpBmp32bpp->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + } + + void testBmpBasics() + { + implTestBmpBasics( mpDevice1bpp, mpBmp1bpp ); + implTestBmpBasics( mpDevice32bpp, mpBmp32bpp ); + } + + void testBmpClip() + { + implTestBmpClip( mpDevice1bpp, mpBmp1bpp ); + implTestBmpClip( mpDevice32bpp, mpBmp32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(BmpTest); + CPPUNIT_TEST(testBmpBasics); + CPPUNIT_TEST(testBmpClip); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(BmpTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/cliptest.cxx b/basebmp/test/cliptest.cxx new file mode 100644 index 000000000000..c41edf3e28a8 --- /dev/null +++ b/basebmp/test/cliptest.cxx @@ -0,0 +1,268 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class ClipTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpClipMask; + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + void implTestPixelClip(const BitmapDeviceSharedPtr& rDevice) + { + const Color aBgCol(0); + rDevice->clear(aBgCol); + + const basegfx::B2IPoint aPt(0,0); + const Color aCol(0xFFFFFFFF); + rDevice->setPixel( aPt, aCol, DrawMode_PAINT, mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel clip #1", + rDevice->getPixel(aPt) == aBgCol); + + const basegfx::B2IPoint aPt2(10,10); + rDevice->setPixel( aPt2, aCol, DrawMode_PAINT, mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel clip #2", + rDevice->getPixel(aPt2) == aBgCol); + + const basegfx::B2IPoint aPt1(10,0); + rDevice->setPixel( aPt1, aCol, DrawMode_PAINT, mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel clip #3", + rDevice->getPixel(aPt1) != aBgCol); + + const basegfx::B2IPoint aPt3(0,10); + rDevice->setPixel( aPt3, aCol, DrawMode_PAINT, mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel clip #4", + rDevice->getPixel(aPt3) != aBgCol); + } + + void implTestLineClip(const BitmapDeviceSharedPtr& rDevice) + { + const Color aBgCol(0); + rDevice->clear(aBgCol); + + const basegfx::B2IPoint aPt1(0,0); + const basegfx::B2IPoint aPt2(1,9); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT, mpClipMask ); + + const basegfx::B2IPoint aPt3(1,5); + CPPUNIT_ASSERT_MESSAGE("get line pixel", + rDevice->getPixel(aPt3) != aBgCol); + CPPUNIT_ASSERT_MESSAGE("number of rendered line pixel is not 4", + countPixel( rDevice, + rDevice->getPixel(aPt3) ) == 4); + + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_XOR, mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("number of xor-rendered line pixel is not 0", + countPixel( rDevice, + rDevice->getPixel(aPt3) ) == 121); + } + + void implTestFillClip(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2DRange aAllOver(-10,-10,20,20); + const Color aCol(0xFFFFFFFF); + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aAllOver)), + aCol, + DrawMode_PAINT, + mpClipMask ); + const basegfx::B2IPoint aPt(0,10); + CPPUNIT_ASSERT_MESSAGE("number of clipped pixel is not 30", + countPixel( rDevice, rDevice->getPixel(aPt) ) == 121-30); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aAllOver)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of filled pixel is not 121", + countPixel( rDevice, rDevice->getPixel(aPt) ) == 121); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aAllOver)), + aCol, + DrawMode_XOR, + mpClipMask ); + CPPUNIT_ASSERT_MESSAGE("number of xor-cleared pixel is not 91", + countPixel( rDevice, rDevice->getPixel(aPt) ) == 121-30); + } + + void implTestBmpClip(const BitmapDeviceSharedPtr& rDevice) + { + BitmapDeviceSharedPtr pBmp( cloneBitmapDevice( + basegfx::B2IVector(3,3), + rDevice )); + Color aCol1(0); + Color aCol2(0xFFFFFFFF); + pBmp->clear(aCol1); + pBmp->setPixel(basegfx::B2IPoint(0,0),aCol2,DrawMode_PAINT); + pBmp->setPixel(basegfx::B2IPoint(1,1),aCol2,DrawMode_PAINT); + pBmp->setPixel(basegfx::B2IPoint(2,2),aCol2,basebmp::DrawMode_PAINT); + + rDevice->clear(aCol1); + rDevice->drawBitmap(pBmp, + basegfx::B2IRange(0,0,3,3), + basegfx::B2IRange(-1,-1,4,4), + DrawMode_PAINT, + mpClipMask); + + const basegfx::B2IPoint aPt(1,1); + CPPUNIT_ASSERT_MESSAGE("number of clipped pixel is not 5", + countPixel( rDevice, + rDevice->getPixel(aPt) ) == 5); + } + + void implTestMaskColorClip(const BitmapDeviceSharedPtr& rDevice) + { + BitmapDeviceSharedPtr pBmp( createBitmapDevice( rDevice->getSize(), + true, + Format::EIGHT_BIT_GREY )); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0h5v10h5v-5h-10z" )); + + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + const basebmp::Color aCol(0xFF); + pBmp->clear( basebmp::Color(0) ); + pBmp->fillPolyPolygon( + aPoly, + aCol, + basebmp::DrawMode_PAINT ); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IPoint aDestLeftTop(0,0); + const Color aCol2(0xF0F0F0F0); + rDevice->drawMaskedColor( + aCol2, + pBmp, + aSourceRect, + aDestLeftTop, + mpClipMask ); + const basegfx::B2IPoint aPt(1,1); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 41", + countPixel( rDevice, rDevice->getPixel(aPt) ) == 41); + + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(11,11); + mpClipMask = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_GREY ); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0 h5 l5 5 v5 h-5 l-5-5 z" )); + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + mpClipMask->clear(Color(0)); + mpClipMask->drawPolygon( + aPoly.getB2DPolygon(0), + Color(0xFFFFFFFF), + DrawMode_PAINT ); + } + + void testPixelClip() + { + implTestPixelClip( mpDevice1bpp ); + implTestPixelClip( mpDevice32bpp ); + } + + void testLineClip() + { + implTestLineClip( mpDevice1bpp ); + implTestLineClip( mpDevice32bpp ); + } + + void testFillClip() + { + implTestFillClip( mpDevice1bpp ); + implTestFillClip( mpDevice32bpp ); + } + + void testBmpClip() + { + implTestBmpClip( mpDevice1bpp ); + implTestBmpClip( mpDevice32bpp ); + } + + void testMaskColorClip() + { + implTestMaskColorClip( mpDevice1bpp ); + implTestMaskColorClip( mpDevice32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(ClipTest); + CPPUNIT_TEST(testPixelClip); + CPPUNIT_TEST(testLineClip); + CPPUNIT_TEST(testFillClip); + CPPUNIT_TEST(testBmpClip); + CPPUNIT_TEST(testMaskColorClip); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ClipTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/export.map b/basebmp/test/export.map new file mode 100644 index 000000000000..3308588ef6f8 --- /dev/null +++ b/basebmp/test/export.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +UDK_3_0_0 { + global: + cppunitTestPlugIn; + + local: + *; +}; diff --git a/basebmp/test/filltest.cxx b/basebmp/test/filltest.cxx new file mode 100644 index 000000000000..d15fa1010050 --- /dev/null +++ b/basebmp/test/filltest.cxx @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class FillTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + void implTestRectFill(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2DRange aRect(1,1,10,10); + + const Color aCol(0xFFFFFFFF); + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aRect )), + aCol, + DrawMode_PAINT ); + + const basegfx::B2IPoint aPt1(1,1); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + const basegfx::B2IPoint aPt2(9,9); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(10,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 81", + countPixel( rDevice, aCol ) == 81); + } + + void implTestCornerCases(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2DRange aEmpty1(0,0,0,11); + const basegfx::B2DRange aEmpty2(0,0,11,0); + const basegfx::B2DRange aVertLineLeft(0,0,1,11); + const basegfx::B2DRange aVertLineRight(10,0,11,11); + const basegfx::B2DRange aHorzLineTop(0,0,11,1); + const basegfx::B2DRange aHorzLineBottom(0,10,11,11); + + const Color aCol(0xFFFFFFFF); + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aEmpty1 )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 0", + countPixel( rDevice, aCol ) == 0); + + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aEmpty2 )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 0", + countPixel( rDevice, aCol ) == 0); + + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aVertLineLeft )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 11", + countPixel( rDevice, aCol ) == 11); + const basegfx::B2IPoint aPt1(0,0); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aVertLineRight )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 22", + countPixel( rDevice, aCol ) == 22); + const basegfx::B2IPoint aPt2(10,10); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aHorzLineTop )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 31", + countPixel( rDevice, aCol ) == 31); + const basegfx::B2IPoint aPt3(5,0); + CPPUNIT_ASSERT_MESSAGE("top-middle pixel set", + rDevice->getPixel(aPt3) == aCol); + + rDevice->fillPolyPolygon( + basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect( aHorzLineBottom )), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 40", + countPixel( rDevice, aCol ) == 40); + const basegfx::B2IPoint aPt4(5,10); + CPPUNIT_ASSERT_MESSAGE("bottom-middle pixel set", + rDevice->getPixel(aPt4) == aCol); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0l7 7h-1z" )); + + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 43", + countPixel( rDevice, aCol ) == 43); + } + + void implTestClipping(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2DRange aLeftTop(-10,-10,1,1); + const basegfx::B2DRange aRightTop(10,-10,20,1); + const basegfx::B2DRange aLeftBottom(-10,10,1,20); + const basegfx::B2DRange aRightBottom(10,10,20,20); + const basegfx::B2DRange aAllOver(-10,-10,20,20); + + const Color aCol(0xFFFFFFFF); + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aLeftTop)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 1", + countPixel( rDevice, aCol ) == 1); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aRightTop)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 2", + countPixel( rDevice, aCol ) == 2); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aLeftBottom)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 3", + countPixel( rDevice, aCol ) == 3); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aRightBottom)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 4", + countPixel( rDevice, aCol ) == 4); + + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon( + basegfx::tools::createPolygonFromRect(aAllOver)), + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 121", + countPixel( rDevice, aCol ) == 121); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(11,11); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + } + + void testRectFill() + { + implTestRectFill( mpDevice1bpp ); + implTestRectFill( mpDevice32bpp ); + } + + void testClipping() + { + implTestClipping( mpDevice1bpp ); + implTestClipping( mpDevice32bpp ); + } + + void testCornerCases() + { + implTestCornerCases( mpDevice1bpp ); + implTestCornerCases( mpDevice32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(FillTest); + CPPUNIT_TEST(testRectFill); + CPPUNIT_TEST(testClipping); + CPPUNIT_TEST(testCornerCases); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(FillTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/linetest.cxx b/basebmp/test/linetest.cxx new file mode 100644 index 000000000000..cee66f4d709b --- /dev/null +++ b/basebmp/test/linetest.cxx @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class LineTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + void implTestBasicDiagonalLines(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(9,9); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(10,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 9", + countPixel( rDevice, aCol ) == 9); + + rDevice->drawLine( aPt2, aPt1, aCol, DrawMode_PAINT ); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 9", + countPixel( rDevice, aCol ) == 9); + } + + void implTestBasicHorizontalLines(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(10,10); + const basegfx::B2IPoint aPt2(0,10); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 11", + countPixel( rDevice, aCol ) == 11); + + rDevice->clear(Color(0)); + rDevice->drawLine( aPt2, aPt1, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 11", + countPixel( rDevice, aCol ) == 11); + } + + void implTestBasicVerticalLines(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(1,9); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(0,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 9", + countPixel( rDevice, aCol ) == 9); + } + + // test pixel rounding (should always tend towards start point of + // the line) + void implTestTieBreaking(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(3,2); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("second pixel set", + rDevice->getPixel(basegfx::B2IPoint(2,1)) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 3", + countPixel( rDevice, aCol ) == 3); + + rDevice->drawLine( aPt2, aPt1, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("alternate second pixel set", + rDevice->getPixel(basegfx::B2IPoint(2,2)) == aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 4", + countPixel( rDevice, aCol ) == 4); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(11,11); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + } + + void testBasicDiagonalLines() + { + implTestBasicDiagonalLines( mpDevice1bpp ); + implTestBasicDiagonalLines( mpDevice32bpp ); + } + + void testBasicHorizontalLines() + { + implTestBasicHorizontalLines( mpDevice1bpp ); + implTestBasicHorizontalLines( mpDevice32bpp ); + } + + void testBasicVerticalLines() + { + implTestBasicVerticalLines( mpDevice1bpp ); + implTestBasicVerticalLines( mpDevice32bpp ); + } + + // test pixel rounding (should always tend towards start point of + // the line) + void testTieBreaking() + { + implTestTieBreaking( mpDevice1bpp ); + implTestTieBreaking( mpDevice32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(LineTest); + CPPUNIT_TEST(testBasicDiagonalLines); + CPPUNIT_TEST(testBasicHorizontalLines); + CPPUNIT_TEST(testBasicVerticalLines); + CPPUNIT_TEST(testTieBreaking); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(LineTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/masktest.cxx b/basebmp/test/masktest.cxx new file mode 100644 index 000000000000..239a069bf564 --- /dev/null +++ b/basebmp/test/masktest.cxx @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class MaskTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + BitmapDeviceSharedPtr mpMask; + + void implTestMaskBasics(const BitmapDeviceSharedPtr& rDevice, + const BitmapDeviceSharedPtr& rBmp) + { + const Color aCol(0); + const Color aCol2(0xF0F0F0F0); + + const basegfx::B2IRange aSourceRect(0,0,10,10); + const basegfx::B2IPoint aDestLeftTop(0,0); + const basegfx::B2IPoint aDestRightTop(5,0); + const basegfx::B2IPoint aDestLeftBottom(0,5); + const basegfx::B2IPoint aDestRightBottom(5,5); + + rDevice->clear(aCol); + rDevice->setPixel( + basegfx::B2IPoint(1,1), + aCol2, + DrawMode_PAINT); + rDevice->drawMaskedColor( + aCol2, + rBmp, + aSourceRect, + aDestLeftTop ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 50", + countPixel( rDevice, aCol ) == 100-50); + + rDevice->clear(aCol); + rDevice->drawMaskedColor( + aCol2, + rBmp, + aSourceRect, + aDestRightTop ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 25", + countPixel( rDevice, aCol ) == 100-25); + + rDevice->clear(aCol); + rDevice->drawMaskedColor( + aCol2, + rBmp, + aSourceRect, + aDestLeftBottom ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 25(b)", + countPixel( rDevice, aCol ) == 100-25); + + rDevice->clear(aCol); + rDevice->drawMaskedColor( + aCol2, + rBmp, + aSourceRect, + aDestRightBottom ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 25(c)", + countPixel( rDevice, aCol ) == 100-25); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(10,10); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + mpMask = createBitmapDevice( aSize, + true, + Format::EIGHT_BIT_GREY ); + + ::rtl::OUString aSvg( RTL_CONSTASCII_USTRINGPARAM( "m 0 0h5v10h5v-5h-10z" )); + + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD( aPoly, aSvg ); + const Color aCol(0xFF); + mpMask->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + } + + void testMaskBasics() + { + implTestMaskBasics( mpDevice32bpp, mpMask ); + implTestMaskBasics( mpDevice1bpp, mpMask ); + } + + void testMaskClip() + { + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(MaskTest); + CPPUNIT_TEST(testMaskBasics); + CPPUNIT_TEST(testMaskClip); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(MaskTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/polytest.cxx b/basebmp/test/polytest.cxx new file mode 100644 index 000000000000..99aba1a06fc4 --- /dev/null +++ b/basebmp/test/polytest.cxx @@ -0,0 +1,284 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include "tools.hxx" + +using namespace ::basebmp; + +namespace +{ +class PolyTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + void implTestEmpty(const BitmapDeviceSharedPtr& rDevice) + { + const Color aCol(0xFFFFFFFF); + const Color aBgCol(0); + rDevice->clear(aBgCol); + basegfx::B2DPolyPolygon aPoly; + ::rtl::OUString aSvg; + + basegfx::tools::importFromSvgD( + aPoly, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M2 2 l7 7 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 0", + countPixel( rDevice, aCol ) == 0); + + // -------------------------------------------------- + + rDevice->clear(aBgCol); + aPoly.clear(); + basegfx::tools::importFromSvgD( + aPoly, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M7 2 l-6 6 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 0(b)", + countPixel( rDevice, aCol ) == 0); + } + + void implTestHairline(const BitmapDeviceSharedPtr& rDevice) + { + const Color aCol(0xFFFFFFFF); + const Color aBgCol(0); + rDevice->clear(aBgCol); + basegfx::B2DPolyPolygon aPoly; + ::rtl::OUString aSvg; + + basegfx::tools::importFromSvgD( + aPoly, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M2 2 h1 l7 7 h-1 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 7", + countPixel( rDevice, aCol ) == 7); + + // -------------------------------------------------- + + rDevice->clear(aBgCol); + aPoly.clear(); + basegfx::tools::importFromSvgD( + aPoly, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M7 2 h-1 l-6 6 h1 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 6", + countPixel( rDevice, aCol ) == 6); + + // -------------------------------------------------- + + rDevice->clear(aBgCol); + aPoly.clear(); + basegfx::tools::importFromSvgD( + aPoly, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M0 0 l7 7 h-1 l-5-7 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 3", + countPixel( rDevice, aCol ) == 3); + } + + void implTestPolyPoly(const BitmapDeviceSharedPtr& rDevice) + { + const Color aCol(0xFFFFFFFF); + const Color aBgCol(0); + rDevice->clear(aBgCol); + basegfx::B2DPolyPolygon aPoly; + ::rtl::OUString aSvg; + + basegfx::tools::importFromSvgD( aPoly, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" )) ); + + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 40", + countPixel( rDevice, aCol ) == 40); + } + + void implTestPolyPolyClip(const BitmapDeviceSharedPtr& rDevice) + { + const Color aCol(0xFFFFFFFF); + const Color aBgCol(0); + rDevice->clear(aBgCol); + basegfx::B2DPolyPolygon aPoly; + ::rtl::OUString aSvg; + + basegfx::tools::importFromSvgD( aPoly, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" )) ); + basegfx::B2DHomMatrix aMat; + aMat.translate(-3,-3); + aMat.rotate( 1.7 ); + aMat.translate(6,5); + aPoly.transform(aMat); + + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 39", + countPixel( rDevice, aCol ) == 39); + + BitmapDeviceSharedPtr pClippedDevice( + subsetBitmapDevice( rDevice, + basegfx::B2IRange(3,3,5,8) )); + + rDevice->clear(aBgCol); + pClippedDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 7", + countPixel( rDevice, aCol ) == 7); + } + + void implTestPolyPolyCrissCross(const BitmapDeviceSharedPtr& rDevice) + { + const Color aCol(0xFFFFFFFF); + const Color aBgCol(0); + rDevice->clear(aBgCol); + basegfx::B2DPolyPolygon aPoly; + ::rtl::OUString aSvg; + + basegfx::tools::importFromSvgD( aPoly, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "M0 0 v2 l10 2 v-2 z" + "M10 6 v-2 l-10 2 v2 z" + "M1 0 h1 v10 h-1 z" + "M4 0 h1 v10 h-1 z" + "M8 0 h1 v10 h-1 z" )) ); + rDevice->fillPolyPolygon( + aPoly, + aCol, + DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 46", + countPixel( rDevice, aCol ) == 46); + } + + +public: + void setUp() + { + const basegfx::B2ISize aSize(10,10); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + } + + void testEmpty() + { + implTestEmpty( mpDevice1bpp ); + implTestEmpty( mpDevice32bpp ); + } + + void testHairline() + { + implTestHairline( mpDevice1bpp ); + implTestHairline( mpDevice32bpp ); + } + + void testPolyPoly() + { + implTestPolyPoly( mpDevice1bpp ); + implTestPolyPoly( mpDevice32bpp ); + } + + void testPolyPolyClip() + { + implTestPolyPolyClip(mpDevice1bpp); + implTestPolyPolyClip(mpDevice32bpp); + } + + void testPolyPolyCrissCross() + { + implTestPolyPolyCrissCross(mpDevice1bpp); + implTestPolyPolyCrissCross(mpDevice32bpp); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(PolyTest); + CPPUNIT_TEST(testEmpty); + CPPUNIT_TEST(testHairline); + CPPUNIT_TEST(testPolyPoly); + CPPUNIT_TEST(testPolyPolyClip); + CPPUNIT_TEST(testPolyPolyCrissCross); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(PolyTest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/tools.cxx b/basebmp/test/tools.cxx new file mode 100644 index 000000000000..ab7219ec32af --- /dev/null +++ b/basebmp/test/tools.cxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// autogenerated file with codegen.pl + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/bitmapdevice.hxx> + +using namespace ::basebmp; + +int countPixel( const BitmapDeviceSharedPtr& rDevice, + Color checkColor ) +{ + int count(0); + const basegfx::B2ISize& rSize( rDevice->getSize() ); + for( sal_Int32 y=0; y<rSize.getY(); ++y ) + for( sal_Int32 x=0; x<rSize.getX(); ++x ) + if( rDevice->getPixel( basegfx::B2IPoint(x,y) ) == checkColor ) + ++count; + + return count; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basebmp/test/tools.hxx b/basebmp/test/tools.hxx new file mode 100644 index 000000000000..57668e55a741 --- /dev/null +++ b/basebmp/test/tools.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "basebmp/bitmapdevice.hxx" + +int countPixel( const basebmp::BitmapDeviceSharedPtr& rDevice, + basebmp::Color checkColor ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |