<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tools.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: ihi $ $Date: 2006-08-03 14:40:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SLIDESHOW_TOOLS_HXX
#define _SLIDESHOW_TOOLS_HXX

#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HXX_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif
#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX
#include <basegfx/range/b2drectangle.hxx>
#endif
#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif
#ifndef _BGFX_VECTOR_B2DSIZE_HXX
#include <basegfx/vector/b2dsize.hxx>
#endif

#ifndef BOOST_BIND_HPP_INCLUDED
#include <boost/bind.hpp>
#endif
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#include <shapeattributelayer.hxx>

#include <string.h> // for strcmp
#include <algorithm>

#include <shape.hxx>
#include <rgbcolor.hxx>
#include <hslcolor.hxx>

#include "boost/optional.hpp"
#include <functional>
#include <cstdlib>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )

namespace com { namespace sun { namespace star { namespace beans {
    struct NamedValue;
} } } }

class GDIMetaFile;

/* Definition of some animation tools */
namespace presentation
{
    namespace internal
    {
        typedef ::boost::shared_ptr< GDIMetaFile > GDIMetaFileSharedPtr;

        // xxx todo: remove with boost::hash when 1.33 is available
        template <typename T>
        struct hash : ::std::unary_function<T, ::std::size_t>
        {
            ::std::size_t operator()( T const& val ) const {
                return hash_value(val);
            }
        };
        template <typename T>
        inline ::std::size_t hash_value( T * const& p )
        {
            ::std::size_t d = static_cast< ::std::size_t >(
                reinterpret_cast< ::std::ptrdiff_t >(p) );
            return d + (d >> 3);
        }

        // xxx todo: shift to namespace com::sun::star::uno when
        //           1.33 is available
        template <typename T>
        inline ::std::size_t hash_value(
            ::com::sun::star::uno::Reference<T> const& x )
        {
            // normalize to object root, because _only_ XInterface is defined
            // to be stable during object lifetime:
            ::com::sun::star::uno::Reference<
                  ::com::sun::star::uno::XInterface> const xRoot(
                      x, ::com::sun::star::uno::UNO_QUERY );
            return hash<void *>()(xRoot.get());
        }

        /** Cycle mode of intrinsic animations
         */
        enum CycleMode
        {
            /// loop the animation back to back
            CYCLE_LOOP,
            /// loop, but play backwards from end to start
            CYCLE_PINGPONGLOOP
        };

        // Value extraction from Any
        // =========================

        class LayerManager;
        typedef ::boost::shared_ptr< LayerManager > LayerManagerSharedPtr;

        /// extract unary double value from Any
        bool extractValue( double&                              o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int16&                           o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( RGBColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( HSLColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract plain string from Any
        bool extractValue( ::rtl::OUString&                     o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract bool value from Any
        bool extractValue( bool&                                o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract double 2-tuple from Any
        bool extractValue( ::basegfx::B2DTuple&                 o_rPair,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /** Search a sequence of NamedValues for a given element.

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue > const& rSequence,
                             const ::com::sun::star::beans::NamedValue& rSearchKey );

        /** Search a sequence of NamedValues for an element with a given name.

            @param o_pRet
            If non-NULL, receives the full NamedValue found (if it was
            found, that is).

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::beans::NamedValue*       o_pRet,
                             const ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::rtl::OUString&                     rSearchString );

        inline ::basegfx::B2DRectangle calcRelativeShapeBounds( const ::basegfx::B2DRectangle& rPageBounds,
                                                                const ::basegfx::B2DRectangle& rShapeBounds )
        {
            return ::basegfx::B2DRectangle( rShapeBounds.getMinX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMinY() / rPageBounds.getHeight(),
                                            rShapeBounds.getMaxX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMaxY() / rPageBounds.getHeight() );
        }

        /** Get the shape transformation from the attribute set

            @param rBounds
            Original shape bound rect (to substitute default attribute
            layer values)

            @param pAttr
            Attribute set. Might be NULL (then, rBounds is used to set
            a simple scale and translate of the unit rect to rBounds).
        */
        ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&      rBounds,
                                                        const ShapeAttributeLayerSharedPtr& pAttr );

        /** Get a shape's sprite transformation from the attribute set

            @param rPixelSize
            Pixel size of the sprite

            @param rOrigSize
            Original shape size (i.e. the size of the actual sprite
            content, in the user coordinate system)

            @param pAttr
            Attribute set. Might be NULL (then, rBounds is used to set
            a simple scale and translate of the unit rect to rBounds).

            @return the transformation to be applied to the sprite.
        */
        ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DSize&              rPixelSize,
                                                         const ::basegfx::B2DSize&              rOrigSize,
                                                         const ShapeAttributeLayerSharedPtr&    pAttr );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape. Apart from applying the given transformation to the
            shape rectangle, this method also takes attributes into
            account, which further scale the output (e.g. character
            sizes).

            @param rUnitBounds
            Shape bounds, in the unit rect coordinate space

            @param rShapeTransform
            Transformation matrix the shape should undergo.

            @param pAttr
            Current shape attributes
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rUnitBounds,
                                                    const ::basegfx::B2DHomMatrix&      rShapeTransform,
                                                    const ShapeAttributeLayerSharedPtr& pAttr );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape. The difference from the other getShapeUpdateArea()
            method is the fact that this one works without
            ShapeAttributeLayer, and only scales up the given shape
            user coordinate bound rect. The method is typically used
            to retrieve user coordinate system bound rects for shapes
            which are smaller than the default unit bound rect
            (because e.g. of subsetting)

            @param rUnitBounds
            Shape bounds, in the unit rect coordinate space

            @param rShapeBounds
            Current shape bounding box in user coordinate space.
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rUnitBounds,
                                                    const ::basegfx::B2DRectangle&      rShapeBounds );

        /** Calc output position and size of shape, according to given
            attribute layer.

            Rotations, shears etc. and not taken into account,
            i.e. the returned rectangle is NOT the bounding box. Use
            it as if aBounds.getMinimum() is the output position and
            aBounds.getRange() the scaling of the shape.
         */
        ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle&         rOrigBounds,
                                                 const ShapeAttributeLayerSharedPtr&    pAttr );

        /** Convert a plain UNO API 32 bit int to RGBColor
         */
        RGBColor unoColor2RGBColor( sal_Int32 );

        /** Init canvas with default background (white)
         */
        void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
                                  const ::basegfx::B2ISize&           rSize );

