LCOV - code coverage report
Current view: top level - filter/source/flash - swfwriter1.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 891 0.0 %
Date: 2012-08-25 Functions: 0 37 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <com/sun/star/i18n/ScriptType.hpp>
      31                 :            : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      32                 :            : #include <comphelper/processfactory.hxx>
      33                 :            : #include "swfwriter.hxx"
      34                 :            : #include <vcl/metaact.hxx>
      35                 :            : #include <vcl/gdimtf.hxx>
      36                 :            : #include <vcl/bmpacc.hxx>
      37                 :            : #include <vcl/virdev.hxx>
      38                 :            : #include <vcl/metric.hxx>
      39                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      40                 :            : #include <svtools/filter.hxx>
      41                 :            : #include <vcl/graphictools.hxx>
      42                 :            : #include <vcl/rendergraphicrasterizer.hxx>
      43                 :            : 
      44                 :            : #ifndef _ZLIB_H
      45                 :            : #ifdef SYSTEM_ZLIB
      46                 :            : #include <zlib.h>
      47                 :            : #else
      48                 :            : #include <external/zlib/zlib.h>
      49                 :            : #endif
      50                 :            : #endif
      51                 :            : 
      52                 :            : #include <vcl/salbtype.hxx>
      53                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      54                 :            : #include <basegfx/polygon/b2dpolypolygon.hxx>
      55                 :            : 
      56                 :            : using namespace ::swf;
      57                 :            : using namespace ::std;
      58                 :            : using namespace ::rtl;
      59                 :            : using namespace ::com::sun::star::i18n;
      60                 :            : using namespace ::com::sun::star::uno;
      61                 :            : using namespace ::com::sun::star::lang;
      62                 :            : using namespace ::com::sun::star::io;
      63                 :            : using namespace ::com::sun::star::beans;
      64                 :            : 
      65                 :            : extern sal_uInt16 getMaxBitsUnsigned( sal_uInt32 nValue );
      66                 :            : extern sal_uInt16 getMaxBitsSigned( sal_Int32 nValue );
      67                 :            : 
      68                 :          0 : static MapMode aTWIPSMode( MAP_TWIP );
      69                 :          0 : static MapMode a100thmmMode( MAP_100TH_MM );
      70                 :            : 
      71                 :            : // -----------------------------------------------------------------------------
      72                 :            : 
      73                 :          0 : Point Writer::map( const Point& rPoint ) const
      74                 :            : {
      75                 :          0 :     const MapMode& aSourceMapMode = mpVDev->GetMapMode();
      76                 :            : 
      77                 :          0 :     Point retPoint = mpVDev->LogicToLogic( rPoint,  &aSourceMapMode, &aTWIPSMode );
      78                 :            : 
      79                 :            :     // AS: Produces a 'possible loss of data' warning that we can't fix without
      80                 :            :     //  hurting code readability.
      81                 :          0 :     retPoint.X() = (long)( retPoint.X() * mnDocXScale );
      82                 :          0 :     retPoint.Y() = (long)( retPoint.Y() * mnDocYScale );
      83                 :            : 
      84                 :          0 :     return retPoint;
      85                 :            : }
      86                 :            : 
      87                 :            : // -----------------------------------------------------------------------------
      88                 :            : 
      89                 :          0 : Size Writer::map( const Size& rSize ) const
      90                 :            : {
      91                 :          0 :     const MapMode& aSourceMapMode = mpVDev->GetMapMode();
      92                 :            : 
      93                 :          0 :     Size retSize = mpVDev->LogicToLogic( rSize,  &aSourceMapMode, &aTWIPSMode );
      94                 :            : 
      95                 :            :     // AS: Produces a 'possible loss of data' warning that we can't fix without
      96                 :            :     //  hurting code readability.
      97                 :          0 :     retSize.Width() = (long)( retSize.Width() * mnDocXScale );
      98                 :          0 :     retSize.Height() = (long)( retSize.Height() * mnDocYScale );
      99                 :            : 
     100                 :          0 :     return retSize;
     101                 :            : }
     102                 :            : 
     103                 :            : // -----------------------------------------------------------------------------
     104                 :            : 
     105                 :          0 : void Writer::map( PolyPolygon& rPolyPolygon ) const
     106                 :            : {
     107                 :          0 :     const sal_uInt16 nPolyCount = rPolyPolygon.Count();
     108                 :          0 :     if( nPolyCount )
     109                 :            :     {
     110                 :            :         sal_uInt16 nPoly, nPoint, nPointCount;
     111                 :          0 :         for( nPoly = 0; nPoly < nPolyCount; nPoly++ )
     112                 :            :         {
     113                 :          0 :             Polygon& rPoly = rPolyPolygon[nPoly];
     114                 :          0 :             nPointCount = rPoly.GetSize();
     115                 :            : 
     116                 :          0 :             for( nPoint = 0; nPoint < nPointCount; nPoint++ )
     117                 :            :             {
     118                 :          0 :                 rPoly[nPoint] = map( rPoly[nPoint] );
     119                 :            :             }
     120                 :            :         }
     121                 :            :     }
     122                 :          0 : }
     123                 :            : 
     124                 :            : // -----------------------------------------------------------------------------
     125                 :            : 
     126                 :          0 : sal_Int32 Writer::mapRelative( sal_Int32 n100thMM ) const
     127                 :            : {
     128                 :          0 :     MapMode aSourceMapMode( mpVDev->GetMapMode() );
     129                 :          0 :     aSourceMapMode.SetOrigin( Point() );
     130                 :            : 
     131                 :          0 :     sal_Int32 nTwips = mpVDev->LogicToLogic( Point( n100thMM, n100thMM ),  &aSourceMapMode, &aTWIPSMode ).X();
     132                 :          0 :     return nTwips;
     133                 :            : }
     134                 :            : 
     135                 :            : // -----------------------------------------------------------------------------
     136                 :            : 
     137                 :            : /**
     138                 :            : */
     139                 :          0 : void Writer::Impl_addPolygon( BitStream& rBits, const Polygon& rPoly, sal_Bool bFilled )
     140                 :            : {
     141                 :          0 :     Point aLastPoint( rPoly[0] );
     142                 :            : 
     143                 :          0 :     Impl_addShapeRecordChange( rBits, _Int16(aLastPoint.X()),_Int16(aLastPoint.Y()), bFilled );
     144                 :            : 
     145                 :          0 :     sal_uInt16 i = 0, nSize = rPoly.GetSize();
     146                 :            : 
     147                 :          0 :     double d = 16.0f;
     148                 :            : 
     149                 :            :     // points
     150                 :          0 :     while( ( i + 1 ) < nSize )
     151                 :            :     {
     152                 :          0 :         if( ( i + 3 ) < nSize )
     153                 :            :         {
     154                 :          0 :             PolyFlags P1( rPoly.GetFlags( i ) );
     155                 :          0 :             PolyFlags P4( rPoly.GetFlags( i + 3 ) );
     156                 :            : 
     157                 :          0 :             if( ( POLY_NORMAL == P1 || POLY_SMOOTH == P1 || POLY_SYMMTR == P1 ) &&
     158                 :          0 :                 ( POLY_CONTROL == rPoly.GetFlags( i + 1 ) ) &&
     159                 :          0 :                 ( POLY_CONTROL == rPoly.GetFlags( i + 2 ) ) &&
     160                 :            :                 ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) )
     161                 :            :             {
     162                 :            :                 Impl_quadBezierApprox( rBits, aLastPoint, d*d,
     163                 :          0 :                                       rPoly.GetPoint( i ).X(),   rPoly.GetPoint( i ).Y(),
     164                 :          0 :                                       rPoly.GetPoint( i+1 ).X(), rPoly.GetPoint( i+1 ).Y(),
     165                 :          0 :                                       rPoly.GetPoint( i+2 ).X(), rPoly.GetPoint( i+2 ).Y(),
     166                 :          0 :                                       rPoly.GetPoint( i+3 ).X(), rPoly.GetPoint( i+3 ).Y() );
     167                 :          0 :                 i += 3;
     168                 :          0 :                 continue;
     169                 :            :             }
     170                 :            :         }
     171                 :            : 
     172                 :          0 :         ++i;
     173                 :            : 
     174                 :          0 :         const Point aPolyPoint( rPoly[ i ] );
     175                 :          0 :         if( aPolyPoint != aLastPoint )
     176                 :            :         {
     177                 :          0 :             Impl_addStraightEdgeRecord( rBits, _Int16(aPolyPoint.X() - aLastPoint.X()),_Int16(aPolyPoint.Y() - aLastPoint.Y()));
     178                 :          0 :             aLastPoint = aPolyPoint;
     179                 :            :         }
     180                 :            :     }
     181                 :            : 
     182                 :          0 :     if( bFilled && (rPoly[0] != rPoly[nSize-1]))
     183                 :            :     {
     184                 :          0 :         const Point aPolyPoint( rPoly[ 0 ] );
     185                 :          0 :         if( aPolyPoint != aLastPoint )
     186                 :            :         {
     187                 :          0 :             Impl_addStraightEdgeRecord( rBits, _Int16(aPolyPoint.X() - aLastPoint.X()),_Int16(aPolyPoint.Y() - aLastPoint.Y()));
     188                 :            :         }
     189                 :            :     }
     190                 :          0 : }
     191                 :            : 
     192                 :            : // -----------------------------------------------------------------------------
     193                 :            : 
     194                 :            : /** exports a style change record with a move to (x,y) and depending on bFilled a line style 1 or fill style 1
     195                 :            : */
     196                 :          0 : void Writer::Impl_addShapeRecordChange( BitStream& rBits, sal_Int16 dx, sal_Int16 dy, sal_Bool bFilled )
     197                 :            : {
     198                 :          0 :     rBits.writeUB( 0, 1 );          // TypeFlag
     199                 :          0 :     rBits.writeUB( 0, 1 );          // StateNewStyles
     200                 :          0 :     rBits.writeUB( !bFilled, 1 );   // StateLineStyle
     201                 :          0 :     rBits.writeUB( 0, 1 );          // StateFillStyle0
     202                 :          0 :     rBits.writeUB( bFilled, 1 );        // StateFillStyle1
     203                 :          0 :     rBits.writeUB( 1, 1 );          // StateMoveTo
     204                 :            : 
     205                 :          0 :     sal_uInt16 nMoveBits = max( getMaxBitsSigned( dx ), getMaxBitsSigned( dy ) );
     206                 :            : 
     207                 :          0 :     rBits.writeUB( nMoveBits, 5 );  // Number of bits per value
     208                 :            :                                     // TODO: Optimize horizontal and vertical lines
     209                 :          0 :     rBits.writeSB( dx, nMoveBits ); // DeltaX
     210                 :          0 :     rBits.writeSB( dy, nMoveBits ); // DeltaY
     211                 :            : 
     212                 :          0 :     rBits.writeUB( 1, 1 );          // set FillStyle1 or LineStyle to 1
     213                 :          0 : }
     214                 :            : 
     215                 :            : // -----------------------------------------------------------------------------
     216                 :            : 
     217                 :            : /** exports a straight edge record
     218                 :            : */
     219                 :          0 : void Writer::Impl_addStraightEdgeRecord( BitStream& rBits, sal_Int16 dx, sal_Int16 dy )
     220                 :            : {
     221                 :          0 :     rBits.writeUB( 1, 1 );          // TypeFlag
     222                 :          0 :     rBits.writeUB( 1, 1 );          // StraightFlag
     223                 :            : 
     224                 :          0 :     sal_uInt16 nBits = max( getMaxBitsSigned( dx ), getMaxBitsSigned( dy ) );
     225                 :            : 
     226                 :          0 :     rBits.writeUB( nBits - 2, 4 );  // Number of bits per value
     227                 :            : 
     228                 :          0 :     if( (dx != 0) && (dy != 0) )
     229                 :            :     {
     230                 :          0 :         rBits.writeUB( 1, 1 );          // GeneralLineFlag
     231                 :          0 :         rBits.writeSB( dx, nBits );     // DeltaX
     232                 :          0 :         rBits.writeSB( dy, nBits );     // DeltaY
     233                 :            :     }
     234                 :            :     else
     235                 :            :     {
     236                 :          0 :         rBits.writeUB( 0, 1 );
     237                 :          0 :         rBits.writeUB( ( dx == 0 ), 1 );
     238                 :          0 :         if( dx == 0 )
     239                 :            :         {
     240                 :          0 :             rBits.writeSB( dy, nBits );     // DeltaY
     241                 :            :         }
     242                 :            :         else
     243                 :            :         {
     244                 :          0 :             rBits.writeSB( dx, nBits );     // DeltaX
     245                 :            :         }
     246                 :            :     }
     247                 :          0 : }
     248                 :            : 
     249                 :            : // -----------------------------------------------------------------------------
     250                 :            : 
     251                 :            : /** exports a curved edge record
     252                 :            : */
     253                 :          0 : void Writer::Impl_addCurvedEdgeRecord( BitStream& rBits, sal_Int16 control_dx, sal_Int16 control_dy, sal_Int16 anchor_dx, sal_Int16 anchor_dy )
     254                 :            : {
     255                 :          0 :     rBits.writeUB( 1, 1 );          // TypeFlag
     256                 :          0 :     rBits.writeUB( 0, 1 );          // CurvedFlag
     257                 :            : 
     258                 :            :     sal_uInt8 nBits = static_cast<sal_uInt8>(
     259                 :          0 :         max( getMaxBitsSigned( control_dx ),
     260                 :          0 :             max( getMaxBitsSigned( control_dy ),
     261                 :          0 :                 max( getMaxBitsSigned( anchor_dx ),
     262                 :          0 :                     max( getMaxBitsSigned( anchor_dy ), (sal_uInt16)3 ) ) ) ) );
     263                 :            : 
     264                 :          0 :     rBits.writeUB( nBits - 2, 4 );  // Number of bits per value
     265                 :            : 
     266                 :          0 :     rBits.writeSB( control_dx, nBits );     // DeltaX
     267                 :          0 :     rBits.writeSB( control_dy, nBits );     // DeltaY
     268                 :          0 :     rBits.writeSB( anchor_dx, nBits );      // DeltaX
     269                 :          0 :     rBits.writeSB( anchor_dy, nBits );      // DeltaY
     270                 :          0 : }
     271                 :            : 
     272                 :            : // -----------------------------------------------------------------------------
     273                 :            : 
     274                 :            : /** exports a end shape record
     275                 :            : */
     276                 :          0 : void Writer::Impl_addEndShapeRecord( BitStream& rBits )
     277                 :            : {
     278                 :          0 :     rBits.writeUB( 0, 6 );
     279                 :          0 : }
     280                 :            : 
     281                 :            : // -----------------------------------------------------------------------------
     282                 :            : 
     283                 :          0 : void Writer::Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled )
     284                 :            : {
     285                 :          0 :     PolyPolygon aPolyPoly( rPoly );
     286                 :          0 :     Impl_writePolyPolygon( aPolyPoly, bFilled );
     287                 :          0 : }
     288                 :            : 
     289                 :            : // -----------------------------------------------------------------------------
     290                 :            : 
     291                 :          0 : void Writer::Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor )
     292                 :            : {
     293                 :          0 :     PolyPolygon aPolyPoly( rPoly );
     294                 :          0 :     Impl_writePolyPolygon( aPolyPoly, bFilled, rFillColor, rLineColor );
     295                 :          0 : }
     296                 :            : 
     297                 :            : // -----------------------------------------------------------------------------
     298                 :            : 
     299                 :          0 : void Writer::Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, sal_uInt8 nTransparence /* = 0 */ )
     300                 :            : {
     301                 :          0 :     Color aLineColor( mpVDev->GetLineColor() );
     302                 :          0 :     if( 0 == aLineColor.GetTransparency() )
     303                 :          0 :         aLineColor.SetTransparency( nTransparence );
     304                 :          0 :     Color aFillColor( mpVDev->GetFillColor() );
     305                 :          0 :     if( 0 == aFillColor.GetTransparency() )
     306                 :          0 :         aFillColor.SetTransparency( nTransparence );
     307                 :          0 :     Impl_writePolyPolygon(rPolyPoly, bFilled, aFillColor, aLineColor );
     308                 :          0 : }
     309                 :            : 
     310                 :            : // -----------------------------------------------------------------------------
     311                 :            : 
     312                 :          0 : void Writer::Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor )
     313                 :            : {
     314                 :          0 :     PolyPolygon aPolyPoly( rPolyPoly );
     315                 :            : 
     316                 :          0 :     if( aPolyPoly.Count() )
     317                 :            :     {
     318                 :          0 :         map( aPolyPoly );
     319                 :            : 
     320                 :          0 :         if( mpClipPolyPolygon )
     321                 :          0 :             rPolyPoly.GetIntersection( *mpClipPolyPolygon, aPolyPoly );
     322                 :            : 
     323                 :            :         sal_uInt16 nID;
     324                 :          0 :         if( bFilled )
     325                 :            :         {
     326                 :          0 :             Color aFillColor( rFillColor );
     327                 :          0 :             if( 0 != mnGlobalTransparency )
     328                 :          0 :                 aFillColor.SetTransparency( mnGlobalTransparency );
     329                 :            : 
     330                 :          0 :             FillStyle aStyle( aFillColor );
     331                 :          0 :             nID = defineShape( aPolyPoly, aStyle );
     332                 :            :         }
     333                 :            :         else
     334                 :            :         {
     335                 :          0 :             Color aLineColor( rLineColor );
     336                 :          0 :             if( 0 != mnGlobalTransparency )
     337                 :          0 :                 aLineColor.SetTransparency( mnGlobalTransparency );
     338                 :            : 
     339                 :          0 :             nID = defineShape( aPolyPoly, 1, aLineColor );
     340                 :            :         }
     341                 :          0 :         maShapeIds.push_back( nID );
     342                 :          0 :     }
     343                 :          0 : }
     344                 :            : 
     345                 :            : // -----------------------------------------------------------------------------
     346                 :            : 
     347                 :            : /** a gradient is a transition from one color to another, rendered inside a given polypolygon */
     348                 :          0 : void Writer::Impl_writeGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient )
     349                 :            : {
     350                 :          0 :     if( rPolyPoly.Count() )
     351                 :            :     {
     352                 :          0 :         PolyPolygon aPolyPolygon( rPolyPoly );
     353                 :          0 :         map( aPolyPolygon );
     354                 :            : 
     355                 :          0 :         if( (rGradient.GetStyle() == GradientStyle_LINEAR && rGradient.GetAngle() == 900) || (rGradient.GetStyle() == GradientStyle_RADIAL)  )
     356                 :            :         {
     357                 :          0 :             const Rectangle aBoundRect( aPolyPolygon.GetBoundRect() );
     358                 :            : 
     359                 :          0 :             FillStyle aFillStyle( aBoundRect, rGradient );
     360                 :            : 
     361                 :          0 :             sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
     362                 :          0 :             maShapeIds.push_back( nShapeId );
     363                 :            :         }
     364                 :            :         else
     365                 :            :         {
     366                 :          0 :             setClipping( &aPolyPolygon );
     367                 :            : 
     368                 :            :             // render the gradient filling to simple polygons
     369                 :            :             {
     370                 :          0 :                 GDIMetaFile aTmpMtf;
     371                 :          0 :                 mpVDev->AddGradientActions( aPolyPolygon.GetBoundRect(), rGradient, aTmpMtf );
     372                 :          0 :                 Impl_writeActions( aTmpMtf );
     373                 :            :             }
     374                 :            : 
     375                 :          0 :             setClipping( NULL );
     376                 :          0 :         }
     377                 :            :     }
     378                 :          0 : }
     379                 :            : 
     380                 :            : // -----------------------------------------------------------------------------
     381                 :            : 
     382                 :          0 : void Writer::setClipping( const PolyPolygon* pClipPolyPolygon )
     383                 :            : {
     384                 :          0 :     mpClipPolyPolygon = pClipPolyPolygon;
     385                 :          0 : }
     386                 :            : 
     387                 :            : // -----------------------------------------------------------------------------
     388                 :            : 
     389                 :            : // AS: Just comparing fonts straight up is too literal.  There are some
     390                 :            : //  differences in font that actually require different glyphs to be defined,
     391                 :            : //  and some that don't.  This function is meant to capture all the differences
     392                 :            : //  that we care about.
     393                 :          0 : bool compare_fonts_for_me(const Font& rFont1, const Font& rFont2)
     394                 :            : {
     395                 :          0 :     return rFont1.GetName() == rFont2.GetName() &&
     396                 :          0 :             rFont1.GetWeight() == rFont2.GetWeight() &&
     397                 :          0 :             rFont1.GetItalic() == rFont2.GetItalic() &&
     398                 :          0 :             rFont1.IsOutline() == rFont2.IsOutline() &&
     399                 :          0 :             rFont1.IsShadow() == rFont2.IsShadow() &&
     400                 :          0 :             rFont1.GetRelief() == rFont2.GetRelief();
     401                 :            : }
     402                 :            : 
     403                 :            : // -----------------------------------------------------------------------------
     404                 :            : 
     405                 :          0 : FlashFont& Writer::Impl_getFont( const Font& rFont )
     406                 :            : {
     407                 :          0 :     FontMap::iterator aIter( maFonts.begin() );
     408                 :          0 :     const FontMap::iterator aEnd( maFonts.end() );
     409                 :            : 
     410                 :          0 :     for(; aIter != aEnd; ++aIter)
     411                 :            :     {
     412                 :          0 :         const Font tempFont = (*aIter)->getFont();
     413                 :          0 :         if( compare_fonts_for_me(tempFont, rFont) )
     414                 :            :         {
     415                 :          0 :             return **aIter;
     416                 :            :         }
     417                 :          0 :     }
     418                 :            : 
     419                 :          0 :     FlashFont* pFont = new FlashFont( rFont, createID() );
     420                 :          0 :     maFonts.push_back( pFont );
     421                 :          0 :     return *pFont;
     422                 :            : }
     423                 :            : 
     424                 :            : // -----------------------------------------------------------------------------
     425                 :            : 
     426                 :          0 : void Writer::Impl_writeText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth )
     427                 :            : {
     428                 :          0 :     const FontMetric aMetric( mpVDev->GetFontMetric() );
     429                 :            : 
     430                 :          0 :     bool bTextSpecial = aMetric.IsShadow() || aMetric.IsOutline() || (aMetric.GetRelief() != RELIEF_NONE);
     431                 :            : 
     432                 :          0 :     if( !bTextSpecial )
     433                 :            :     {
     434                 :          0 :         Impl_writeText( rPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     435                 :            :     }
     436                 :            :     else
     437                 :            :     {
     438                 :          0 :         if( aMetric.GetRelief() != RELIEF_NONE )
     439                 :            :         {
     440                 :          0 :             Color aReliefColor( COL_LIGHTGRAY );
     441                 :          0 :             Color aTextColor( mpVDev->GetTextColor() );
     442                 :            : 
     443                 :          0 :             if ( aTextColor.GetColor() == COL_BLACK )
     444                 :          0 :                 aTextColor = Color( COL_WHITE );
     445                 :            : 
     446                 :          0 :             if ( aTextColor.GetColor() == COL_WHITE )
     447                 :          0 :                 aReliefColor = Color( COL_BLACK );
     448                 :            : 
     449                 :            : 
     450                 :          0 :             Point aPos( rPos );
     451                 :          0 :             Point aOffset( 6,6 );
     452                 :            : 
     453                 :          0 :             if ( aMetric.GetRelief() == RELIEF_ENGRAVED )
     454                 :            :             {
     455                 :          0 :                 aPos -= aOffset;
     456                 :            :             }
     457                 :            :             else
     458                 :            :             {
     459                 :          0 :                 aPos += aOffset;
     460                 :            :             }
     461                 :            : 
     462                 :          0 :             Impl_writeText( aPos, rText, pDXArray, nWidth, aReliefColor );
     463                 :          0 :             Impl_writeText( rPos, rText, pDXArray, nWidth, aTextColor );
     464                 :            :         }
     465                 :            :         else
     466                 :            :         {
     467                 :          0 :             if( aMetric.IsShadow() )
     468                 :            :             {
     469                 :          0 :                 long nOff = 1 + ((aMetric.GetLineHeight()-24)/24);
     470                 :          0 :                 if ( aMetric.IsOutline() )
     471                 :          0 :                     nOff += 6;
     472                 :            : 
     473                 :          0 :                 Color aTextColor( mpVDev->GetTextColor() );
     474                 :          0 :                 Color aShadowColor = Color( COL_BLACK );
     475                 :            : 
     476                 :          0 :                 if ( (aTextColor.GetColor() == COL_BLACK) || (aTextColor.GetLuminance() < 8) )
     477                 :          0 :                     aShadowColor = Color( COL_LIGHTGRAY );
     478                 :            : 
     479                 :          0 :                 Point aPos( rPos );
     480                 :          0 :                 aPos += Point( nOff, nOff );
     481                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, aShadowColor );
     482                 :            : 
     483                 :          0 :                 if( !aMetric.IsOutline() )
     484                 :            :                 {
     485                 :          0 :                     Impl_writeText( rPos, rText, pDXArray, nWidth, aTextColor );
     486                 :            :                 }
     487                 :            :             }
     488                 :            : 
     489                 :          0 :             if( aMetric.IsOutline() )
     490                 :            :             {
     491                 :          0 :                 Point aPos = rPos + Point( -6, -6 );
     492                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     493                 :          0 :                 aPos = rPos + Point(+6,+6);
     494                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     495                 :          0 :                 aPos = rPos + Point(-6,+0);
     496                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     497                 :          0 :                 aPos = rPos + Point(-6,+6);
     498                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     499                 :          0 :                 aPos = rPos + Point(+0,+6);
     500                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     501                 :          0 :                 aPos = rPos + Point(+0,-6);
     502                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     503                 :          0 :                 aPos = rPos + Point(+6,-1);
     504                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     505                 :          0 :                 aPos = rPos + Point(+6,+0);
     506                 :          0 :                 Impl_writeText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
     507                 :            : 
     508                 :          0 :                 Impl_writeText( rPos, rText, pDXArray, nWidth, Color( COL_WHITE ) );
     509                 :            :             }
     510                 :            :         }
     511                 :          0 :     }
     512                 :          0 : }
     513                 :            : 
     514                 :          0 : void Writer::Impl_writeText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, Color aTextColor )
     515                 :            : {
     516                 :          0 :     sal_uInt32 nLen = rText.Len();
     517                 :            : 
     518                 :          0 :     if( !nLen )
     519                 :          0 :         return;
     520                 :            : 
     521                 :          0 :     const bool bRTL = (mpVDev->GetLayoutMode() & TEXT_LAYOUT_BIDI_RTL) != 0;
     522                 :            : 
     523                 :          0 :     sal_Int16 nScriptType = ScriptType::LATIN;
     524                 :          0 :     Reference < XBreakIterator > xBI( Impl_GetBreakIterator() );
     525                 :          0 :     if( xBI.is() )
     526                 :            :     {
     527                 :          0 :         const OUString oText( rText );
     528                 :          0 :         nScriptType = xBI->getScriptType( oText, 0 );
     529                 :            :     }
     530                 :            : 
     531                 :            :     // if the text is either right to left or complex or asian, we
     532                 :            :     // ask the output device for a polygon representation.
     533                 :            :     // On complex and asian text, each unicode character can have
     534                 :            :     // different glyph representation, based on context. Also positioning
     535                 :            :     // is not trivial so we let the output device do it for us.
     536                 :          0 :     if( bRTL || (nScriptType != ScriptType::LATIN) )
     537                 :            :     {
     538                 :            :         // todo: optimize me as this will generate a huge amount of duplicate polygons
     539                 :          0 :         PolyPolygon aPolyPoygon;
     540                 :          0 :         mpVDev->GetTextOutline( aPolyPoygon, rText, 0, 0, (sal_uInt16)nLen, sal_True, nWidth, pDXArray );
     541                 :          0 :         aPolyPoygon.Translate( rPos );
     542                 :          0 :         Impl_writePolyPolygon( aPolyPoygon, sal_True, aTextColor, aTextColor );
     543                 :            :     }
     544                 :            :     else
     545                 :            :     {
     546                 :          0 :         Size    aNormSize;
     547                 :            :         sal_Int32* pOwnArray;
     548                 :            :         sal_Int32* pDX;
     549                 :            : 
     550                 :            :         // get text sizes
     551                 :          0 :         if( pDXArray )
     552                 :            :         {
     553                 :          0 :             pOwnArray = NULL;
     554                 :          0 :             aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
     555                 :          0 :             pDX = (sal_Int32*) pDXArray;
     556                 :            :         }
     557                 :            :         else
     558                 :            :         {
     559                 :          0 :             pOwnArray = new sal_Int32[ nLen ];
     560                 :          0 :             aNormSize = Size( mpVDev->GetTextArray( rText, pOwnArray ), 0 );
     561                 :          0 :             pDX = pOwnArray;
     562                 :            :         }
     563                 :            : 
     564                 :          0 :         if( nLen > 1 )
     565                 :            :         {
     566                 :          0 :             aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( rtl::OUString(rText.GetChar((sal_uInt16) nLen - 1)) );
     567                 :            : 
     568                 :          0 :             if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
     569                 :            :             {
     570                 :          0 :                 const double fFactor = (double) nWidth / aNormSize.Width();
     571                 :            : 
     572                 :            :                 sal_uInt32 i;
     573                 :          0 :                 for( i = 0; i < ( nLen - 1 ); i++ )
     574                 :          0 :                     pDX[ i ] = FRound( pDX[ i ] * fFactor );
     575                 :            :             }
     576                 :            :         }
     577                 :            : 
     578                 :          0 :         Font aOldFont( mpVDev->GetFont() );
     579                 :          0 :         Point               aBaseLinePos( rPos );
     580                 :            : 
     581                 :          0 :         Font aFont(aOldFont);
     582                 :          0 :         short nOrientation = aFont.GetOrientation();
     583                 :          0 :         aFont.SetOrientation( 0 );
     584                 :          0 :         aFont.SetUnderline(UNDERLINE_NONE);
     585                 :          0 :         aFont.SetStrikeout(STRIKEOUT_NONE);
     586                 :          0 :         mpVDev->SetFont( aFont );
     587                 :            : 
     588                 :          0 :         const FontMetric    aMetric( mpVDev->GetFontMetric() );
     589                 :            : 
     590                 :          0 :         FlashFont&          rFlashFont = Impl_getFont( aFont );
     591                 :            : 
     592                 :            :         // always adjust text position to match baseline alignment
     593                 :          0 :         switch( aOldFont.GetAlign() )
     594                 :            :         {
     595                 :            :             case( ALIGN_TOP ):
     596                 :          0 :                 aBaseLinePos.Y() += aMetric.GetAscent();
     597                 :          0 :             break;
     598                 :            : 
     599                 :            :             case( ALIGN_BOTTOM ):
     600                 :          0 :                 aBaseLinePos.Y() -= aMetric.GetDescent();
     601                 :          0 :             break;
     602                 :            : 
     603                 :            :             default:
     604                 :          0 :             break;
     605                 :            :         }
     606                 :            : 
     607                 :            :         // get mapped text position
     608                 :          0 :         const Point aPt( map( aBaseLinePos ) );
     609                 :            : 
     610                 :            :         // write text element
     611                 :            : 
     612                 :            : #if 0 // makes the calculated bound rect visible for debuging
     613                 :            : {
     614                 :            :         Polygon aTmpPoly( aPoly );
     615                 :            :         sal_uInt16 nID = FlashGeometryExporter::writePolygonShape( aMovieStream, aTmpPoly, false, Color(COL_MAGENTA), Color(COL_MAGENTA), mpClipPolyPolygon  );
     616                 :            :         ImplPlaceObject( nID );
     617                 :            : }
     618                 :            : #endif
     619                 :            : 
     620                 :            :         // CL: This is still a hack until we figure out how to calculate a correct bound rect
     621                 :            :         //     for rotatet text
     622                 :          0 :         Rectangle textBounds( 0, 0, static_cast<long>(mnDocWidth*mnDocXScale), static_cast<long>(mnDocHeight*mnDocYScale) );
     623                 :          0 :         double scale = 1.0;
     624                 :            : 
     625                 :            :         // scale width if we have a stretched text
     626                 :          0 :         if( 0 != aFont.GetSize().Width() )
     627                 :            :         {
     628                 :          0 :             Font aTmpFont( aFont );
     629                 :          0 :             aTmpFont.SetWidth(0);
     630                 :          0 :             mpVDev->SetFont( aTmpFont );
     631                 :            : 
     632                 :          0 :             const FontMetric aMetric2( mpVDev->GetFontMetric() );
     633                 :          0 :             mpVDev->SetFont( aFont );
     634                 :            : 
     635                 :          0 :             const long n1 = aFont.GetSize().Width();
     636                 :          0 :             const long n2 = aMetric2.GetSize().Width();
     637                 :          0 :             scale =  (double)n1 / (double)n2;
     638                 :            :         }
     639                 :            : 
     640                 :          0 :         basegfx::B2DHomMatrix m(basegfx::tools::createRotateB2DHomMatrix(static_cast<double>(nOrientation) * F_PI1800));
     641                 :          0 :         m.translate( double(aPt.X() / scale), double(aPt.Y()) );
     642                 :          0 :         m.scale( scale, scale );
     643                 :            : 
     644                 :          0 :         sal_Int16 nHeight = _Int16( map( Size( 0, aFont.GetHeight() ) ).Height() );
     645                 :            : 
     646                 :          0 :         startTag( TAG_DEFINETEXT );
     647                 :            : 
     648                 :          0 :         sal_uInt16 nTextId = createID();
     649                 :            : 
     650                 :          0 :         mpTag->addUI16( nTextId );
     651                 :          0 :         mpTag->addRect( textBounds );
     652                 :          0 :         mpTag->addMatrix( m );
     653                 :            : 
     654                 :          0 :         sal_uInt8 nGlyphBits = 16;
     655                 :          0 :         sal_uInt8 nAdvanceBits = 16;
     656                 :            : 
     657                 :          0 :         mpTag->addUI8( nGlyphBits );
     658                 :          0 :         mpTag->addUI8( nAdvanceBits );
     659                 :            : 
     660                 :            :         // text style change record
     661                 :          0 :         mpTag->addUI8( 0x8c );
     662                 :          0 :         mpTag->addUI16( rFlashFont.getID() );
     663                 :          0 :         mpTag->addRGB( aTextColor );
     664                 :          0 :         mpTag->addUI16( _uInt16( nHeight ) );
     665                 :            : 
     666                 :            :         DBG_ASSERT( nLen <= 127, "TODO: handle text with more than 127 characters" );
     667                 :            : 
     668                 :            :         // Glyph record
     669                 :          0 :         mpTag->addUI8( (sal_uInt8) nLen );
     670                 :            : 
     671                 :          0 :         BitStream aBits;
     672                 :            : 
     673                 :          0 :         sal_Int32 nLastDX = 0;
     674                 :            :         sal_Int32 nAdvance;
     675                 :            :         sal_uInt32 i;
     676                 :          0 :         for( i = 0; i < nLen; i++  )
     677                 :            :         {
     678                 :          0 :             if( i < (nLen-1) )
     679                 :            :             {
     680                 :          0 :                 nAdvance = pDX[i] - nLastDX;
     681                 :          0 :                 nLastDX = pDX[i];
     682                 :            :             }
     683                 :            :             else
     684                 :            :             {
     685                 :          0 :                 nAdvance = 0;
     686                 :            :             }
     687                 :            : 
     688                 :          0 :             aBits.writeUB( rFlashFont.getGlyph(rText.GetChar(_uInt16(i)),mpVDev), nGlyphBits );
     689                 :          0 :             aBits.writeSB( _Int16(map( Size( (long)( nAdvance / scale ), 0 ) ).Width() ), nAdvanceBits );
     690                 :            :         }
     691                 :            : 
     692                 :          0 :         mpTag->addBits( aBits );
     693                 :          0 :         mpTag->addUI8( 0 );
     694                 :            : 
     695                 :          0 :         endTag();
     696                 :            : 
     697                 :          0 :         maShapeIds.push_back( nTextId );
     698                 :            : 
     699                 :            :         // AS: Write strikeout and underline, if neccessary.  This code was originally taken from the SVG
     700                 :            :         //  export facility, although the positioning had to be tweaked a little.  I can't explain the
     701                 :            :         //  numbers, but the flash lines up very well with the original OOo document.  All of this should
     702                 :            :         //  probably be converted to polygons as part of the meta file, though, as we don't handle any
     703                 :            :         //  fancy lines (like dashes).
     704                 :          0 :         if( ( aOldFont.GetStrikeout() != STRIKEOUT_NONE ) || ( aOldFont.GetUnderline() != UNDERLINE_NONE ) )
     705                 :            :         {
     706                 :          0 :             Polygon     aPoly( 4 );
     707                 :          0 :             const long  nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
     708                 :            : 
     709                 :          0 :             if( aOldFont.GetStrikeout() != STRIKEOUT_NONE )
     710                 :            :             {
     711                 :          0 :                 aPoly[ 0 ].X() = aBaseLinePos.X();
     712                 :          0 :                 aPoly[ 0 ].Y() = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 ) - nLineHeight;
     713                 :          0 :                 aPoly[ 1 ].X() = aPoly[ 0 ].X() + aNormSize.Width() - 1;
     714                 :          0 :                 aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
     715                 :          0 :                 aPoly[ 2 ].X() = aPoly[ 1 ].X();
     716                 :          0 :                 aPoly[ 2 ].Y() = aPoly[ 1 ].Y() + nLineHeight - 1;
     717                 :          0 :                 aPoly[ 3 ].X() = aPoly[ 0 ].X();
     718                 :          0 :                 aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
     719                 :            : 
     720                 :          0 :                 Impl_writePolygon( aPoly, sal_True, aTextColor, aTextColor );
     721                 :            :             }
     722                 :            : 
     723                 :            :             // AS: The factor of 1.5 on the nLineHeight is a magic number.  I'm not sure why it works,
     724                 :            :             //  but it looks good to me.
     725                 :          0 :             if( aOldFont.GetUnderline() != UNDERLINE_NONE )
     726                 :            :             {
     727                 :          0 :                 aPoly[ 0 ].X() = aBaseLinePos.X();
     728                 :          0 :                 aPoly[ 0 ].Y() = static_cast<long>(aBaseLinePos.Y() + 1.5*nLineHeight);
     729                 :          0 :                 aPoly[ 1 ].X() = aPoly[ 0 ].X() + aNormSize.Width() - 1;
     730                 :          0 :                 aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
     731                 :          0 :                 aPoly[ 2 ].X() = aPoly[ 1 ].X();
     732                 :          0 :                 aPoly[ 2 ].Y() = aPoly[ 1 ].Y() + nLineHeight - 1;
     733                 :          0 :                 aPoly[ 3 ].X() = aPoly[ 0 ].X();
     734                 :          0 :                 aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
     735                 :            : 
     736                 :          0 :                 Impl_writePolygon( aPoly, sal_True, aTextColor, aTextColor );
     737                 :          0 :             }
     738                 :            :         }
     739                 :            : 
     740                 :          0 :         mpVDev->SetFont( aOldFont );
     741                 :          0 :         delete[] pOwnArray;
     742                 :          0 :     }
     743                 :            : }
     744                 :            : 
     745                 :            : // -----------------------------------------------------------------------------
     746                 :            : // AS: Because JPEGs require the alpha channel provided seperately (JPEG does not
     747                 :            : //  natively support alpha channel, but SWF lets you provide it seperately), we
     748                 :            : //  extract the alpha channel into a seperate array here.
     749                 :          0 : void getBitmapData( const BitmapEx& aBmpEx, sal_uInt8*& tgadata, sal_uInt8*& tgaAlphadata, sal_uInt32& nWidth, sal_uInt32& nHeight )
     750                 :            : {
     751                 :          0 :     if( !aBmpEx.IsEmpty() )
     752                 :            :     {
     753                 :          0 :         Bitmap              aBmp( aBmpEx.GetBitmap() );
     754                 :          0 :         BitmapReadAccess*   pRAcc = aBmp.AcquireReadAccess();
     755                 :            : 
     756                 :          0 :         if( pRAcc )
     757                 :            :         {
     758                 :          0 :             AlphaMask   aAlpha;
     759                 :          0 :             nWidth = pRAcc->Width();
     760                 :          0 :             nHeight = pRAcc->Height();
     761                 :          0 :             tgadata = new sal_uInt8[nWidth*nHeight*4];
     762                 :          0 :             tgaAlphadata = new sal_uInt8[nWidth*nHeight];
     763                 :          0 :             sal_uInt8* p = tgadata, *pAlpha = tgaAlphadata;
     764                 :            : 
     765                 :            : 
     766                 :          0 :             if( aBmpEx.IsAlpha() )
     767                 :          0 :                 aAlpha = aBmpEx.GetAlpha();
     768                 :          0 :             else if( aBmpEx.IsTransparent() )
     769                 :          0 :                 aAlpha = aBmpEx.GetMask();
     770                 :            :             else
     771                 :            :             {
     772                 :          0 :                 sal_uInt8 cAlphaVal = 0;
     773                 :          0 :                 aAlpha = AlphaMask( aBmp.GetSizePixel(), &cAlphaVal );
     774                 :            :             }
     775                 :            : 
     776                 :          0 :             BitmapReadAccess* pAAcc = aAlpha.AcquireReadAccess();
     777                 :            : 
     778                 :          0 :             if( pAAcc )
     779                 :            :             {
     780                 :          0 :                 for( sal_uInt32 nY = 0; nY < nHeight; nY++ )
     781                 :            :                 {
     782                 :          0 :                     for( sal_uInt32 nX = 0; nX < nWidth; nX++ )
     783                 :            :                     {
     784                 :          0 :                         const sal_uInt8     nAlpha = pAAcc->GetPixel( nY, nX ).GetIndex();
     785                 :          0 :                         const BitmapColor   aPixelColor( pRAcc->GetColor( nY, nX ) );
     786                 :            : 
     787                 :          0 :                         if( nAlpha == 0xff )
     788                 :            :                         {
     789                 :          0 :                             *p++ = 0;
     790                 :          0 :                             *p++ = 0;
     791                 :          0 :                             *p++ = 0;
     792                 :          0 :                             *p++ = 0;
     793                 :            :                         }
     794                 :            :                         else
     795                 :            :                         {
     796                 :          0 :                             *p++ = 0xff-nAlpha;
     797                 :          0 :                             *p++ = aPixelColor.GetRed();
     798                 :          0 :                             *p++ = aPixelColor.GetGreen();
     799                 :          0 :                             *p++ = aPixelColor.GetBlue();
     800                 :            :                         }
     801                 :          0 :                         *pAlpha++ = 0xff - nAlpha;
     802                 :          0 :                     }
     803                 :            :                 }
     804                 :            : 
     805                 :          0 :                 aAlpha.ReleaseAccess( pAAcc );
     806                 :            :             }
     807                 :            : 
     808                 :          0 :             aBmp.ReleaseAccess( pRAcc );
     809                 :          0 :         }
     810                 :            :     }
     811                 :          0 : }
     812                 :            : 
     813                 :            : // -----------------------------------------------------------------------------
     814                 :          0 : sal_uInt16 Writer::defineBitmap( const BitmapEx &bmpSource, sal_Int32 nJPEGQualityLevel )
     815                 :            : {
     816                 :          0 :     sal_uLong bmpChecksum = bmpSource.GetChecksum();
     817                 :            : 
     818                 :          0 :     ChecksumCache::iterator it = mBitmapCache.find(bmpChecksum);
     819                 :            : 
     820                 :            :     // AS: We already exported this bitmap, so just return its ID.
     821                 :          0 :     if (mBitmapCache.end() != it)
     822                 :          0 :         return it->second;
     823                 :            : 
     824                 :          0 :     sal_uInt16 nBitmapId = createID();
     825                 :          0 :     mBitmapCache[bmpChecksum] = nBitmapId;
     826                 :            : 
     827                 :            :     // AS: OK, we have a good image, so now we decide whether or not to JPEG it or
     828                 :            :     //  or Lossless compress it.
     829                 :            : 
     830                 :            :     //Figure out lossless size
     831                 :            :     sal_uInt8 *pImageData, *pAlphaData;
     832                 :            :     sal_uInt32 width, height;
     833                 :            : 
     834                 :          0 :     getBitmapData( bmpSource, pImageData, pAlphaData, width, height );
     835                 :          0 :     sal_uInt32 raw_size = width * height * 4;
     836                 :          0 :     uLongf compressed_size = raw_size + (sal_uInt32)(raw_size/100) + 12;
     837                 :          0 :     sal_uInt8 *pCompressed = new sal_uInt8[ compressed_size ];
     838                 :            : 
     839                 :            : #ifdef DBG_UTIL
     840                 :            :     if(compress2(pCompressed, &compressed_size, pImageData, raw_size, Z_BEST_COMPRESSION) != Z_OK)
     841                 :            :     {
     842                 :            :         DBG_ASSERT( false, "compress2 failed!" ); ((void)0);
     843                 :            :     }
     844                 :            : #else
     845                 :          0 :     compress2(pCompressed, &compressed_size, pImageData, raw_size, Z_BEST_COMPRESSION);
     846                 :            : #endif
     847                 :            : 
     848                 :            :     // AS: SWF files let you provide an Alpha mask for JPEG images, but we have
     849                 :            :     //  to ZLIB compress the alpha channel seperately.
     850                 :          0 :     uLong alpha_compressed_size = 0;
     851                 :          0 :     sal_uInt8 *pAlphaCompressed = NULL;
     852                 :          0 :     if (bmpSource.IsAlpha() || bmpSource.IsTransparent())
     853                 :            :     {
     854                 :          0 :         alpha_compressed_size = uLongf(width * height + (sal_uInt32)(raw_size/100) + 12);
     855                 :          0 :         pAlphaCompressed = new sal_uInt8[ compressed_size ];
     856                 :            : 
     857                 :            : #ifdef DBG_UTIL
     858                 :            :         if(compress2(pAlphaCompressed, &alpha_compressed_size, pAlphaData, width * height, Z_BEST_COMPRESSION) != Z_OK)
     859                 :            :         {
     860                 :            :             DBG_ASSERT( false, "compress2 failed!" ); ((void)0);
     861                 :            :         }
     862                 :            : #else
     863                 :          0 :         compress2(pAlphaCompressed, &alpha_compressed_size, pAlphaData, width * height, Z_BEST_COMPRESSION);
     864                 :            : #endif
     865                 :            :     }
     866                 :            : 
     867                 :            :     //Figure out JPEG size
     868                 :          0 :     const sal_uInt8* pJpgData = NULL;;
     869                 :          0 :     sal_uInt32 nJpgDataLength = 0xffffffff;
     870                 :            : 
     871                 :          0 :     Graphic aGraphic( bmpSource );
     872                 :          0 :     SvMemoryStream aDstStm( 65535, 65535 );
     873                 :            : 
     874                 :          0 :     GraphicFilter aFilter;
     875                 :            : 
     876                 :          0 :     Sequence< PropertyValue > aFilterData(nJPEGQualityLevel != -1);
     877                 :          0 :     if( nJPEGQualityLevel != -1 )
     878                 :            :     {
     879                 :          0 :         aFilterData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("Quality"));
     880                 :          0 :         aFilterData[0].Value <<= nJPEGQualityLevel;
     881                 :            :     }
     882                 :            : 
     883                 :          0 :     if( aFilter.ExportGraphic( aGraphic, String(), aDstStm,
     884                 :          0 :                                 aFilter.GetExportFormatNumberForShortName( OUString( RTL_CONSTASCII_USTRINGPARAM( JPG_SHORTNAME ) ) ), &aFilterData ) == ERRCODE_NONE )
     885                 :            :     {
     886                 :          0 :         pJpgData = reinterpret_cast<const sal_uInt8*>(aDstStm.GetData());
     887                 :          0 :         nJpgDataLength = aDstStm.Seek( STREAM_SEEK_TO_END );
     888                 :            :     }
     889                 :            : 
     890                 :            :     // AS: Ok, now go ahead and use whichever is smaller.  If JPEG is smaller, then
     891                 :            :     //  we have to export as TAG_DEFINEBITSJPEG3 in the case that there is alpha
     892                 :            :     //  channel data.
     893                 :          0 :     if ( pJpgData && ( nJpgDataLength + alpha_compressed_size < compressed_size) )
     894                 :          0 :         Impl_writeJPEG(nBitmapId, pJpgData, nJpgDataLength, pAlphaCompressed, alpha_compressed_size );
     895                 :            :     else
     896                 :          0 :         Impl_writeBmp( nBitmapId, width, height, pCompressed, compressed_size );
     897                 :            : 
     898                 :          0 :     delete[] pCompressed;
     899                 :          0 :     delete[] pAlphaCompressed;
     900                 :          0 :     delete[] pImageData;
     901                 :          0 :     delete[] pAlphaData;
     902                 :            : 
     903                 :          0 :     return nBitmapId;
     904                 :            : }
     905                 :            : 
     906                 :            : // -----------------------------------------------------------------------------
     907                 :            : 
     908                 :          0 : void Writer::Impl_writeImage( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& /* rSrcPt */, const Size& /* rSrcSz */, const Rectangle& rClipRect, bool bNeedToMapClipRect )
     909                 :            : {
     910                 :          0 :     if( !!rBmpEx )
     911                 :            :     {
     912                 :          0 :         BitmapEx bmpSource( rBmpEx );
     913                 :            : 
     914                 :          0 :         Rectangle originalPixelRect = Rectangle(Point(), bmpSource.GetSizePixel());
     915                 :            : 
     916                 :          0 :         Point srcPt( map(rPt) );
     917                 :          0 :         Size srcSize( map(rSz) );
     918                 :          0 :         Rectangle destRect( srcPt, srcSize );
     919                 :            : 
     920                 :            :         // AS: Christian, my scaling factors are different than yours, and work better for me.
     921                 :            :         //  However, I can't explain why exactly.  I got some of this by trial and error.
     922                 :          0 :         double XScale = static_cast<double>(originalPixelRect.GetWidth())/destRect.GetWidth();
     923                 :          0 :         double YScale = static_cast<double>(originalPixelRect.GetHeight())/destRect.GetHeight();
     924                 :            : 
     925                 :            :         // AS: If rClipRect has a value set, then we need to crop the bmp appropriately.
     926                 :            :         //  If a map event already occurred in the metafile, then we do not need to map
     927                 :            :         //  the clip rect as it's already been done.
     928                 :          0 :         if (!rClipRect.IsEmpty())
     929                 :            :         {
     930                 :            :             // AS: Christian, I also don't understand why bNeedToMapClipRect is necessary, but it
     931                 :            :             //  works like a charm.  Usually, the map event in the meta file does not cause the
     932                 :            :             //  clipping rectangle to get mapped.  However, sometimes there are multiple layers
     933                 :            :             //  of mapping which eventually do cause the clipping rect to be mapped.
     934                 :          0 :             Size clipSize( bNeedToMapClipRect ? map(rClipRect.GetSize()) : rClipRect.GetSize() );
     935                 :          0 :             Rectangle clipRect = Rectangle(Point(), clipSize);
     936                 :          0 :             destRect.Intersection( clipRect );
     937                 :            : 
     938                 :          0 :             Rectangle cropRect(destRect);
     939                 :            : 
     940                 :            :             // AS: The bmp origion is always 0,0 so we have to adjust before we crop.
     941                 :          0 :             cropRect.Move(-srcPt.X(), -srcPt.Y());
     942                 :            :             // AS: Rectangle has no scale function (?!) so I do it manually...
     943                 :          0 :             Rectangle cropPixelRect(static_cast<long>(cropRect.Left()*XScale),
     944                 :          0 :                                     static_cast<long>(cropRect.Top()*YScale),
     945                 :          0 :                                     static_cast<long>(cropRect.Right()*XScale),
     946                 :          0 :                                     static_cast<long>(cropRect.Bottom()*YScale));
     947                 :            : 
     948                 :          0 :             bmpSource.Crop(cropPixelRect);
     949                 :            :         }
     950                 :            : 
     951                 :          0 :         if( !!bmpSource )
     952                 :            :         {
     953                 :            :             // #105949# fix images that are under 16 pixels width or height by
     954                 :            :             //          expanding them. Some swf players can't display such small
     955                 :            :             //          bitmaps
     956                 :          0 :             const Size& rSizePixel = bmpSource.GetSizePixel();
     957                 :          0 :             if( (rSizePixel.Width() < 16) || (rSizePixel.Height() < 16) )
     958                 :            :             {
     959                 :          0 :                 const sal_uInt32 nDX = rSizePixel.Width() < 16 ? 16 - rSizePixel.Width() : 0;
     960                 :          0 :                 const sal_uInt32 nDY = rSizePixel.Height() < 16 ? 16 - rSizePixel.Height() : 0;
     961                 :          0 :                 bmpSource.Expand( nDX, nDY );
     962                 :            :             }
     963                 :            : 
     964                 :          0 :             sal_Int32 nJPEGQuality = mnJPEGCompressMode;
     965                 :            : 
     966                 :          0 :             Size szDestPixel = mpVDev->LogicToPixel(srcSize, aTWIPSMode);
     967                 :            : 
     968                 :          0 :             double pixXScale = static_cast<double>(szDestPixel.Width()) / originalPixelRect.GetWidth();
     969                 :          0 :             double pixYScale = static_cast<double>(szDestPixel.Height()) / originalPixelRect.GetHeight();
     970                 :            : 
     971                 :            :             // AS: If the image has been scaled down, then scale down the quality
     972                 :            :             //   that we use for JPEG compression.
     973                 :          0 :             if (pixXScale < 1.0 && pixYScale < 1.0)
     974                 :            :             {
     975                 :            : 
     976                 :          0 :                 double qualityScale = (pixXScale + pixYScale)/2;
     977                 :            : 
     978                 :          0 :                 nJPEGQuality = (sal_Int32)( nJPEGQuality * qualityScale );
     979                 :            : 
     980                 :          0 :                 if (nJPEGQuality < 10)
     981                 :          0 :                     nJPEGQuality += 3;
     982                 :            :             }
     983                 :            : 
     984                 :          0 :             sal_uInt16 nBitmapId = defineBitmap(bmpSource, nJPEGQuality);
     985                 :            : 
     986                 :          0 :             Polygon aPoly( destRect );
     987                 :            : 
     988                 :            :             // AS: Since images are being cropped now, no translation is normally necessary.
     989                 :            :             //  However, some things like graphical bullet points are still get translated.
     990                 :          0 :             ::basegfx::B2DHomMatrix m; // #i73264#
     991                 :          0 :             m.scale(1.0/XScale, 1.0/YScale );
     992                 :          0 :             if (destRect.Left() || destRect.Top())
     993                 :          0 :                 m.translate(destRect.Left(), destRect.Top());
     994                 :            : 
     995                 :          0 :             FillStyle aFillStyle( nBitmapId, true, m );
     996                 :            : 
     997                 :          0 :             sal_uInt16 nShapeId = defineShape( aPoly, aFillStyle );
     998                 :            : 
     999                 :          0 :             maShapeIds.push_back( nShapeId );
    1000                 :          0 :         }
    1001                 :            :     }
    1002                 :          0 : }
    1003                 :            : // -----------------------------------------------------------------------------
    1004                 :            : 
    1005                 :          0 : void Writer::Impl_writeBmp( sal_uInt16 nBitmapId, sal_uInt32 width, sal_uInt32 height, sal_uInt8 *pCompressed, sal_uInt32 compressed_size )
    1006                 :            : {
    1007                 :          0 :     startTag( TAG_DEFINEBITSLOSSLESS2 );
    1008                 :            : 
    1009                 :          0 :     mpTag->addUI16( nBitmapId );
    1010                 :          0 :     mpTag->addUI8( 5 );
    1011                 :          0 :     mpTag->addUI16( _uInt16(width) );
    1012                 :          0 :     mpTag->addUI16( _uInt16(height) );
    1013                 :            : 
    1014                 :          0 :     mpTag->Write( pCompressed, compressed_size );
    1015                 :            : 
    1016                 :          0 :     endTag();
    1017                 :          0 : }
    1018                 :            : 
    1019                 :            : // -----------------------------------------------------------------------------
    1020                 :            : 
    1021                 :          0 : void Writer::Impl_writeJPEG(sal_uInt16 nBitmapId, const sal_uInt8* pJpgData, sal_uInt32 nJpgDataLength, sal_uInt8 *pAlphaCompressed, sal_uInt32 alpha_compressed_size )
    1022                 :            : {
    1023                 :            :     // AS: Go through the actuall JPEG bits, seperating out the
    1024                 :            :     //  header fields from the actual image fields.  Fields are
    1025                 :            :     //  identifed by 0xFFXX where XX is the field type.  Both
    1026                 :            :     //  the header and the image need start and stop (D8 and D9),
    1027                 :            :     //  so that's why you see those written to both.  I don't
    1028                 :            :     //  really know what the rest of these are, I got it to work
    1029                 :            :     //  kind of by trial and error and by comparing with known
    1030                 :            :     //  good SWF files.
    1031                 :          0 :     sal_uInt8 cType = 0x01;
    1032                 :          0 :     const sal_uInt8* pJpgSearch = pJpgData;
    1033                 :            : 
    1034                 :          0 :     int nLength = 0;
    1035                 :            : 
    1036                 :          0 :     SvMemoryStream EncodingTableStream;
    1037                 :          0 :     SvMemoryStream ImageBitsStream;
    1038                 :          0 :     for (;pJpgSearch < pJpgData + nJpgDataLength; pJpgSearch += nLength)
    1039                 :            :     {
    1040                 :            : 
    1041                 :            : #ifdef DBG_UTIL
    1042                 :            :         if (0xFF != *pJpgSearch)
    1043                 :            :         {
    1044                 :            :             OSL_FAIL( "Expected JPEG marker." ); ((void)0);
    1045                 :            :         }
    1046                 :            : #endif
    1047                 :            : 
    1048                 :          0 :         cType = *(pJpgSearch + 1);
    1049                 :            : 
    1050                 :          0 :         if (0xD8 == cType || 0xD9 == cType)
    1051                 :            :         {
    1052                 :          0 :             nLength = 2;
    1053                 :            :         }
    1054                 :          0 :         else if (0xDA == cType)
    1055                 :            :         {
    1056                 :            :             //AS: This is the actual image data, and runs to the
    1057                 :            :             // end of the file (as best I know), minus 2 bytes
    1058                 :            :             // for the closing 0xFFD9.
    1059                 :          0 :             nLength = nJpgDataLength - (pJpgSearch - pJpgData) - 2;
    1060                 :            :         }
    1061                 :            :         else
    1062                 :            :         {
    1063                 :            :             // AS: Lengths are big endian.
    1064                 :            : 
    1065                 :            :             // Beware. pJpgSearch is not necessarily word-aligned,
    1066                 :            :             // so we access it byte-wise.
    1067                 :            : 
    1068                 :            :             // AS: Add 2 to the length to include the 0xFFXX itself.
    1069                 :          0 :             nLength = 2 + (pJpgSearch[2]<<8) + pJpgSearch[3];
    1070                 :            :         }
    1071                 :            : 
    1072                 :            :         // AS: I'm refering to libjpeg for a list of what these
    1073                 :            :         //  markers are.  See jdmarker.c for a list.
    1074                 :            :         // AS: I'm ignoring application specific markers 0xE1...0xEF
    1075                 :            :         //  and comments 0xFE.  I don't know what
    1076                 :            :         //  0xF0 or 0xFD are for, and they don't come up.
    1077                 :            :         //  Additionally, 0xDE and 0xDF aren't clear to me.
    1078                 :          0 :         switch(cType)
    1079                 :            :         {
    1080                 :            :         case 0xD8:
    1081                 :            :         case 0xD9:
    1082                 :          0 :             EncodingTableStream.Write( pJpgSearch, nLength );
    1083                 :          0 :             ImageBitsStream.Write( pJpgSearch, nLength );
    1084                 :          0 :             break;
    1085                 :            : 
    1086                 :            :         case 0x01:
    1087                 :            :         case 0xDB:
    1088                 :            :         case 0xDC:
    1089                 :            :         case 0xDD:
    1090                 :            :         case 0xC4:
    1091                 :          0 :             EncodingTableStream.Write( pJpgSearch, nLength );
    1092                 :          0 :             break;
    1093                 :            : 
    1094                 :            :         case 0xC0:
    1095                 :            :         case 0xC1:
    1096                 :            :         case 0xC2:
    1097                 :            :         case 0xC3:
    1098                 :            :         case 0xC5:
    1099                 :            :         case 0xC6:
    1100                 :            :         case 0xC7:
    1101                 :            : //      case 0xC8: Apparently reserved for JPEG extensions?
    1102                 :            :         case 0xC9:
    1103                 :            :         case 0xCA:
    1104                 :            :         case 0xCB:
    1105                 :            :         case 0xCD:
    1106                 :            :         case 0xCE:
    1107                 :            :         case 0xCF:
    1108                 :            :         case 0xDA:
    1109                 :            :         case 0xE0:
    1110                 :          0 :             ImageBitsStream.Write( pJpgSearch, nLength );
    1111                 :          0 :             break;
    1112                 :            : 
    1113                 :            :         default:
    1114                 :            :             OSL_FAIL( "JPEG marker I didn't handle!" );
    1115                 :            : 
    1116                 :            :         }
    1117                 :            :     }
    1118                 :            : 
    1119                 :          0 :     EncodingTableStream.Seek( STREAM_SEEK_TO_END );
    1120                 :          0 :     sal_uInt32 nEncodingTableSize = EncodingTableStream.Tell();
    1121                 :          0 :     EncodingTableStream.Seek( STREAM_SEEK_TO_BEGIN );
    1122                 :            : 
    1123                 :          0 :     ImageBitsStream.Seek( STREAM_SEEK_TO_END );
    1124                 :          0 :     sal_uInt32 nImageBitsSize = ImageBitsStream.Tell();
    1125                 :          0 :     ImageBitsStream.Seek( STREAM_SEEK_TO_BEGIN );
    1126                 :            : 
    1127                 :            :     // AS: If we need alpha support, use TAG_DEFINEBITSJPEG3.
    1128                 :          0 :     if (alpha_compressed_size > 0)
    1129                 :            :     {
    1130                 :          0 :         startTag( TAG_DEFINEBITSJPEG3 );
    1131                 :            : 
    1132                 :          0 :         mpTag->addUI16( nBitmapId );
    1133                 :            : 
    1134                 :          0 :         mpTag->addUI32( nEncodingTableSize + nImageBitsSize );
    1135                 :            : 
    1136                 :          0 :         mpTag->Write(EncodingTableStream.GetData(), nEncodingTableSize);
    1137                 :          0 :         mpTag->Write(ImageBitsStream.GetData(), nImageBitsSize);
    1138                 :            : 
    1139                 :          0 :         mpTag->Write( pAlphaCompressed, alpha_compressed_size );
    1140                 :            : 
    1141                 :          0 :         endTag();
    1142                 :            :     }
    1143                 :            :     else
    1144                 :            :     {
    1145                 :          0 :         startTag( TAG_DEFINEBITSJPEG2 );
    1146                 :            : 
    1147                 :          0 :         mpTag->addUI16( nBitmapId );
    1148                 :            : 
    1149                 :          0 :         mpTag->Write(EncodingTableStream.GetData(), nEncodingTableSize);
    1150                 :          0 :         mpTag->Write(ImageBitsStream.GetData(), nImageBitsSize);
    1151                 :            : 
    1152                 :          0 :         endTag();
    1153                 :          0 :     }
    1154                 :          0 : }
    1155                 :            : 
    1156                 :            : // -----------------------------------------------------------------------------
    1157                 :            : 
    1158                 :          0 : void Writer::Impl_writeLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor )
    1159                 :            : {
    1160                 :          0 :     Color aOldColor( mpVDev->GetLineColor() );
    1161                 :          0 :     if( pLineColor )
    1162                 :          0 :         mpVDev->SetLineColor( *pLineColor );
    1163                 :            : 
    1164                 :          0 :     const Point aPtAry[2] = { rPt1, rPt2 };
    1165                 :          0 :     Polygon aPoly( 2, aPtAry );
    1166                 :          0 :     Impl_writePolyPolygon( aPoly, false );
    1167                 :            : 
    1168                 :          0 :     mpVDev->SetLineColor( aOldColor );
    1169                 :          0 : }
    1170                 :            : 
    1171                 :            : // -----------------------------------------------------------------------------
    1172                 :            : 
    1173                 :          0 : void Writer::Impl_writeRect( const Rectangle& rRect, long nRadX, long nRadY )
    1174                 :            : {
    1175                 :          0 :     if( (rRect.nTop == rRect.nBottom) || (rRect.nLeft == rRect.nRight) )
    1176                 :            :     {
    1177                 :          0 :         Color aColor( mpVDev->GetFillColor() );
    1178                 :          0 :         Impl_writeLine( rRect.TopLeft(), rRect.BottomRight(), &aColor );
    1179                 :            :     }
    1180                 :            :     else
    1181                 :            :     {
    1182                 :          0 :         Polygon aPoly( rRect, nRadX, nRadY );
    1183                 :          0 :         Impl_writePolyPolygon( aPoly, true );
    1184                 :            :     }
    1185                 :          0 : }
    1186                 :            : 
    1187                 :            : // -----------------------------------------------------------------------------
    1188                 :            : 
    1189                 :          0 : void Writer::Impl_writeEllipse( const Point& rCenter, long nRadX, long nRadY )
    1190                 :            : {
    1191                 :          0 :     Polygon aPoly( rCenter, nRadX, nRadY );
    1192                 :          0 :     Impl_writePolyPolygon( aPoly, false );
    1193                 :          0 : }
    1194                 :            : 
    1195                 :            : 
    1196                 :            : /** writes the stroke defined by SvtGraphicStroke and returns true or it returns
    1197                 :            :     false if it can't handle this stroke.
    1198                 :            : */
    1199                 :          0 : bool Writer::Impl_writeStroke( SvtGraphicStroke& rStroke )
    1200                 :            : {
    1201                 :          0 :     Polygon aPolygon;
    1202                 :          0 :     rStroke.getPath( aPolygon );
    1203                 :          0 :     PolyPolygon aPolyPolygon( aPolygon );
    1204                 :            : 
    1205                 :          0 :     map( aPolyPolygon );
    1206                 :            : 
    1207                 :            :     // as log as not LINESTYLE2 and DefineShape4 is used (which
    1208                 :            :     // added support for LineJoin), only round LineJoins are
    1209                 :            :     // supported. Fallback to META_POLYLINE_ACTION and META_LINE_ACTION
    1210                 :          0 :     if(SvtGraphicStroke::joinRound != rStroke.getJoinType())
    1211                 :          0 :         return false;
    1212                 :            : 
    1213                 :          0 :     PolyPolygon aStartArrow;
    1214                 :          0 :     rStroke.getStartArrow( aStartArrow );
    1215                 :          0 :     if( 0 != aStartArrow.Count() )
    1216                 :          0 :         return false;       // todo: Implement line ends
    1217                 :            : 
    1218                 :          0 :     PolyPolygon aEndArrow;
    1219                 :          0 :     rStroke.getEndArrow( aEndArrow );
    1220                 :          0 :     if( 0 != aEndArrow.Count() )
    1221                 :          0 :         return false;       // todo: Implement line ends
    1222                 :            : 
    1223                 :          0 :     SvtGraphicStroke::DashArray aDashArray;
    1224                 :          0 :     rStroke.getDashArray( aDashArray );
    1225                 :          0 :     if( 0 != aDashArray.size() )
    1226                 :          0 :         return false;       // todo: implement dashes
    1227                 :            : 
    1228                 :          0 :     Color aColor( mpVDev->GetLineColor() );
    1229                 :            : 
    1230                 :          0 :     if( 0.0 != rStroke.getTransparency() )
    1231                 :          0 :         aColor.SetTransparency( sal::static_int_cast<sal_uInt8>( MinMax( (long int)( rStroke.getTransparency() * 0xff ), 0, 0xff ) ) );
    1232                 :            : 
    1233                 :          0 :     sal_uInt16 nShapeId = defineShape( aPolyPolygon, sal::static_int_cast<sal_uInt16>( mapRelative( (sal_Int32)( rStroke.getStrokeWidth() ) ) ), aColor );
    1234                 :          0 :     maShapeIds.push_back( nShapeId );
    1235                 :          0 :     return true;
    1236                 :            : }
    1237                 :            : 
    1238                 :            : // -----------------------------------------------------------------------------
    1239                 :            : 
    1240                 :            : /** writes the filling defined by SvtGraphicFill and returns true or it returns
    1241                 :            :     false if it can't handle this filling.
    1242                 :            : */
    1243                 :          0 : bool Writer::Impl_writeFilling( SvtGraphicFill& rFilling )
    1244                 :            : {
    1245                 :          0 :     PolyPolygon aPolyPolygon;
    1246                 :          0 :     rFilling.getPath( aPolyPolygon );
    1247                 :            : 
    1248                 :          0 :     Rectangle aOldRect( aPolyPolygon.GetBoundRect() );
    1249                 :            : 
    1250                 :          0 :     map( aPolyPolygon );
    1251                 :            : 
    1252                 :          0 :     Rectangle aNewRect( aPolyPolygon.GetBoundRect() );
    1253                 :            : 
    1254                 :          0 :     switch( rFilling.getFillType() )
    1255                 :            :     {
    1256                 :            :     case SvtGraphicFill::fillSolid:
    1257                 :            :         {
    1258                 :          0 :             Color aColor( rFilling.getFillColor() );
    1259                 :            : 
    1260                 :          0 :             if( 0.0 != rFilling.getTransparency() )
    1261                 :          0 :                 aColor.SetTransparency( sal::static_int_cast<sal_uInt8>( MinMax( (long int)( rFilling.getTransparency() * 0xff ) , 0, 0xff ) ) );
    1262                 :            : 
    1263                 :          0 :             FillStyle aFillStyle( aColor );
    1264                 :            : 
    1265                 :          0 :             sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
    1266                 :          0 :             maShapeIds.push_back( nShapeId );
    1267                 :            :         }
    1268                 :          0 :         break;
    1269                 :            :     case SvtGraphicFill::fillGradient:
    1270                 :          0 :         return false;
    1271                 :            :     case SvtGraphicFill::fillHatch:
    1272                 :          0 :         return false;
    1273                 :            :     case SvtGraphicFill::fillTexture:
    1274                 :            :         {
    1275                 :          0 :             Graphic aGraphic;
    1276                 :          0 :             rFilling.getGraphic( aGraphic );
    1277                 :            : 
    1278                 :            :             // CL->AS: Should we also scale down the quality here depending on image scale?
    1279                 :          0 :             sal_uInt16 nBitmapId = defineBitmap( aGraphic.GetBitmapEx(), mnJPEGCompressMode );
    1280                 :            : 
    1281                 :          0 :             ::basegfx::B2DHomMatrix aMatrix; // #i73264#
    1282                 :            : 
    1283                 :          0 :             SvtGraphicFill::Transform aTransform;
    1284                 :            : 
    1285                 :          0 :             rFilling.getTransform( aTransform );
    1286                 :            : 
    1287                 :            :             sal_uInt16 a,b;
    1288                 :          0 :             for( a = 0; a < 2; a++ )
    1289                 :            :             {
    1290                 :          0 :                 for( b = 0; b < 3; b++ )
    1291                 :            :                 {
    1292                 :          0 :                     aMatrix.set(a, b, aTransform.matrix[a*3+b]);
    1293                 :            :                 }
    1294                 :            :             }
    1295                 :          0 :             aMatrix.set(2, 0, 0.0);
    1296                 :          0 :             aMatrix.set(2, 1, 0.0);
    1297                 :          0 :             aMatrix.set(2, 2, 1.0);
    1298                 :            : 
    1299                 :            :             // scale bitmap
    1300                 :          0 :             double XScale = (double)aNewRect.GetWidth()/aOldRect.GetWidth();
    1301                 :          0 :             double YScale = (double)aNewRect.GetHeight()/aOldRect.GetHeight();
    1302                 :            : 
    1303                 :          0 :             aMatrix.scale( XScale, YScale );
    1304                 :            : 
    1305                 :          0 :             FillStyle aFillStyle( nBitmapId, !rFilling.IsTiling(), aMatrix );
    1306                 :            : 
    1307                 :          0 :             sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
    1308                 :          0 :             maShapeIds.push_back( nShapeId );
    1309                 :            :         }
    1310                 :          0 :         break;
    1311                 :            :     }
    1312                 :          0 :     return true;
    1313                 :            : }
    1314                 :            : 
    1315                 :            : // -----------------------------------------------------------------------------
    1316                 :            : 
    1317                 :            : /* CL: The idea was to export page fields as text fields that get theire
    1318                 :            :    string from a variable set with actionscript by each page. This didn't
    1319                 :            :    work out since the formating is always wrong when text follows the
    1320                 :            :    page number field since pages greater one may require more space than
    1321                 :            :    page 1
    1322                 :            : */
    1323                 :            : #if 0
    1324                 :            : bool Writer::Impl_writePageField( Rectangle& rTextBounds )
    1325                 :            : {
    1326                 :            :     startTag( TAG_DEFINEEDITTEXT );
    1327                 :            : 
    1328                 :            :     sal_uInt16 nTextId = createID();
    1329                 :            : 
    1330                 :            :     mpTag->addUI16( nTextId );
    1331                 :            :     mpTag->addRect( rTextBounds );
    1332                 :            : 
    1333                 :            :     BitStream aBits;
    1334                 :            :     aBits.writeUB( 1, 1 );                  // HasText
    1335                 :            :     aBits.writeUB( 0, 1 );                  // WordWrap
    1336                 :            :     aBits.writeUB( 0, 1 );                  // MultiLine
    1337                 :            :     aBits.writeUB( 0, 1 );                  // Password
    1338                 :            :     aBits.writeUB( 1, 1 );                  // HasTextColor
    1339                 :            :     aBits.writeUB( 0, 1 );                  // HasMaxLength
    1340                 :            :     aBits.writeUB( 0, 1 );                  // HasFont
    1341                 :            :     aBits.writeUB( 0, 1 );                  // Reserved
    1342                 :            :     aBits.writeUB( 0, 1 );                  // AutoSize
    1343                 :            :     aBits.writeUB( 0, 1 );                  // HasLayout
    1344                 :            :     aBits.writeUB( 1, 1 );                  // NoSelect
    1345                 :            :     aBits.writeUB( 1, 1 );                  // Border
    1346                 :            :     aBits.writeUB( 0, 1 );                  // Reserved
    1347                 :            :     aBits.writeUB( 0, 1 );                  // HTML
    1348                 :            :     aBits.writeUB( 0, 1 );                  // UseOutlines
    1349                 :            :     mpTag->addBits( aBits );
    1350                 :            : 
    1351                 :            :     Color aColor( COL_BLACK );
    1352                 :            :     mpTag->addRGB( aColor );
    1353                 :            :     mpTag->addString( "PageNumber" );
    1354                 :            :     mpTag->addString( "XXX" );
    1355                 :            : 
    1356                 :            :     endTag();
    1357                 :            : 
    1358                 :            :     maShapeIds.push_back( nTextId );
    1359                 :            : 
    1360                 :            :     return true;
    1361                 :            : }
    1362                 :            : #endif
    1363                 :            : 
    1364                 :            : // -----------------------------------------------------------------------------
    1365                 :            : 
    1366                 :          0 : void Writer::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
    1367                 :            : {
    1368                 :          0 :     if(rLinePolygon.count())
    1369                 :            :     {
    1370                 :          0 :         basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
    1371                 :          0 :         basegfx::B2DPolyPolygon aFillPolyPolygon;
    1372                 :            : 
    1373                 :          0 :         rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
    1374                 :            : 
    1375                 :          0 :         if(aLinePolyPolygon.count())
    1376                 :            :         {
    1377                 :          0 :             for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
    1378                 :            :             {
    1379                 :          0 :                 const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
    1380                 :          0 :                 Impl_writePolygon(Polygon(aCandidate), sal_False );
    1381                 :          0 :             }
    1382                 :            :         }
    1383                 :            : 
    1384                 :          0 :         if(aFillPolyPolygon.count())
    1385                 :            :         {
    1386                 :          0 :             const Color aOldLineColor(mpVDev->GetLineColor());
    1387                 :          0 :             const Color aOldFillColor(mpVDev->GetFillColor());
    1388                 :            : 
    1389                 :          0 :             mpVDev->SetLineColor();
    1390                 :          0 :             mpVDev->SetFillColor(aOldLineColor);
    1391                 :            : 
    1392                 :          0 :             for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
    1393                 :            :             {
    1394                 :          0 :                 const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
    1395                 :          0 :                 Impl_writePolyPolygon(PolyPolygon(Polygon(aPolygon)), sal_True );
    1396                 :          0 :             }
    1397                 :            : 
    1398                 :          0 :             mpVDev->SetLineColor(aOldLineColor);
    1399                 :          0 :             mpVDev->SetFillColor(aOldFillColor);
    1400                 :          0 :         }
    1401                 :            :     }
    1402                 :          0 : }
    1403                 :            : 
    1404                 :            : // -----------------------------------------------------------------------------
    1405                 :            : 
    1406                 :          0 : void Writer::Impl_writeActions( const GDIMetaFile& rMtf )
    1407                 :            : {
    1408                 :          0 :     Rectangle clipRect;
    1409                 :          0 :     int bMap = 0;
    1410                 :          0 :     for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; i++ )
    1411                 :            :     {
    1412                 :          0 :         const MetaAction*   pAction = rMtf.GetAction( i );
    1413                 :          0 :         const sal_uInt16        nType = pAction->GetType();
    1414                 :            : 
    1415                 :          0 :         switch( nType )
    1416                 :            :         {
    1417                 :            :             case( META_PIXEL_ACTION ):
    1418                 :            :             {
    1419                 :          0 :                 const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
    1420                 :            : 
    1421                 :          0 :                 Impl_writeLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor() );
    1422                 :            :             }
    1423                 :          0 :             break;
    1424                 :            : 
    1425                 :            :             case( META_POINT_ACTION ):
    1426                 :            :             {
    1427                 :          0 :                 const MetaPointAction* pA = (const MetaPointAction*) pAction;
    1428                 :            : 
    1429                 :          0 :                 Impl_writeLine( pA->GetPoint(), pA->GetPoint() );
    1430                 :            :             }
    1431                 :          0 :             break;
    1432                 :            : 
    1433                 :            :             case( META_LINE_ACTION ):
    1434                 :            :             {
    1435                 :          0 :                 const MetaLineAction* pA = (const MetaLineAction*) pAction;
    1436                 :            : 
    1437                 :          0 :                 if(pA->GetLineInfo().IsDefault())
    1438                 :            :                 {
    1439                 :          0 :                     Impl_writeLine( pA->GetStartPoint(), pA->GetEndPoint() );
    1440                 :            :                 }
    1441                 :            :                 else
    1442                 :            :                 {
    1443                 :            :                     // LineInfo used; handle Dash/Dot and fat lines
    1444                 :          0 :                     basegfx::B2DPolygon aPolygon;
    1445                 :          0 :                     aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
    1446                 :          0 :                     aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
    1447                 :          0 :                     Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
    1448                 :            :                 }
    1449                 :            :             }
    1450                 :          0 :             break;
    1451                 :            : 
    1452                 :            :             case( META_RECT_ACTION ):
    1453                 :            :             {
    1454                 :          0 :                 Impl_writeRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0 );
    1455                 :            :             }
    1456                 :          0 :             break;
    1457                 :            : 
    1458                 :            :             case( META_ROUNDRECT_ACTION ):
    1459                 :            :             {
    1460                 :          0 :                 const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
    1461                 :            : 
    1462                 :          0 :                 Impl_writeRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
    1463                 :            :             }
    1464                 :          0 :             break;
    1465                 :            : 
    1466                 :            :             case( META_ELLIPSE_ACTION ):
    1467                 :            :             {
    1468                 :          0 :                 const MetaEllipseAction*    pA = (const MetaEllipseAction*) pAction;
    1469                 :          0 :                 const Rectangle&            rRect = pA->GetRect();
    1470                 :            : 
    1471                 :          0 :                 Impl_writeEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1 );
    1472                 :            :             }
    1473                 :          0 :             break;
    1474                 :            : 
    1475                 :            :             case( META_ARC_ACTION ):
    1476                 :            :             case( META_PIE_ACTION ):
    1477                 :            :             case( META_CHORD_ACTION ):
    1478                 :            :             case( META_POLYGON_ACTION ):
    1479                 :            :             {
    1480                 :          0 :                 Polygon aPoly;
    1481                 :            : 
    1482                 :          0 :                 switch( nType )
    1483                 :            :                 {
    1484                 :            :                     case( META_ARC_ACTION ):
    1485                 :            :                     {
    1486                 :          0 :                         const MetaArcAction* pA = (const MetaArcAction*) pAction;
    1487                 :          0 :                         aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
    1488                 :            :                     }
    1489                 :          0 :                     break;
    1490                 :            : 
    1491                 :            :                     case( META_PIE_ACTION ):
    1492                 :            :                     {
    1493                 :          0 :                         const MetaPieAction* pA = (const MetaPieAction*) pAction;
    1494                 :          0 :                         aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
    1495                 :            :                     }
    1496                 :          0 :                     break;
    1497                 :            : 
    1498                 :            :                     case( META_CHORD_ACTION ):
    1499                 :            :                     {
    1500                 :          0 :                         const MetaChordAction* pA = (const MetaChordAction*) pAction;
    1501                 :          0 :                         aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
    1502                 :            :                     }
    1503                 :          0 :                     break;
    1504                 :            : 
    1505                 :            :                     case( META_POLYGON_ACTION ):
    1506                 :          0 :                         aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
    1507                 :          0 :                     break;
    1508                 :            :                 }
    1509                 :            : 
    1510                 :          0 :                 if( aPoly.GetSize() )
    1511                 :            :                 {
    1512                 :          0 :                     Impl_writePolygon( aPoly, sal_True );
    1513                 :          0 :                 }
    1514                 :            :             }
    1515                 :          0 :             break;
    1516                 :            : 
    1517                 :            :             case( META_POLYLINE_ACTION ):
    1518                 :            :             {
    1519                 :          0 :                 const MetaPolyLineAction*   pA = (const MetaPolyLineAction*) pAction;
    1520                 :          0 :                 const Polygon&              rPoly = pA->GetPolygon();
    1521                 :            : 
    1522                 :          0 :                 if( rPoly.GetSize() )
    1523                 :            :                 {
    1524                 :          0 :                     if(pA->GetLineInfo().IsDefault())
    1525                 :            :                     {
    1526                 :          0 :                         Impl_writePolygon( rPoly, sal_False );
    1527                 :            :                     }
    1528                 :            :                     else
    1529                 :            :                     {
    1530                 :            :                         // LineInfo used; handle Dash/Dot and fat lines
    1531                 :          0 :                         Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
    1532                 :            :                     }
    1533                 :            :                 }
    1534                 :            :             }
    1535                 :          0 :             break;
    1536                 :            : 
    1537                 :            :             case( META_POLYPOLYGON_ACTION ):
    1538                 :            :             {
    1539                 :          0 :                 const MetaPolyPolygonAction*    pA = (const MetaPolyPolygonAction*) pAction;
    1540                 :          0 :                 const PolyPolygon&              rPolyPoly = pA->GetPolyPolygon();
    1541                 :            : 
    1542                 :          0 :                 if( rPolyPoly.Count() )
    1543                 :          0 :                     Impl_writePolyPolygon( rPolyPoly, sal_True );
    1544                 :            :             }
    1545                 :          0 :             break;
    1546                 :            : 
    1547                 :            :             case( META_GRADIENT_ACTION ):
    1548                 :            :             {
    1549                 :          0 :                 const MetaGradientAction*   pA = (const MetaGradientAction*) pAction;
    1550                 :            : 
    1551                 :          0 :                 Polygon aPoly( pA->GetRect() );
    1552                 :          0 :                 Impl_writeGradientEx( aPoly, pA->GetGradient() );
    1553                 :            :             }
    1554                 :          0 :             break;
    1555                 :            : 
    1556                 :            :             case( META_GRADIENTEX_ACTION ):
    1557                 :            :             {
    1558                 :          0 :                 const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
    1559                 :          0 :                 Impl_writeGradientEx( pA->GetPolyPolygon(), pA->GetGradient() );
    1560                 :            :             }
    1561                 :          0 :             break;
    1562                 :            : 
    1563                 :            :             case META_HATCH_ACTION:
    1564                 :            :             {
    1565                 :          0 :                 const MetaHatchAction*  pA = (const MetaHatchAction*) pAction;
    1566                 :          0 :                 GDIMetaFile             aTmpMtf;
    1567                 :            : 
    1568                 :          0 :                 mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
    1569                 :          0 :                 Impl_writeActions( aTmpMtf );
    1570                 :            :             }
    1571                 :          0 :             break;
    1572                 :            : 
    1573                 :            :             case( META_TRANSPARENT_ACTION ):
    1574                 :            :             {
    1575                 :          0 :                 const MetaTransparentAction*    pA = (const MetaTransparentAction*) pAction;
    1576                 :          0 :                 const PolyPolygon&              rPolyPoly = pA->GetPolyPolygon();
    1577                 :            : 
    1578                 :          0 :                 if( rPolyPoly.Count() )
    1579                 :            :                 {
    1580                 :            :                     // convert transparence from percent into 0x00 - 0xff
    1581                 :          0 :                     sal_uInt8 nTransparence = (sal_uInt8) MinMax( FRound( pA->GetTransparence() * 2.55 ), 0, 255 );
    1582                 :          0 :                     Impl_writePolyPolygon( rPolyPoly, sal_True, nTransparence );
    1583                 :            :                 }
    1584                 :            :             }
    1585                 :          0 :             break;
    1586                 :            : 
    1587                 :            :             case( META_FLOATTRANSPARENT_ACTION ):
    1588                 :            :             {
    1589                 :          0 :                 const MetaFloatTransparentAction*   pA = (const MetaFloatTransparentAction*) pAction;
    1590                 :          0 :                 GDIMetaFile                         aTmpMtf( pA->GetGDIMetaFile() );
    1591                 :          0 :                 Point                               aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
    1592                 :          0 :                 const Size                          aSrcSize( aTmpMtf.GetPrefSize() );
    1593                 :          0 :                 const Point                         aDestPt( pA->GetPoint() );
    1594                 :          0 :                 const Size                          aDestSize( pA->GetSize() );
    1595                 :          0 :                 const double                        fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
    1596                 :          0 :                 const double                        fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
    1597                 :            :                 long                                nMoveX, nMoveY;
    1598                 :            : 
    1599                 :          0 :                 if( fScaleX != 1.0 || fScaleY != 1.0 )
    1600                 :            :                 {
    1601                 :          0 :                     aTmpMtf.Scale( fScaleX, fScaleY );
    1602                 :          0 :                     aSrcPt.X() = FRound( aSrcPt.X() * fScaleX );
    1603                 :          0 :                     aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
    1604                 :            :                 }
    1605                 :            : 
    1606                 :          0 :                 nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
    1607                 :            : 
    1608                 :          0 :                 if( nMoveX || nMoveY )
    1609                 :          0 :                     aTmpMtf.Move( nMoveX, nMoveY );
    1610                 :            : 
    1611                 :          0 :                 const Gradient& rGradient = pA->GetGradient();
    1612                 :          0 :                 sal_uInt32 nLuminance = ((sal_Int32)rGradient.GetStartColor().GetLuminance() + (sal_Int32)rGradient.GetEndColor().GetLuminance() ) >> 1;
    1613                 :            : 
    1614                 :          0 :                 sal_uInt8 nOldGlobalTransparency = mnGlobalTransparency;
    1615                 :          0 :                 mnGlobalTransparency = (sal_uInt8)MinMax( nLuminance, 0, 0xff );
    1616                 :            : 
    1617                 :          0 :                 mpVDev->Push();
    1618                 :          0 :                 Impl_writeActions( aTmpMtf );
    1619                 :          0 :                 mpVDev->Pop();
    1620                 :            : 
    1621                 :          0 :                 mnGlobalTransparency = nOldGlobalTransparency;
    1622                 :            :             }
    1623                 :          0 :             break;
    1624                 :            : 
    1625                 :            :             case( META_EPS_ACTION ):
    1626                 :            :             {
    1627                 :          0 :                 const MetaEPSAction*    pA = (const MetaEPSAction*) pAction;
    1628                 :          0 :                 const GDIMetaFile       aGDIMetaFile( pA->GetSubstitute() );
    1629                 :          0 :                 sal_Bool                bFound = sal_False;
    1630                 :            : 
    1631                 :          0 :                 for( size_t j = 0, nC = aGDIMetaFile.GetActionSize(); ( j < nC ) && !bFound; j++ )
    1632                 :            :                 {
    1633                 :          0 :                     const MetaAction* pSubstAct = aGDIMetaFile.GetAction( j );
    1634                 :            : 
    1635                 :          0 :                     if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
    1636                 :            :                     {
    1637                 :          0 :                         bFound = sal_True;
    1638                 :          0 :                         const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
    1639                 :          0 :                         Impl_writeImage( pBmpScaleAction->GetBitmap(),
    1640                 :          0 :                                       pA->GetPoint(), pA->GetSize(),
    1641                 :          0 :                                       Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), clipRect, 1 == bMap  );
    1642                 :            :                     }
    1643                 :          0 :                 }
    1644                 :            :             }
    1645                 :          0 :             break;
    1646                 :            : 
    1647                 :            :             case( META_COMMENT_ACTION ):
    1648                 :            :             {
    1649                 :          0 :                 const MetaCommentAction*    pA = (const MetaCommentAction*) pAction;
    1650                 :          0 :                 const sal_uInt8*                pData = pA->GetData();
    1651                 :          0 :                 String                      aSkipComment;
    1652                 :            : 
    1653                 :          0 :                 if( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XGRAD_SEQ_BEGIN")) )
    1654                 :            :                 {
    1655                 :          0 :                     const MetaGradientExAction* pGradAction = NULL;
    1656                 :          0 :                     sal_Bool                    bDone = sal_False;
    1657                 :            : 
    1658                 :          0 :                     while( !bDone && ( ++i < nCount ) )
    1659                 :            :                     {
    1660                 :          0 :                         pAction = rMtf.GetAction( i );
    1661                 :            : 
    1662                 :          0 :                         if( pAction->GetType() == META_GRADIENTEX_ACTION )
    1663                 :          0 :                             pGradAction = (const MetaGradientExAction*) pAction;
    1664                 :          0 :                         else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
    1665                 :          0 :                                  ( ( (const MetaCommentAction*) pAction )->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XGRAD_SEQ_END")) ) )
    1666                 :            :                         {
    1667                 :          0 :                             bDone = sal_True;
    1668                 :            :                         }
    1669                 :            :                     }
    1670                 :            : 
    1671                 :          0 :                     if( pGradAction )
    1672                 :          0 :                         Impl_writeGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient());
    1673                 :            :                 }
    1674                 :          0 :                 else if( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XPATHFILL_SEQ_BEGIN")) &&
    1675                 :            :                          pData )
    1676                 :            :                 {
    1677                 :            : 
    1678                 :            :                     // this comment encapsulates all high level information for a filling that caused
    1679                 :            :                     // the meta actions between the "XPATHFILL_SEQ_BEGIN" and "XPATHFILL_SEQ_END" comment.
    1680                 :            : 
    1681                 :          0 :                     SvtGraphicFill  aFilling;
    1682                 :          0 :                     SvMemoryStream  aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
    1683                 :            : 
    1684                 :            :                     // read the fill info
    1685                 :          0 :                     aMemStm >> aFilling;
    1686                 :            : 
    1687                 :            :                     // if impl_writeFilling can handle this high level filling, it returns true and we
    1688                 :            :                     // skip all meta actions until "XPATHFILL_SEQ_END"
    1689                 :          0 :                     if( Impl_writeFilling( aFilling ) )
    1690                 :            :                     {
    1691                 :          0 :                         bool bDone = sal_False;
    1692                 :            : 
    1693                 :          0 :                         while( !bDone && ( ++i < nCount ) )
    1694                 :            :                         {
    1695                 :          0 :                             pAction = rMtf.GetAction( i );
    1696                 :            : 
    1697                 :          0 :                             if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
    1698                 :          0 :                                      ( ( (const MetaCommentAction*) pAction )->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XPATHFILL_SEQ_END")) ) )
    1699                 :            :                             {
    1700                 :          0 :                                 bDone = sal_True;
    1701                 :            :                             }
    1702                 :            :                         }
    1703                 :          0 :                     }
    1704                 :            :                 }
    1705                 :          0 :                 else if( pA->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XPATHSTROKE_SEQ_BEGIN")) &&
    1706                 :            :                          pData )
    1707                 :            :                 {
    1708                 :            : 
    1709                 :            :                     // this comment encapsulates all high level information for a filling that caused
    1710                 :            :                     // the meta actions between the "XPATHFILL_SEQ_BEGIN" and "XPATHFILL_SEQ_END" comment.
    1711                 :            : 
    1712                 :          0 :                     SvtGraphicStroke aStroke;
    1713                 :          0 :                     SvMemoryStream  aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
    1714                 :            : 
    1715                 :            :                     // read the fill info
    1716                 :          0 :                     aMemStm >> aStroke;
    1717                 :            : 
    1718                 :            :                     // if impl_writeStroke can handle this high level stroke, it returns true and we
    1719                 :            :                     // skip all meta actions until "XPATHSTROKE_SEQ_END"
    1720                 :          0 :                     if( Impl_writeStroke( aStroke ) )
    1721                 :            :                     {
    1722                 :          0 :                         bool bDone = sal_False;
    1723                 :            : 
    1724                 :          0 :                         while( !bDone && ( ++i < nCount ) )
    1725                 :            :                         {
    1726                 :          0 :                             pAction = rMtf.GetAction( i );
    1727                 :            : 
    1728                 :          0 :                             if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
    1729                 :          0 :                                      ( ( (const MetaCommentAction*) pAction )->GetComment().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("XPATHSTROKE_SEQ_END")) ) )
    1730                 :            :                             {
    1731                 :          0 :                                 bDone = sal_True;
    1732                 :            :                             }
    1733                 :            :                         }
    1734                 :          0 :                     }
    1735                 :          0 :                 }
    1736                 :            :             }
    1737                 :          0 :             break;
    1738                 :            : 
    1739                 :            :             case( META_BMPSCALE_ACTION ):
    1740                 :            :             {
    1741                 :          0 :                 const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
    1742                 :            : 
    1743                 :          0 :                 Impl_writeImage( pA->GetBitmap(),
    1744                 :          0 :                           pA->GetPoint(), pA->GetSize(),
    1745                 :          0 :                           Point(), pA->GetBitmap().GetSizePixel(), clipRect, 1 == bMap );
    1746                 :            :             }
    1747                 :          0 :             break;
    1748                 :            : 
    1749                 :            :             case( META_BMP_ACTION ):
    1750                 :            :             {
    1751                 :          0 :                 const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
    1752                 :          0 :                 Impl_writeImage( pA->GetBitmap(),
    1753                 :          0 :                           pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel()),
    1754                 :          0 :                           Point(), pA->GetBitmap().GetSizePixel(), clipRect, 1 ==bMap );
    1755                 :            :             }
    1756                 :          0 :             break;
    1757                 :            : 
    1758                 :            :             case( META_BMPSCALEPART_ACTION ):
    1759                 :            :             {
    1760                 :          0 :                 const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
    1761                 :          0 :                 Impl_writeImage( pA->GetBitmap(),
    1762                 :          0 :                           pA->GetDestPoint(), pA->GetDestSize(),
    1763                 :          0 :                           pA->GetSrcPoint(), pA->GetSrcSize(), clipRect, 1 == bMap );
    1764                 :            :             }
    1765                 :          0 :             break;
    1766                 :            : 
    1767                 :            :             case( META_BMPEX_ACTION ):
    1768                 :            :             {
    1769                 :          0 :                 const MetaBmpExAction*  pA = (const MetaBmpExAction*) pAction;
    1770                 :          0 :                 Impl_writeImage( pA->GetBitmapEx(),
    1771                 :          0 :                           pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
    1772                 :          0 :                           Point(), pA->GetBitmapEx().GetSizePixel(), clipRect, 1 == bMap );
    1773                 :            :             }
    1774                 :          0 :             break;
    1775                 :            : 
    1776                 :            :             case( META_BMPEXSCALE_ACTION ):
    1777                 :            :             {
    1778                 :          0 :                 const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
    1779                 :          0 :                 Impl_writeImage( pA->GetBitmapEx(),
    1780                 :          0 :                           pA->GetPoint(), pA->GetSize(),
    1781                 :          0 :                           Point(), pA->GetBitmapEx().GetSizePixel(), clipRect, 1 == bMap );
    1782                 :            :             }
    1783                 :          0 :             break;
    1784                 :            : 
    1785                 :            :             case( META_BMPEXSCALEPART_ACTION ):
    1786                 :            :             {
    1787                 :          0 :                 const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
    1788                 :          0 :                 Impl_writeImage( pA->GetBitmapEx(),
    1789                 :          0 :                           pA->GetDestPoint(), pA->GetDestSize(),
    1790                 :          0 :                           pA->GetSrcPoint(), pA->GetSrcSize(), clipRect, 1 == bMap );
    1791                 :            :             }
    1792                 :          0 :             break;
    1793                 :            : 
    1794                 :            :             case( META_TEXT_ACTION ):
    1795                 :            :             {
    1796                 :          0 :                 const MetaTextAction* pA = (const MetaTextAction*) pAction;
    1797                 :          0 :                 Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0);
    1798                 :            :             }
    1799                 :          0 :             break;
    1800                 :            : 
    1801                 :            :             case( META_TEXTRECT_ACTION ):
    1802                 :            :             {
    1803                 :          0 :                 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
    1804                 :          0 :                 Impl_writeText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0  );
    1805                 :            :             }
    1806                 :          0 :             break;
    1807                 :            : 
    1808                 :            :             case( META_TEXTARRAY_ACTION ):
    1809                 :            :             {
    1810                 :          0 :                 const MetaTextArrayAction*  pA = (const MetaTextArrayAction*) pAction;
    1811                 :          0 :                 Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0 );
    1812                 :            :             }
    1813                 :          0 :             break;
    1814                 :            : 
    1815                 :            :             case( META_STRETCHTEXT_ACTION ):
    1816                 :            :             {
    1817                 :          0 :                 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
    1818                 :          0 :                 Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth() );
    1819                 :            :             }
    1820                 :          0 :             break;
    1821                 :            : 
    1822                 :            :             case( META_ISECTRECTCLIPREGION_ACTION ):
    1823                 :            :             {
    1824                 :          0 :                 const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
    1825                 :          0 :                 clipRect = pA->GetRect();
    1826                 :            :             }
    1827                 :            :             case( META_CLIPREGION_ACTION ):
    1828                 :            :             case( META_ISECTREGIONCLIPREGION_ACTION ):
    1829                 :            :             case( META_MOVECLIPREGION_ACTION ):
    1830                 :            :             {
    1831                 :          0 :                 ( (MetaAction*) pAction )->Execute( mpVDev );
    1832                 :            :             }
    1833                 :          0 :             break;
    1834                 :            : 
    1835                 :            :             case( META_RENDERGRAPHIC_ACTION ):
    1836                 :            :             {
    1837                 :          0 :                 const MetaRenderGraphicAction*          pA = (const MetaRenderGraphicAction*) pAction;
    1838                 :          0 :                 const ::vcl::RenderGraphicRasterizer    aRasterizer( pA->GetRenderGraphic() );
    1839                 :          0 :                 const Point                             aPointPixel;
    1840                 :          0 :                 const Size                              aSizePixel( mpVDev->LogicToPixel( pA->GetSize() ) );
    1841                 :          0 :                 const BitmapEx                          aBmpEx( aRasterizer.Rasterize( aSizePixel ) );
    1842                 :            : 
    1843                 :          0 :                 Impl_writeImage( aBmpEx, pA->GetPoint(), pA->GetSize(),
    1844                 :          0 :                                  aPointPixel, aBmpEx.GetSizePixel(), clipRect, 1 == bMap );
    1845                 :            :             }
    1846                 :          0 :             break;
    1847                 :            : 
    1848                 :            :             case( META_MAPMODE_ACTION ):
    1849                 :            :             {
    1850                 :          0 :                 bMap++;
    1851                 :            :             }
    1852                 :            :             case( META_REFPOINT_ACTION ):
    1853                 :            :             case( META_LINECOLOR_ACTION ):
    1854                 :            :             case( META_FILLCOLOR_ACTION ):
    1855                 :            :             case( META_TEXTLINECOLOR_ACTION ):
    1856                 :            :             case( META_TEXTFILLCOLOR_ACTION ):
    1857                 :            :             case( META_TEXTCOLOR_ACTION ):
    1858                 :            :             case( META_TEXTALIGN_ACTION ):
    1859                 :            :             case( META_FONT_ACTION ):
    1860                 :            :             case( META_PUSH_ACTION ):
    1861                 :            :             case( META_POP_ACTION ):
    1862                 :            :             case( META_LAYOUTMODE_ACTION ):
    1863                 :            :             {
    1864                 :          0 :                 ( (MetaAction*) pAction )->Execute( mpVDev );
    1865                 :            :             }
    1866                 :          0 :             break;
    1867                 :            : 
    1868                 :            :             case( META_RASTEROP_ACTION ):
    1869                 :            :             case( META_MASK_ACTION ):
    1870                 :            :             case( META_MASKSCALE_ACTION ):
    1871                 :            :             case( META_MASKSCALEPART_ACTION ):
    1872                 :            :             case( META_WALLPAPER_ACTION ):
    1873                 :            :             case( META_TEXTLINE_ACTION ):
    1874                 :            :             {
    1875                 :            :                 // !!! >>> we don't want to support these actions
    1876                 :            :             }
    1877                 :          0 :             break;
    1878                 :            : 
    1879                 :            :             default:
    1880                 :          0 :             break;
    1881                 :            :         }
    1882                 :            :     }
    1883                 :          0 : }
    1884                 :            : 
    1885                 :            : 
    1886                 :            : /////////////////////////////////////////////////////////////////////////
    1887                 :            : 
    1888                 :            : 
    1889                 :          0 : void Writer::Impl_addStraightLine( BitStream& rBits, Point& rLastPoint,
    1890                 :            :                                    const double P2x, const double P2y )
    1891                 :            : {
    1892                 :          0 :     Point aPoint( FRound(P2x), FRound(P2y) );
    1893                 :            : 
    1894                 :          0 :     Impl_addStraightEdgeRecord( rBits, _Int16(aPoint.X() - rLastPoint.X()),_Int16(aPoint.Y() - rLastPoint.Y()));
    1895                 :          0 :     rLastPoint = aPoint;
    1896                 :            : 
    1897                 :          0 : }
    1898                 :            : 
    1899                 :            : // -----------------------------------------------------------------------------
    1900                 :            : 
    1901                 :          0 : void Writer::Impl_addQuadBezier( BitStream& rBits, Point& rLastPoint,
    1902                 :            :                                  const double P2x, const double P2y,
    1903                 :            :                                  const double P3x, const double P3y )
    1904                 :            : {
    1905                 :            : 
    1906                 :          0 :     Point aControlPoint( FRound(P2x), FRound(P2y) );
    1907                 :          0 :     Point aAnchorPoint( FRound(P3x), FRound(P3y) );
    1908                 :            : 
    1909                 :            :     Impl_addCurvedEdgeRecord( rBits,
    1910                 :          0 :                                 _Int16(aControlPoint.X() - rLastPoint.X()),_Int16(aControlPoint.Y() - rLastPoint.Y()),
    1911                 :          0 :                                 _Int16(aAnchorPoint.X() - aControlPoint.X()),_Int16(aAnchorPoint.Y() - aControlPoint.Y()) );
    1912                 :          0 :     rLastPoint = aAnchorPoint;
    1913                 :          0 : }
    1914                 :            : 
    1915                 :            : // -----------------------------------------------------------------------------
    1916                 :            : 
    1917                 :            : /* Approximate given cubic bezier curve by quadratic bezier segments */
    1918                 :          0 : void Writer::Impl_quadBezierApprox( BitStream& rBits,
    1919                 :            :                                    Point& rLastPoint,
    1920                 :            :                                    const double d2,
    1921                 :            :                                    const double P1x, const double P1y,
    1922                 :            :                                    const double P2x, const double P2y,
    1923                 :            :                                    const double P3x, const double P3y,
    1924                 :            :                                    const double P4x, const double P4y )
    1925                 :            : {
    1926                 :            :     // Check for degenerate case, where the given cubic bezier curve
    1927                 :            :     // is already quadratic: P4 == 3P3 - 3P2 + P1
    1928                 :          0 :     if( P4x == 3.0*P3x - 3.0*P2x + P1x &&
    1929                 :            :         P4y == 3.0*P3y - 3.0*P2y + P1y )
    1930                 :            :     {
    1931                 :            :         Impl_addQuadBezier( rBits, rLastPoint,
    1932                 :            :                            3.0/2.0*P2x - 1.0/2.0*P1x, 3.0/2.0*P2y - 1.0/2.0*P1y,
    1933                 :          0 :                            P4x, P4y);
    1934                 :            :     }
    1935                 :            :     else
    1936                 :            :     {
    1937                 :            :         // Create quadratic segment for given cubic:
    1938                 :            :         // Start and end point must coincide, determine quadratic control
    1939                 :            :         // point in such a way that it lies on the intersection of the
    1940                 :            :         // tangents at start and end point, resp. Thus, both cubic and
    1941                 :            :         // quadratic curve segments will match in 0th and 1st derivative
    1942                 :            :         // at the start and end points
    1943                 :            : 
    1944                 :            :         // Intersection of P2P1 and P4P3
    1945                 :            :         //           (P2y-P4y)(P3x-P4x)-(P2x-P4x)(P3y-P4y)
    1946                 :            :         //  lambda = -------------------------------------
    1947                 :            :         //           (P1x-P2x)(P3y-P4y)-(P1y-P2y)(P3x-P4x)
    1948                 :            :         //
    1949                 :            :         // Intersection point IP is now
    1950                 :            :         // IP = P2 + lambda(P1-P2)
    1951                 :            :         //
    1952                 :          0 :         const double nominator( (P2y-P4y)*(P3x-P4x) - (P2x-P4x)*(P3y-P4y) );
    1953                 :          0 :         const double denominator( (P1x-P2x)*(P3y-P4y) - (P1y-P2y)*(P3x-P4x) );
    1954                 :          0 :         const double lambda( nominator / denominator );
    1955                 :            : 
    1956                 :          0 :         const double IPx( P2x + lambda*( P1x - P2x) );
    1957                 :          0 :         const double IPy( P2y + lambda*( P1y - P2y) );
    1958                 :            : 
    1959                 :            :         // Introduce some alias names: quadratic start point is P1, end
    1960                 :            :         // point is P4, control point is IP
    1961                 :          0 :         const double QP1x( P1x );
    1962                 :          0 :         const double QP1y( P1y );
    1963                 :          0 :         const double QP2x( IPx );
    1964                 :          0 :         const double QP2y( IPy );
    1965                 :          0 :         const double QP3x( P4x );
    1966                 :          0 :         const double QP3y( P4y );
    1967                 :            : 
    1968                 :            :         // Adapted bezier flatness test (lecture notes from R. Schaback,
    1969                 :            :         // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
    1970                 :            :         //
    1971                 :            :         // ||C(t) - Q(t)|| <= max     ||c_j - q_j||
    1972                 :            :         //                    0<=j<=n
    1973                 :            :         //
    1974                 :            :         // In this case, we don't need the distance from the cubic bezier
    1975                 :            :         // to a straight line, but to a quadratic bezier. The c_j's are
    1976                 :            :         // the cubic bezier's bernstein coefficients, the q_j's the
    1977                 :            :         // quadratic bezier's. We have the c_j's given, the q_j's can be
    1978                 :            :         // calculated from QPi like this (sorry, mixed index notation, we
    1979                 :            :         // use [1,n], formulas use [0,n-1]):
    1980                 :            :         //
    1981                 :            :         // q_0 = QP1 = P1
    1982                 :            :         // q_1 = 1/3 QP1 + 2/3 QP2
    1983                 :            :         // q_2 = 2/3 QP2 + 1/3 QP3
    1984                 :            :         // q_3 = QP3 = P4
    1985                 :            :         //
    1986                 :            :         // We can drop case 0 and 3, since there the curves coincide
    1987                 :            :         // (distance is zero)
    1988                 :            : 
    1989                 :            :         // calculate argument of max for j=1 and j=2
    1990                 :          0 :         const double fJ1x( P2x - 1.0/3.0*QP1x - 2.0/3.0*QP2x );
    1991                 :          0 :         const double fJ1y( P2y - 1.0/3.0*QP1y - 2.0/3.0*QP2y );
    1992                 :          0 :         const double fJ2x( P3x - 2.0/3.0*QP2x - 1.0/3.0*QP3x );
    1993                 :          0 :         const double fJ2y( P3y - 2.0/3.0*QP2y - 1.0/3.0*QP3y );
    1994                 :            : 
    1995                 :            :         // stop if distance from cubic curve is guaranteed to be bounded by d
    1996                 :            :         // Should denominator be 0: then P1P2 and P3P4 are parallel (P1P2^T R[90,P3P4] = 0.0),
    1997                 :            :         // meaning that either we have a straight line or an inflexion point (see else block below)
    1998                 :          0 :         if( 0.0 != denominator &&
    1999                 :            :             ::std::max( fJ1x*fJ1x + fJ1y*fJ1y,
    2000                 :          0 :                         fJ2x*fJ2x + fJ2y*fJ2y) < d2 )
    2001                 :            :         {
    2002                 :            :             // requested resolution reached.
    2003                 :            :             // Add end points to output file.
    2004                 :            :             // order is preserved, since this is so to say depth first traversal.
    2005                 :            :             Impl_addQuadBezier( rBits, rLastPoint,
    2006                 :            :                                 QP2x, QP2y,
    2007                 :          0 :                                 QP3x, QP3y);
    2008                 :            :         }
    2009                 :            :         else
    2010                 :            :         {
    2011                 :            :             // Maybe subdivide further
    2012                 :            : 
    2013                 :            :             // This is for robustness reasons, since the line intersection
    2014                 :            :             // method below gets instable if the curve gets closer to a
    2015                 :            :             // straight line. If the given cubic bezier does not deviate by
    2016                 :            :             // more than d/4 from a straight line, either:
    2017                 :            :             //  - take the line (that's what we do here)
    2018                 :            :             //  - express the line by a quadratic bezier
    2019                 :            : 
    2020                 :            :             // Perform bezier flatness test (lecture notes from R. Schaback,
    2021                 :            :             // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
    2022                 :            :             //
    2023                 :            :             // ||P(t) - L(t)|| <= max     ||b_j - b_0 - j/n(b_n - b_0)||
    2024                 :            :             //                    0<=j<=n
    2025                 :            :             //
    2026                 :            :             // What is calculated here is an upper bound to the distance from
    2027                 :            :             // a line through b_0 and b_3 (P1 and P4 in our notation) and the
    2028                 :            :             // curve. We can drop 0 and n from the running indices, since the
    2029                 :            :             // argument of max becomes zero for those cases.
    2030                 :          0 :             const double fJ1x2( P2x - P1x - 1.0/3.0*(P4x - P1x) );
    2031                 :          0 :             const double fJ1y2( P2y - P1y - 1.0/3.0*(P4y - P1y) );
    2032                 :          0 :             const double fJ2x2( P3x - P1x - 2.0/3.0*(P4x - P1x) );
    2033                 :          0 :             const double fJ2y2( P3y - P1y - 2.0/3.0*(P4y - P1y) );
    2034                 :            : 
    2035                 :            :             // stop if distance from line is guaranteed to be bounded by d/4
    2036                 :          0 :             if( ::std::max( fJ1x2*fJ1x2 + fJ1y2*fJ1y2,
    2037                 :          0 :                             fJ2x2*fJ2x2 + fJ2y2*fJ2y2) < d2/16.0 )
    2038                 :            :             {
    2039                 :            :                 // do not subdivide further, add straight line instead
    2040                 :          0 :                 Impl_addStraightLine( rBits, rLastPoint, P4x, P4y);
    2041                 :            :             }
    2042                 :            :             else
    2043                 :            :             {
    2044                 :            :                 // deCasteljau bezier arc, split at t=0.5
    2045                 :            :                 // Foley/vanDam, p. 508
    2046                 :          0 :                 const double L1x( P1x ),             L1y( P1y );
    2047                 :          0 :                 const double L2x( (P1x + P2x)*0.5 ), L2y( (P1y + P2y)*0.5 );
    2048                 :          0 :                 const double Hx ( (P2x + P3x)*0.5 ), Hy ( (P2y + P3y)*0.5 );
    2049                 :          0 :                 const double L3x( (L2x + Hx)*0.5 ),  L3y( (L2y + Hy)*0.5 );
    2050                 :          0 :                 const double R4x( P4x ),             R4y( P4y );
    2051                 :          0 :                 const double R3x( (P3x + P4x)*0.5 ), R3y( (P3y + P4y)*0.5 );
    2052                 :          0 :                 const double R2x( (Hx + R3x)*0.5 ),  R2y( (Hy + R3y)*0.5 );
    2053                 :          0 :                 const double R1x( (L3x + R2x)*0.5 ), R1y( (L3y + R2y)*0.5 );
    2054                 :          0 :                 const double L4x( R1x ),             L4y( R1y );
    2055                 :            : 
    2056                 :            :                 // subdivide further
    2057                 :          0 :                 Impl_quadBezierApprox(rBits, rLastPoint, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y);
    2058                 :          0 :                 Impl_quadBezierApprox(rBits, rLastPoint, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y);
    2059                 :            :             }
    2060                 :            :         }
    2061                 :            :     }
    2062                 :          0 : }
    2063                 :            : 
    2064                 :          0 : Reference < XBreakIterator > Writer::Impl_GetBreakIterator()
    2065                 :            : {
    2066                 :          0 :     if ( !mxBreakIterator.is() )
    2067                 :            :     {
    2068                 :          0 :         Reference< XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() );
    2069                 :          0 :         mxBreakIterator.set( xMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" )) ), UNO_QUERY );
    2070                 :            :     }
    2071                 :          0 :     return mxBreakIterator;
    2072                 :          0 : }
    2073                 :            : 
    2074                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10