        /// Gets a random ordinal [0,n)
        inline ::std::size_t getRandomOrdinal( const ::std::size_t n )
        {
            return static_cast< ::std::size_t >(
                double(n) * rand() / (RAND_MAX + 1.0) );
        }

        /// To work around ternary operator in initializer lists
        /// (Solaris compiler problems)
        template <typename T>
        inline T const & ternary_op(
            const bool cond, T const & arg1, T const & arg2 )
        {
            if (cond)
                return arg1;
            else
                return arg2;
        }

        template <typename ValueType>
        inline bool getPropertyValue(
            ValueType & rValue,
            com::sun::star::uno::Reference<
            com::sun::star::beans::XPropertySet> const & xPropSet,
            rtl::OUString const & propName )
        {
            try {
                com::sun::star::uno::Any const a(
                    xPropSet->getPropertyValue( propName ) );
                bool const bRet = (a >>= rValue);
                OSL_ENSURE( bRet, "property seems to have unexpected type!" );
                return bRet;
            }
            catch (com::sun::star::uno::RuntimeException &) {
                throw;
            }
            catch (com::sun::star::uno::Exception &) {
                return false;
            }
        }
    }
}

#endif /* _SLIDESHOW_TOOLS_HXX */
<commit_msg>INTEGRATION: CWS presfixes09 (1.7.10); FILE MERGED 2006/04/24 13:25:38 thb 1.7.10.7: #i53194# Unified include statements (local headers always have double quotes; external headers angle brackets); reverted EventMultiplexer pause events to shared_ptr; removed EventMultiplexer::removeViewHandler(), since the handler is held weakly, anyway. 2006/04/13 14:16:45 thb 1.7.10.6: #i37778# Added line break to OSL_TRACEs; improved getPropertyValue() debug output 2006/04/12 19:25:07 thb 1.7.10.5: #i37778# Making slideshow engine much more robust against missing/unsupported interfaces and properties; fixed RehearseTimings output offset issue; fixed WaitSymbol output position 2006/03/24 18:23:39 thb 1.7.10.4: #i37778# Moved whole slideshow engine from namespace presentation (which conflicts with one of the UNO subnamespaces) to slideshow 2006/03/08 18:08:07 thb 1.7.10.3: #i49357# Removed cruft from gdimtftools; moved slideshow component to ServiceDecl; refactored multiple places of filling a rectangle in XCanvas into a tools method; now clearing the shape area to grey50 for applets/plugins (to at least show _something_ during slide transitions) 2006/03/06 22:41:13 thb 1.7.10.2: #i49357# Added AppletShape, which implements Java applets & plugin objects (Netscape plugins) 2006/03/06 22:14:37 thb 1.7.10.1: #i53194# #i55294# #i59324# Overhauled IntrinsicAnimationActivity; fixes GIF animation import; corrected rehearse timings sprite size; several cosmetic changes (removed external header guards); prepared scene for sprite prio<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tools.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 16:05:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SLIDESHOW_TOOLS_HXX
#define _SLIDESHOW_TOOLS_HXX

#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b2dsize.hxx>

#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

#include "shapeattributelayer.hxx"
#include "shape.hxx"
#include "rgbcolor.hxx"
#include "hslcolor.hxx"

#include <string.h> // for strcmp
#include <algorithm>

#include <boost/optional.hpp>
#include <functional>
#include <cstdlib>

#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )

namespace com { namespace sun { namespace star { namespace beans {
    struct NamedValue;
} } } }

class GDIMetaFile;

/* Definition of some animation tools */
namespace slideshow
{
    namespace internal
    {
        typedef ::boost::shared_ptr< GDIMetaFile > GDIMetaFileSharedPtr;

        // xxx todo: remove with boost::hash when 1.33 is available
        template <typename T>
        struct hash : ::std::unary_function<T, ::std::size_t>
        {
            ::std::size_t operator()( T const& val ) const {
                return hash_value(val);
            }
        };
        template <typename T>
        inline ::std::size_t hash_value( T * const& p )
        {
            ::std::size_t d = static_cast< ::std::size_t >(
                reinterpret_cast< ::std::ptrdiff_t >(p) );
            return d + (d >> 3);
        }

        // xxx todo: shift to namespace com::sun::star::uno when
        //           1.33 is available
        template <typename T>
        inline ::std::size_t hash_value(
            ::com::sun::star::uno::Reference<T> const& x )
        {
            // normalize to object root, because _only_ XInterface is defined
            // to be stable during object lifetime:
            ::com::sun::star::uno::Reference<
                  ::com::sun::star::uno::XInterface> const xRoot(
                      x, ::com::sun::star::uno::UNO_QUERY );
            return hash<void *>()(xRoot.get());
        }

        /** Cycle mode of intrinsic animations
         */
        enum CycleMode
        {
            /// loop the animation back to back
            CYCLE_LOOP,
            /// loop, but play backwards from end to start
            CYCLE_PINGPONGLOOP
        };

        // Value extraction from Any
        // =========================

        class LayerManager;
        typedef ::boost::shared_ptr< LayerManager > LayerManagerSharedPtr;

        /// extract unary double value from Any
        bool extractValue( double&                              o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract int from Any
        bool extractValue( sal_Int32&                           o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int16&                           o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( RGBColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract color value from Any
        bool extractValue( HSLColor&                            o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract plain string from Any
        bool extractValue( ::rtl::OUString&                     o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract bool value from Any
        bool extractValue( bool&                                o_rValue,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /// extract double 2-tuple from Any
        bool extractValue( ::basegfx::B2DTuple&                 o_rPair,
                           const ::com::sun::star::uno::Any&    rSourceAny,
                           const ShapeSharedPtr&                rShape,
                           const LayerManagerSharedPtr&         rLayerManager );

        /** Search a sequence of NamedValues for a given element.

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue > const& rSequence,
                             const ::com::sun::star::beans::NamedValue& rSearchKey );

        /** Search a sequence of NamedValues for an element with a given name.

            @param o_pRet
            If non-NULL, receives the full NamedValue found (if it was
            found, that is).

            @return true, if the sequence contains the specified
            element.
         */
        bool findNamedValue( ::com::sun::star::beans::NamedValue*       o_pRet,
                             const ::com::sun::star::uno::Sequence<
                                 ::com::sun::star::beans::NamedValue >&     rSequence,
                             const ::rtl::OUString&                     rSearchString );

        inline ::basegfx::B2DRectangle calcRelativeShapeBounds( const ::basegfx::B2DRectangle& rPageBounds,
                                                                const ::basegfx::B2DRectangle& rShapeBounds )
        {
            return ::basegfx::B2DRectangle( rShapeBounds.getMinX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMinY() / rPageBounds.getHeight(),
                                            rShapeBounds.getMaxX() / rPageBounds.getWidth(),
                                            rShapeBounds.getMaxY() / rPageBounds.getHeight() );
        }

        /** Get the shape transformation from the attribute set

            @param rBounds
            Original shape bound rect (to substitute default attribute
            layer values)

            @param pAttr
            Attribute set. Might be NULL (then, rBounds is used to set
            a simple scale and translate of the unit rect to rBounds).
        */
        ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&      rBounds,
                                                        const ShapeAttributeLayerSharedPtr& pAttr );

        /** Get a shape's sprite transformation from the attribute set

            @param rPixelSize
            Pixel size of the sprite

            @param rOrigSize
            Original shape size (i.e. the size of the actual sprite
            content, in the user coordinate system)

            @param pAttr
            Attribute set. Might be NULL (then, rBounds is used to set
            a simple scale and translate of the unit rect to rBounds).

            @return the transformation to be applied to the sprite.
        */
        ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DSize&              rPixelSize,
                                                         const ::basegfx::B2DSize&              rOrigSize,
                                                         const ShapeAttributeLayerSharedPtr&    pAttr );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape. Apart from applying the given transformation to the
            shape rectangle, this method also takes attributes into
            account, which further scale the output (e.g. character
            sizes).

            @param rUnitBounds
            Shape bounds, in the unit rect coordinate space

            @param rShapeTransform
            Transformation matrix the shape should undergo.

            @param pAttr
            Current shape attributes
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rUnitBounds,
                                                    const ::basegfx::B2DHomMatrix&      rShapeTransform,
                                                    const ShapeAttributeLayerSharedPtr& pAttr );

        /** Calc update area for a shape.

            This method calculates the 'covered' area for the shape,
            i.e. the rectangle that is affected when rendering the
            shape. The difference from the other getShapeUpdateArea()
            method is the fact that this one works without
            ShapeAttributeLayer, and only scales up the given shape
            user coordinate bound rect. The method is typically used
            to retrieve user coordinate system bound rects for shapes
            which are smaller than the default unit bound rect
            (because e.g. of subsetting)

            @param rUnitBounds
            Shape bounds, in the unit rect coordinate space

            @param rShapeBounds
            Current shape bounding box in user coordinate space.
         */
        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&      rUnitBounds,
                                                    const ::basegfx::B2DRectangle&      rShapeBounds );

        /** Calc output position and size of shape, according to given
            attribute layer.

            Rotations, shears etc. and not taken into account,
            i.e. the returned rectangle is NOT the bounding box. Use
            it as if aBounds.getMinimum() is the output position and
            aBounds.getRange() the scaling of the shape.
         */
        ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle&         rOrigBounds,
                                                 const ShapeAttributeLayerSharedPtr&    pAttr );

        /** Convert a plain UNO API 32 bit int to RGBColor
         */
        RGBColor unoColor2RGBColor( sal_Int32 );

        /** Fill a plain rectangle on the given canvas with the given color
         */
        void fillRect( const ::cppcanvas::CanvasSharedPtr& rCanvas,
                       const ::basegfx::B2DRectangle&      rRect,
                       ::cppcanvas::Color::IntSRGBA        aFillColor );

        /** Init canvas with default background (white)
         */
        void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
                                  const ::basegfx::B2ISize&           rSize );

        /// Gets a random ordinal [0,n)
        inline ::std::size_t getRandomOrdinal( const ::std::size_t n )
        {
            return static_cast< ::std::size_t >(
                double(n) * rand() / (RAND_MAX + 1.0) );
        }

        /// To work around ternary operator in initializer lists
        /// (Solaris compiler problems)
        template <typename T>
        inline T const & ternary_op(
            const bool cond, T const & arg1, T const & arg2 )
        {
            if (cond)
                return arg1;
            else
                return arg2;
        }

        template <typename ValueType>
        inline bool getPropertyValue(
            ValueType & rValue,
            com::sun::star::uno::Reference<
            com::sun::star::beans::XPropertySet> const & xPropSet,
            rtl::OUString const & propName )
        {
            try {
                const com::sun::star::uno::Any& a(
                    xPropSet->getPropertyValue( propName ) );
                bool const bRet = (a >>= rValue);
#if OSL_DEBUG_LEVEL > 0
                if( !bRet )
                    OSL_TRACE( "%s: while retrieving property %s, cannot extract Any of type %s\n",
                               ::rtl::OUStringToOString( propName,
                                                         RTL_TEXTENCODING_ASCII_US ).getStr(),
                               BOOST_CURRENT_FUNCTION,
                               ::rtl::OUStringToOString( a.getValueTypeRef()->pTypeName,
                                                         RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
                return bRet;
            }
            catch (com::sun::star::uno::RuntimeException &)
            {
                throw;
            }
            catch (com::sun::star::uno::Exception &)
            {
                return false;
            }
        }

        template <typename ValueType>
        inline bool getPropertyValue(
            com::sun::star::uno::Reference< ValueType >& rIfc,
            com::sun::star::uno::Reference<
            com::sun::star::beans::XPropertySet> const & xPropSet,
            rtl::OUString const & propName )
        {
            try
            {
                const com::sun::star::uno::Any& a(
                    xPropSet->getPropertyValue( propName ));
                rIfc.set( a,
                          com::sun::star::uno::UNO_QUERY );

                bool const bRet = rIfc.is();
#if OSL_DEBUG_LEVEL > 0
                if( !bRet )
                    OSL_TRACE( "%s: while retrieving property %s, cannot extract Any of type %s to interface\n",
                               ::rtl::OUStringToOString( propName,
                                                         RTL_TEXTENCODING_ASCII_US ).getStr(),
                               BOOST_CURRENT_FUNCTION,
                               ::rtl::OUStringToOString( a.getValueTypeRef()->pTypeName,
                                                         RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
                return bRet;
            }
            catch (com::sun::star::uno::RuntimeException &)
            {
                throw;
            }
            catch (com::sun::star::uno::Exception &)
            {
                return false;
            }
        }

        /// Get the content of the BoundRect shape property
        ::basegfx::B2DRectangle getAPIShapeBounds( const ::com::sun::star::uno::Reference<
                                                         ::com::sun::star::drawing::XShape >& xShape );

        /// Get the content of the ZOrder shape property
        double getAPIShapePrio( const ::com::sun::star::uno::Reference<
                                      ::com::sun::star::drawing::XShape >& xShape );
    }
}

#endif /* _SLIDESHOW_TOOLS_HXX */
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

/*
 * This represents a collection of row blocks that we usually access with
 * a single I/O request. However, due to load balancing, we sometimes
 * need to access the collection of row blocks with many smaller I/O
 * requests. In this case, each row block is accessed by one I/O request.
 */
class large_row_io
{
	// A reference to the row block vector of the graph.
	const std::vector<row_block> *blocks;
	// The offset of the first row block in the row block vector.
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	/*
	 * Create an I/O request that access all row blocks in the collection.
	 */
	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	/*
	 * Create an I/O request that accesses a single row block.
	 */
	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

/*
 * The I/O generator that access a matrix on disks by rows.
 * An I/O generator are assigned a number of row blocks that it can accesses.
 * Each thread has an I/O generator and gets I/O requests from its own I/O
 * generator. When load balancing kicks in, a thread will try to steal I/O requests
 * from other threads' I/O generators.
 */
class row_io_generator: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	row_io_generator(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, const row_block_mapper &mapper);

	/*
	 * This method is called by the worker thread that owns the I/O generator
	 * to get I/O requests.
	 */
	virtual matrix_io get_next_io() {
		// TODO it should return a smaller I/O to improve load balancing at
		// the end of SpMM.
		matrix_io ret;
		pthread_spin_lock(&lock);
		// It's possible that all IOs have been stolen.
		// We have to check it.
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

row_io_generator::row_io_generator(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id,
		const row_block_mapper &mapper)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		size_t num_row_blocks = mapper.get_range(i).num;
		off_t rb_off = mapper.get_range(i).idx;
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - rb_off * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, rb_off, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

/*
 * The I/O generator for accessing 2D-partitioned blocks.
 * A generated I/O request may access multiple 2D-partitioned blocks.
 * Each I/O generator still accesses all blocks in a block row.
 */
class b2d_io_generator: public matrix_io_generator
{
	pthread_spinlock_t lock;
	size_t brow_idx;
	size_t min_num_brows;
	size_t io_num_brows;
	// This is the starting point where we give a single block row for
	// each assignment for load balancing. This points to a block row.
	size_t balance_point;

	SpM_2d_index::ptr idx;
	block_2d_size block_size;
	int file_id;
	size_t tot_num_cols;
public:
	b2d_io_generator(SpM_2d_index::ptr idx, int file_id, size_t io_num_brows,
			size_t min_num_brows);

	virtual matrix_io get_next_io();

	virtual bool has_next_io() {
		return brow_idx < idx->get_num_block_rows();
	}
};

b2d_io_generator::b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
		size_t io_num_brows, size_t min_num_brows): block_size(
			idx->get_header().get_2d_block_size())
{
	this->idx = idx;
	this->io_num_brows = io_num_brows;
	this->min_num_brows = min_num_brows;
	if (io_num_brows > min_num_brows) {
		size_t num_threads = detail::mem_thread_pool::get_global_num_threads();
		// We reserve some block rows in the matrix that are assigned one blow
		// row at a time.
		if (idx->get_num_block_rows() > io_num_brows * num_threads)
			balance_point = idx->get_num_block_rows() - num_threads;
		else
			balance_point = 0;
	}
	else
		balance_point = idx->get_num_block_rows();
	this->tot_num_cols = idx->get_header().get_num_cols();
	this->file_id = file_id;
	this->brow_idx = 0;
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
}

matrix_io b2d_io_generator::get_next_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (has_next_io()) {
		// If we have passed the balancing point, we now assign one block row
		// to a thread each time.
		if (brow_idx >= balance_point)
			io_num_brows = min_num_brows;

		matrix_loc mat_loc(brow_idx * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, idx->get_block_row_off(brow_idx));
		size_t num_brows = std::min(io_num_brows,
				idx->get_num_block_rows() - brow_idx);
		size_t brow_size = idx->get_block_row_off(brow_idx
				+ num_brows) - idx->get_block_row_off(brow_idx);
		ret = matrix_io(mat_loc, block_size.get_num_rows() * num_brows,
				tot_num_cols, data_loc, brow_size);
		brow_idx += num_brows;
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new row_io_generator(_blocks,
				tot_num_rows, tot_num_cols, file_id, mapper));
}

matrix_io_generator::ptr matrix_io_generator::create(SpM_2d_index::ptr idx,
		int file_id, size_t io_num_brows, size_t min_num_brows)
{
	return matrix_io_generator::ptr(new b2d_io_generator(idx, file_id,
				io_num_brows, min_num_brows));
}

void row_block_mapper::init(size_t num_rbs, size_t range_size)
{
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	for (size_t i = 0; i < num_rbs; i += range_size) {
		struct rb_range range;
		range.idx = i;
		range.num = std::min(range_size, num_rbs - i);
		ranges.push_back(range);
	}
}

row_block_mapper::row_block_mapper(const SpM_2d_index &index, size_t range_size)
{
	init(index.get_num_block_rows(), range_size);
}

}
<commit_msg>[Matrix]: add a static I/O gen for FG SpMM.<commit_after>/*
 * Copyright 2014 Open Connectome Project (http://openconnecto.me)
 * Written by Da Zheng (zhengda1936@gmail.com)
 *
 * This file is part of FlashMatrix.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <pthread.h>

#include "sparse_matrix.h"
#include "matrix_io.h"
#include "matrix_config.h"

namespace fm
{

/*
 * This represents a collection of row blocks that we usually access with
 * a single I/O request. However, due to load balancing, we sometimes
 * need to access the collection of row blocks with many smaller I/O
 * requests. In this case, each row block is accessed by one I/O request.
 */
class large_row_io
{
	// A reference to the row block vector of the graph.
	const std::vector<row_block> *blocks;
	// The offset of the first row block in the row block vector.
	off_t first_row_block;
	size_t num_row_blocks;
	size_t tot_num_rows;
public:
	large_row_io(const std::vector<row_block> &_blocks, off_t first_row_block,
			size_t num_row_blocks, size_t tot_num_rows) {
		this->blocks = &_blocks;
		this->first_row_block = first_row_block;
		this->num_row_blocks = num_row_blocks;
		this->tot_num_rows = tot_num_rows;
	}

	/*
	 * Create an I/O request that access all row blocks in the collection.
	 */
	matrix_io get_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_rows = tot_num_rows;
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows, tot_num_cols,
					safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_row_blocks;
		num_row_blocks = 0;
		tot_num_rows = 0;
		return ret;
	}

	/*
	 * Create an I/O request that accesses a single row block.
	 */
	matrix_io get_sub_io(size_t tot_num_cols, int file_id) {
		off_t first_row_id = first_row_block * matrix_conf.get_row_block_size();
		matrix_loc top_left(first_row_id, 0);
		size_t num_curr_row_blocks = std::min(num_row_blocks,
				(size_t) matrix_conf.get_rb_steal_io_size());
		size_t num_rows = std::min(tot_num_rows,
				(size_t) num_curr_row_blocks * matrix_conf.get_row_block_size());
		off_t first_row_offset = blocks->at(first_row_block).get_offset();
		size_t size = blocks->at(first_row_block + num_curr_row_blocks).get_offset()
			- first_row_offset;
		matrix_io ret(top_left, num_rows,
				tot_num_cols, safs::data_loc_t(file_id, first_row_offset), size);
		first_row_block += num_curr_row_blocks;
		num_row_blocks -= num_curr_row_blocks;
		tot_num_rows -= num_rows;
		return ret;
	}

	bool has_data() const {
		return num_row_blocks > 0;
	}
};

/*
 * The I/O generator that access a matrix on disks by rows.
 * It dynamically assigns a row block to a thread each time and thus balances
 * the load automatically.
 */
class dyn_row_iogen: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	// The current offset in the row_block vector.
	volatile off_t curr_io_off;
	int file_id;
	size_t tot_num_cols;

	pthread_spinlock_t lock;
public:
	dyn_row_iogen(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, const row_block_mapper &mapper);

	/*
	 * This method is called by the worker thread that owns the I/O generator
	 * to get I/O requests.
	 */
	virtual matrix_io get_next_io() {
		matrix_io ret;
		pthread_spin_lock(&lock);
		if ((size_t) curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off++].get_io(tot_num_cols, file_id);
			assert(ret.is_valid());
		}
		pthread_spin_unlock(&lock);
		return ret;
	}

	virtual bool has_next_io() {
		// The last entry in the row_block vector is the size of the matrix
		// file.
		return (size_t) curr_io_off < ios.size();
	}
};

dyn_row_iogen::dyn_row_iogen(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id,
		const row_block_mapper &mapper)
{
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		size_t num_row_blocks = mapper.get_range(i).num;
		off_t rb_off = mapper.get_range(i).idx;
		size_t num_rows = std::min(num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - rb_off * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, rb_off, num_row_blocks, num_rows);
	}
	curr_io_off = 0;
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
}

/*
 * The I/O generator that access a matrix on disks by rows.
 * This assigns a row block to a thread statically, so it can't balance the load.
 * This is for testing purpose only.
 */
class static_row_iogen: public matrix_io_generator
{
	std::vector<large_row_io> ios;
	int file_id;
	size_t tot_num_cols;
	size_t num_threads;
	// The current offset in the row_block vector for each thread.
	std::vector<size_t> curr_io_offs;
public:
	static_row_iogen(const std::vector<row_block> &_blocks, size_t tot_num_rows,
			size_t tot_num_cols, int file_id, const row_block_mapper &mapper);

	/*
	 * This method is called by the worker thread that owns the I/O generator
	 * to get I/O requests.
	 */
	virtual matrix_io get_next_io() {
		matrix_io ret;
		int thread_id = detail::mem_thread_pool::get_curr_thread_id();
		size_t curr_io_off = curr_io_offs[thread_id];
		if (curr_io_off < ios.size()) {
			assert(ios[curr_io_off].has_data());
			ret = ios[curr_io_off].get_io(tot_num_cols, file_id);
			// This is the easiest way of assign row blocks to threads.
			curr_io_offs[thread_id] += num_threads;
			assert(ret.is_valid());
		}
		return ret;
	}

	virtual bool has_next_io() {
		int thread_id = detail::mem_thread_pool::get_curr_thread_id();
		return curr_io_offs[thread_id] < ios.size();
	}
};

static_row_iogen::static_row_iogen(const std::vector<row_block> &blocks,
		size_t tot_num_rows, size_t tot_num_cols, int file_id,
		const row_block_mapper &mapper)
{
	// blocks[blocks.size() - 1] is an empty block. It only indicates
	// the end of the matrix file.
	// blocks[blocks.size() - 2] is the last row block. It's possible that
	// it's smaller than the full-size row block.
	for (size_t i = 0; i < mapper.get_num_ranges(); i++) {
		size_t num_row_blocks = mapper.get_range(i).num;
		off_t rb_off = mapper.get_range(i).idx;
		size_t num_rows = std::min(
				num_row_blocks * matrix_conf.get_row_block_size(),
				tot_num_rows - rb_off * matrix_conf.get_row_block_size());
		ios.emplace_back(blocks, rb_off, num_row_blocks, num_rows);
	}
	this->tot_num_cols = tot_num_cols;
	this->file_id = file_id;
	this->num_threads = detail::mem_thread_pool::get_global_num_threads();
	curr_io_offs.resize(num_threads);
	for (size_t i = 0; i < curr_io_offs.size(); i++)
		curr_io_offs[i] = i;
}

/*
 * The I/O generator for accessing 2D-partitioned blocks.
 * A generated I/O request may access multiple 2D-partitioned blocks.
 * Each I/O generator still accesses all blocks in a block row.
 */
class b2d_io_generator: public matrix_io_generator
{
	pthread_spinlock_t lock;
	size_t brow_idx;
	size_t min_num_brows;
	size_t io_num_brows;
	// This is the starting point where we give a single block row for
	// each assignment for load balancing. This points to a block row.
	size_t balance_point;

	SpM_2d_index::ptr idx;
	block_2d_size block_size;
	int file_id;
	size_t tot_num_cols;
public:
	b2d_io_generator(SpM_2d_index::ptr idx, int file_id, size_t io_num_brows,
			size_t min_num_brows);

	virtual matrix_io get_next_io();

	virtual bool has_next_io() {
		return brow_idx < idx->get_num_block_rows();
	}
};

b2d_io_generator::b2d_io_generator(SpM_2d_index::ptr idx, int file_id,
		size_t io_num_brows, size_t min_num_brows): block_size(
			idx->get_header().get_2d_block_size())
{
	this->idx = idx;
	this->io_num_brows = io_num_brows;
	this->min_num_brows = min_num_brows;
	if (io_num_brows > min_num_brows) {
		size_t num_threads = detail::mem_thread_pool::get_global_num_threads();
		// We reserve some block rows in the matrix that are assigned one blow
		// row at a time.
		if (idx->get_num_block_rows() > io_num_brows * num_threads)
			balance_point = idx->get_num_block_rows() - num_threads;
		else
			balance_point = 0;
	}
	else
		balance_point = idx->get_num_block_rows();
	this->tot_num_cols = idx->get_header().get_num_cols();
	this->file_id = file_id;
	this->brow_idx = 0;
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
}

matrix_io b2d_io_generator::get_next_io()
{
	matrix_io ret;
	pthread_spin_lock(&lock);
	// It's possible that all IOs have been stolen.
	// We have to check it.
	if (has_next_io()) {
		// If we have passed the balancing point, we now assign one block row
		// to a thread each time.
		if (brow_idx >= balance_point)
			io_num_brows = min_num_brows;

		matrix_loc mat_loc(brow_idx * block_size.get_num_rows(), 0);
		safs::data_loc_t data_loc(file_id, idx->get_block_row_off(brow_idx));
		size_t num_brows = std::min(io_num_brows,
				idx->get_num_block_rows() - brow_idx);
		size_t brow_size = idx->get_block_row_off(brow_idx
				+ num_brows) - idx->get_block_row_off(brow_idx);
		ret = matrix_io(mat_loc, block_size.get_num_rows() * num_brows,
				tot_num_cols, data_loc, brow_size);
		brow_idx += num_brows;
	}
	pthread_spin_unlock(&lock);
	return ret;
}

matrix_io_generator::ptr matrix_io_generator::create(
		const std::vector<row_block> &_blocks, size_t tot_num_rows,
		size_t tot_num_cols, int file_id, const row_block_mapper &mapper)
{
	return matrix_io_generator::ptr(new dyn_row_iogen(_blocks,
				tot_num_rows, tot_num_cols, file_id, mapper));
}

matrix_io_generator::ptr matrix_io_generator::create(SpM_2d_index::ptr idx,
		int file_id, size_t io_num_brows, size_t min_num_brows)
{
	return matrix_io_generator::ptr(new b2d_io_generator(idx, file_id,
				io_num_brows, min_num_brows));
}

void row_block_mapper::init(size_t num_rbs, size_t range_size)
{
	// We now need to jump to the next row block that belongs to
	// the current I/O generator.
	for (size_t i = 0; i < num_rbs; i += range_size) {
		struct rb_range range;
		range.idx = i;
		range.num = std::min(range_size, num_rbs - i);
		ranges.push_back(range);
	}
}

row_block_mapper::row_block_mapper(const SpM_2d_index &index, size_t range_size)
{
	init(index.get_num_block_rows(), range_size);
}

}
<|endoftext|>


<commit_before><commit_msg>first stab at handling table[] all range<commit_after><|endoftext|>


<commit_before><commit_msg>added Latvian "LVL" to EUROCONVERT(), fdo#73239<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rangeseq.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:48:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifdef PCH
#include "core_pch.hxx"
#endif

#pragma hdrstop

#include <svtools/zforlist.hxx>
#include <rtl/math.hxx>
#include <tools/debug.hxx>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>

#include "rangeseq.hxx"
#include "document.hxx"
#include "scmatrix.hxx"
#include "cell.hxx"

using namespace com::sun::star;

//------------------------------------------------------------------------

long lcl_DoubleToLong( double fVal )
{
    double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
                                  ::rtl::math::approxCeil( fVal );
    if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
        return (long)fInt;
    else
        return 0;       // out of range
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
                ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( static_cast<sal_Int32>(nColCount) );
        INT32* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0;
            else
                pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = pDoc->GetValue(
                ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<double> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( static_cast<sal_Int32>(nColCount) );
        double* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0.0;
            else
                pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            pDoc->GetString( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab, aDocStr );
            pColAry[nCol] = rtl::OUString( aDocStr );
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
                                            SvNumberFormatter* pFormatter )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( static_cast<sal_Int32>(nColCount) );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
        {
            String aStr;
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
            }
            else if ( pFormatter )
            {
                double fVal = pMatrix->GetDouble( nCol, nRow );
                Color* pColor;
                pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
            }
            pColAry[nCol] = rtl::OUString( aStr );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

double lcl_GetValueFromCell( ScBaseCell& rCell )
{
    //! ScBaseCell member function?

    CellType eType = rCell.GetCellType();
    if ( eType == CELLTYPE_VALUE )
        return ((ScValueCell&)rCell).GetValue();
    else if ( eType == CELLTYPE_FORMULA )
        return ((ScFormulaCell&)rCell).GetValue();      // called only if result is value

    DBG_ERROR( "GetValueFromCell: wrong type" );
    return 0;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange,
                                        BOOL bAllowNV )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;
    BOOL bHasErrors = FALSE;

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            uno::Any& rElement = pColAry[nCol];

            ScAddress aPos( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab );
            ScBaseCell* pCell = pDoc->GetCell( aPos );
            if ( pCell )
            {
                if ( pCell->GetCellType() == CELLTYPE_FORMULA &&
                        ((ScFormulaCell*)pCell)->GetErrCode() != 0 )
                {
                    // if NV is allowed, leave empty for errors
                    bHasErrors = TRUE;
                }
                else if ( pCell->HasValueData() )
                    rElement <<= (double) lcl_GetValueFromCell( *pCell );
                else
                    rElement <<= rtl::OUString( pCell->GetStringData() );
            }
            else
                rElement <<= rtl::OUString();       // empty: empty string
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return bAllowNV || !bHasErrors;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( static_cast<sal_Int32>(nColCount) );
        uno::Any* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
        {
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                String aStr;
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
                pColAry[nCol] <<= rtl::OUString( aStr );
            }
            else
                pColAry[nCol] <<= (double) pMatrix->GetDouble( nCol, nRow );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScByteSequenceToString::GetString( String& rString, const uno::Any& rAny,
                                        sal_uInt16 nEncoding )
{
    uno::Sequence<sal_Int8> aSeq;
    if ( rAny >>= aSeq )
    {
        rString = String( (const sal_Char*)aSeq.getConstArray(),
                            (xub_StrLen)aSeq.getLength(), nEncoding );
        rString.EraseTrailingChars( (sal_Unicode) 0 );
        return TRUE;
    }
    return FALSE;
}

//------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS pchfix01 (1.6.216); FILE MERGED 2006/07/12 10:01:45 kaib 1.6.216.1: #i67080# Converted cxx files in sc, added initial project level pch and stripped old PCH definitions.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rangeseq.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-07-21 11:41:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include <svtools/zforlist.hxx>
#include <rtl/math.hxx>
#include <tools/debug.hxx>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>

#include "rangeseq.hxx"
#include "document.hxx"
#include "scmatrix.hxx"
#include "cell.hxx"

using namespace com::sun::star;

//------------------------------------------------------------------------

long lcl_DoubleToLong( double fVal )
{
    double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
                                  ::rtl::math::approxCeil( fVal );
    if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
        return (long)fInt;
    else
        return 0;       // out of range
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( nColCount );
        INT32* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
                ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<INT32> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<INT32> aColSeq( static_cast<sal_Int32>(nColCount) );
        INT32* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0;
            else
                pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( nColCount );
        double* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
            pColAry[nCol] = pDoc->GetValue(
                ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<double> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<double>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<double> aColSeq( static_cast<sal_Int32>(nColCount) );
        double* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
            if ( pMatrix->IsString( nCol, nRow ) )
                pColAry[nCol] = 0.0;
            else
                pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( nColCount );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            pDoc->GetString( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab, aDocStr );
            pColAry[nCol] = rtl::OUString( aDocStr );
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;        //! check for errors
}

BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
                                            SvNumberFormatter* pFormatter )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<rtl::OUString> aColSeq( static_cast<sal_Int32>(nColCount) );
        rtl::OUString* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
        {
            String aStr;
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
            }
            else if ( pFormatter )
            {
                double fVal = pMatrix->GetDouble( nCol, nRow );
                Color* pColor;
                pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
            }
            pColAry[nCol] = rtl::OUString( aStr );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

double lcl_GetValueFromCell( ScBaseCell& rCell )
{
    //! ScBaseCell member function?

    CellType eType = rCell.GetCellType();
    if ( eType == CELLTYPE_VALUE )
        return ((ScValueCell&)rCell).GetValue();
    else if ( eType == CELLTYPE_FORMULA )
        return ((ScFormulaCell&)rCell).GetValue();      // called only if result is value

    DBG_ERROR( "GetValueFromCell: wrong type" );
    return 0;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange,
                                        BOOL bAllowNV )
{
    SCTAB nTab = rRange.aStart.Tab();
    SCCOL nStartCol = rRange.aStart.Col();
    SCROW nStartRow = rRange.aStart.Row();
    long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
    long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();

    String aDocStr;
    BOOL bHasErrors = FALSE;

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (long nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( nColCount );
        uno::Any* pColAry = aColSeq.getArray();
        for (long nCol = 0; nCol < nColCount; nCol++)
        {
            uno::Any& rElement = pColAry[nCol];

            ScAddress aPos( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab );
            ScBaseCell* pCell = pDoc->GetCell( aPos );
            if ( pCell )
            {
                if ( pCell->GetCellType() == CELLTYPE_FORMULA &&
                        ((ScFormulaCell*)pCell)->GetErrCode() != 0 )
                {
                    // if NV is allowed, leave empty for errors
                    bHasErrors = TRUE;
                }
                else if ( pCell->HasValueData() )
                    rElement <<= (double) lcl_GetValueFromCell( *pCell );
                else
                    rElement <<= rtl::OUString( pCell->GetStringData() );
            }
            else
                rElement <<= rtl::OUString();       // empty: empty string
        }
        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return bAllowNV || !bHasErrors;
}

BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix )
{
    if (!pMatrix)
        return FALSE;

    SCSIZE nColCount;
    SCSIZE nRowCount;
    pMatrix->GetDimensions( nColCount, nRowCount );

    uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
    uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
    for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
    {
        uno::Sequence<uno::Any> aColSeq( static_cast<sal_Int32>(nColCount) );
        uno::Any* pColAry = aColSeq.getArray();
        for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
        {
            if ( pMatrix->IsString( nCol, nRow ) )
            {
                String aStr;
                if ( !pMatrix->IsEmpty( nCol, nRow ) )
                    aStr = pMatrix->GetString( nCol, nRow );
                pColAry[nCol] <<= rtl::OUString( aStr );
            }
            else
                pColAry[nCol] <<= (double) pMatrix->GetDouble( nCol, nRow );
        }

        pRowAry[nRow] = aColSeq;
    }

    rAny <<= aRowSeq;
    return TRUE;
}

//------------------------------------------------------------------------

BOOL ScByteSequenceToString::GetString( String& rString, const uno::Any& rAny,
                                        sal_uInt16 nEncoding )
{
    uno::Sequence<sal_Int8> aSeq;
    if ( rAny >>= aSeq )
    {
        rString = String( (const sal_Char*)aSeq.getConstArray(),
                            (xub_StrLen)aSeq.getLength(), nEncoding );
        rString.EraseTrailingChars( (sal_Unicode) 0 );
        return TRUE;
    }
    return FALSE;
}

//------------------------------------------------------------------------

<|endoftext|>