LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - graphicprimitivehelper2d.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 26 144 18.1 %
Date: 2014-11-03 Functions: 3 14 21.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
      21             : #include <drawinglayer/animation/animationtiming.hxx>
      22             : #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
      23             : #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
      24             : #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
      25             : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
      26             : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
      27             : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
      28             : #include <basegfx/polygon/b2dpolygon.hxx>
      29             : #include <basegfx/polygon/b2dpolygontools.hxx>
      30             : #include <basegfx/numeric/ftools.hxx>
      31             : 
      32             : // helper class for animated graphics
      33             : 
      34             : #include <vcl/animate.hxx>
      35             : #include <vcl/graph.hxx>
      36             : #include <vcl/virdev.hxx>
      37             : #include <vcl/svapp.hxx>
      38             : #include <vcl/metaact.hxx>
      39             : 
      40             : namespace
      41             : {
      42           0 :     struct animationStep
      43             :     {
      44             :         BitmapEx                                maBitmapEx;
      45             :         sal_uInt32                              mnTime;
      46             :     };
      47             : 
      48           0 :     class animatedBitmapExPreparator
      49             :     {
      50             :         ::Animation                             maAnimation;
      51             :         ::std::vector< animationStep >          maSteps;
      52             : 
      53             :         sal_uInt32 generateStepTime(sal_uInt32 nIndex) const;
      54             : 
      55             :     public:
      56             :         animatedBitmapExPreparator(const Graphic& rGraphic);
      57             : 
      58           0 :         sal_uInt32 count() const { return maSteps.size(); }
      59           0 :         sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); }
      60           0 :         sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; }
      61           0 :         const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; }
      62             :     };
      63             : 
      64           0 :     sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const
      65             :     {
      66           0 :         const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex));
      67           0 :         sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10);
      68             : 
      69             :         // #115934#
      70             :         // Take care of special value for MultiPage TIFFs. ATM these shall just
      71             :         // show their first page. Later we will offer some switching when object
      72             :         // is selected.
      73           0 :         if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait)
      74             :         {
      75             :             // ATM the huge value would block the timer, so
      76             :             // use a long time to show first page (whole day)
      77           0 :             nWaitTime = 100 * 60 * 60 * 24;
      78             :         }
      79             : 
      80             :         // Bad trap: There are animated gifs with no set WaitTime (!).
      81             :         // In that case use a default value.
      82           0 :         if(0L == nWaitTime)
      83             :         {
      84           0 :             nWaitTime = 100L;
      85             :         }
      86             : 
      87           0 :         return nWaitTime;
      88             :     }
      89             : 
      90           0 :     animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic)
      91           0 :     :   maAnimation(rGraphic.GetAnimation())
      92             :     {
      93             :         OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)");
      94             : 
      95             :         // #128539# secure access to Animation, looks like there exist animated GIFs out there
      96             :         // with a step count of zero
      97           0 :         if(maAnimation.Count())
      98             :         {
      99           0 :             VirtualDevice aVirtualDevice(*Application::GetDefaultDevice());
     100           0 :             VirtualDevice aVirtualDeviceMask(*Application::GetDefaultDevice(), 1L);
     101             : 
     102             :             // Prepare VirtualDevices and their states
     103           0 :             aVirtualDevice.EnableMapMode(false);
     104           0 :             aVirtualDeviceMask.EnableMapMode(false);
     105           0 :             aVirtualDevice.SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
     106           0 :             aVirtualDeviceMask.SetOutputSizePixel(maAnimation.GetDisplaySizePixel());
     107           0 :             aVirtualDevice.Erase();
     108           0 :             aVirtualDeviceMask.Erase();
     109             : 
     110           0 :             for(sal_uInt16 a(0L); a < maAnimation.Count(); a++)
     111             :             {
     112           0 :                 animationStep aNextStep;
     113           0 :                 aNextStep.mnTime = generateStepTime(a);
     114             : 
     115             :                 // prepare step
     116           0 :                 const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a));
     117             : 
     118           0 :                 switch(rAnimBitmap.eDisposal)
     119             :                 {
     120             :                     case DISPOSE_NOT:
     121             :                     {
     122           0 :                         aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
     123           0 :                         Bitmap aMask = rAnimBitmap.aBmpEx.GetMask();
     124             : 
     125           0 :                         if(aMask.IsEmpty())
     126             :                         {
     127           0 :                             const Point aEmpty;
     128           0 :                             const Rectangle aRect(aEmpty, aVirtualDeviceMask.GetOutputSizePixel());
     129           0 :                             const Wallpaper aWallpaper(COL_BLACK);
     130           0 :                             aVirtualDeviceMask.DrawWallpaper(aRect, aWallpaper);
     131             :                         }
     132             :                         else
     133             :                         {
     134           0 :                             BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask);
     135           0 :                             aVirtualDeviceMask.DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask);
     136             :                         }
     137             : 
     138           0 :                         break;
     139             :                     }
     140             :                     case DISPOSE_BACK:
     141             :                     {
     142             :                         // #i70772# react on no mask, for primitives, too.
     143           0 :                         const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask());
     144           0 :                         const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap());
     145             : 
     146           0 :                         aVirtualDeviceMask.Erase();
     147           0 :                         aVirtualDevice.DrawBitmap(rAnimBitmap.aPosPix, aContent);
     148             : 
     149           0 :                         if(aMask.IsEmpty())
     150             :                         {
     151           0 :                             const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel());
     152           0 :                             aVirtualDeviceMask.SetFillColor(COL_BLACK);
     153           0 :                             aVirtualDeviceMask.SetLineColor();
     154           0 :                             aVirtualDeviceMask.DrawRect(aRect);
     155             :                         }
     156             :                         else
     157             :                         {
     158           0 :                             aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, aMask);
     159             :                         }
     160             : 
     161           0 :                         break;
     162             :                     }
     163             :                     case DISPOSE_FULL:
     164             :                     {
     165           0 :                         aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
     166           0 :                         break;
     167             :                     }
     168             :                     case DISPOSE_PREVIOUS :
     169             :                     {
     170           0 :                         aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx);
     171           0 :                         aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask());
     172           0 :                         break;
     173             :                     }
     174             :                 }
     175             : 
     176             :                 // create BitmapEx
     177           0 :                 Bitmap aMainBitmap = aVirtualDevice.GetBitmap(Point(), aVirtualDevice.GetOutputSizePixel());
     178             : #if defined(MACOSX) || defined(IOS)
     179             :                 AlphaMask aMaskBitmap( aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel()));
     180             : #else
     181           0 :                 Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel());
     182             : #endif
     183           0 :                 aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap);
     184             : 
     185             :                 // add to vector
     186           0 :                 maSteps.push_back(aNextStep);
     187           0 :             }
     188             :         }
     189           0 :     }
     190             : } // end of anonymous namespace
     191             : 
     192             : namespace drawinglayer
     193             : {
     194             :     namespace primitive2d
     195             :     {
     196         512 :         Primitive2DSequence create2DDecompositionOfGraphic(
     197             :             const Graphic& rGraphic,
     198             :             const basegfx::B2DHomMatrix& rTransform)
     199             :         {
     200         512 :             Primitive2DSequence aRetval;
     201             : 
     202         512 :             switch(rGraphic.GetType())
     203             :             {
     204             :                 case GRAPHIC_BITMAP :
     205             :                 {
     206         282 :                     if(rGraphic.IsAnimated())
     207             :                     {
     208             :                         // prepare animation data
     209           0 :                         animatedBitmapExPreparator aData(rGraphic);
     210             : 
     211           0 :                         if(aData.count())
     212             :                         {
     213             :                             // create sub-primitives for animated bitmap and the needed animation loop
     214           0 :                             animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff);
     215           0 :                             Primitive2DSequence aBitmapPrimitives(aData.count());
     216             : 
     217           0 :                             for(sal_uInt32 a(0); a < aData.count(); a++)
     218             :                             {
     219           0 :                                 animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count());
     220           0 :                                 aAnimationLoop.append(aTime);
     221           0 :                                 aBitmapPrimitives[a] = new BitmapPrimitive2D(
     222             :                                     aData.stepBitmapEx(a),
     223           0 :                                     rTransform);
     224           0 :                             }
     225             : 
     226             :                             // prepare animation list
     227           0 :                             animation::AnimationEntryList aAnimationList;
     228           0 :                             aAnimationList.append(aAnimationLoop);
     229             : 
     230             :                             // create and add animated switch primitive
     231           0 :                             aRetval.realloc(1);
     232           0 :                             aRetval[0] = new AnimatedSwitchPrimitive2D(
     233             :                                 aAnimationList,
     234             :                                 aBitmapPrimitives,
     235           0 :                                 false);
     236           0 :                         }
     237             :                     }
     238         282 :                     else if(rGraphic.getSvgData().get())
     239             :                     {
     240             :                         // embedded Svg fill, create embed transform
     241           2 :                         const basegfx::B2DRange& rSvgRange(rGraphic.getSvgData()->getRange());
     242             : 
     243           2 :                         if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0))
     244             :                         {
     245             :                             // translate back to origin, scale to unit coordinates
     246             :                             basegfx::B2DHomMatrix aEmbedSvg(
     247             :                                 basegfx::tools::createTranslateB2DHomMatrix(
     248           0 :                                     -rSvgRange.getMinX(),
     249           0 :                                     -rSvgRange.getMinY()));
     250             : 
     251             :                             aEmbedSvg.scale(
     252           0 :                                 1.0 / rSvgRange.getWidth(),
     253           0 :                                 1.0 / rSvgRange.getHeight());
     254             : 
     255             :                             // apply created object transformation
     256           0 :                             aEmbedSvg = rTransform * aEmbedSvg;
     257             : 
     258             :                             // add Svg primitives embedded
     259           0 :                             aRetval.realloc(1);
     260           0 :                             aRetval[0] = new TransformPrimitive2D(
     261             :                                 aEmbedSvg,
     262           0 :                                 rGraphic.getSvgData()->getPrimitive2DSequence());
     263             :                         }
     264             :                     }
     265             :                     else
     266             :                     {
     267         280 :                         aRetval.realloc(1);
     268         840 :                         aRetval[0] = new BitmapPrimitive2D(
     269             :                             rGraphic.GetBitmapEx(),
     270         560 :                             rTransform);
     271             :                     }
     272             : 
     273         282 :                     break;
     274             :                 }
     275             : 
     276             :                 case GRAPHIC_GDIMETAFILE :
     277             :                 {
     278             :                     // create MetafilePrimitive2D
     279         230 :                     const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile();
     280             : 
     281         230 :                     aRetval.realloc(1);
     282         460 :                     aRetval[0] = new MetafilePrimitive2D(
     283             :                         rTransform,
     284         460 :                         rMetafile);
     285             : 
     286             :                     // #i100357# find out if clipping is needed for this primitive. Unfortunately,
     287             :                     // there exist Metafiles who's content is bigger than the proposed PrefSize set
     288             :                     // at them. This is an error, but we need to work around this
     289         230 :                     const Size aMetaFilePrefSize(rMetafile.GetPrefSize());
     290             :                     const Size aMetaFileRealSize(
     291             :                         const_cast< GDIMetaFile& >(rMetafile).GetBoundRect(
     292         230 :                             *Application::GetDefaultDevice()).GetSize());
     293             : 
     294         460 :                     if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth()
     295         230 :                         || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight())
     296             :                     {
     297             :                         // clipping needed. Embed to MaskPrimitive2D. Create children and mask polygon
     298          26 :                         basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon());
     299          26 :                         aMaskPolygon.transform(rTransform);
     300             : 
     301             :                         Primitive2DReference mask = new MaskPrimitive2D(
     302             :                             basegfx::B2DPolyPolygon(aMaskPolygon),
     303          52 :                             aRetval);
     304          52 :                         aRetval[0] = mask;
     305             :                     }
     306         230 :                     break;
     307             :                 }
     308             : 
     309             :                 default:
     310             :                 {
     311             :                     // nothing to create
     312           0 :                     break;
     313             :                 }
     314             :             }
     315             : 
     316         512 :             return aRetval;
     317             :         }
     318             : 
     319           0 :         Primitive2DSequence create2DColorModifierEmbeddingsAsNeeded(
     320             :             const Primitive2DSequence& rChildren,
     321             :             GraphicDrawMode aGraphicDrawMode,
     322             :             double fLuminance,
     323             :             double fContrast,
     324             :             double fRed,
     325             :             double fGreen,
     326             :             double fBlue,
     327             :             double fGamma,
     328             :             bool bInvert)
     329             :         {
     330           0 :             Primitive2DSequence aRetval;
     331             : 
     332           0 :             if(!rChildren.getLength())
     333             :             {
     334             :                 // no child content, done
     335           0 :                 return aRetval;
     336             :             }
     337             : 
     338             :             // set child content as retval; that is what will be used as child content in all
     339             :             // embeddings from here
     340           0 :             aRetval = rChildren;
     341             : 
     342           0 :             if(GRAPHICDRAWMODE_WATERMARK == aGraphicDrawMode)
     343             :             {
     344             :                 // this is solved by applying fixed values additionally to luminance
     345             :                 // and contrast, do it here and reset DrawMode to GRAPHICDRAWMODE_STANDARD
     346             :                 // original in svtools uses:
     347             :                 // #define WATERMARK_LUM_OFFSET        50
     348             :                 // #define WATERMARK_CON_OFFSET        -70
     349           0 :                 fLuminance = basegfx::clamp(fLuminance + 0.5, -1.0, 1.0);
     350           0 :                 fContrast = basegfx::clamp(fContrast - 0.7, -1.0, 1.0);
     351           0 :                 aGraphicDrawMode = GRAPHICDRAWMODE_STANDARD;
     352             :             }
     353             : 
     354             :             // DrawMode (GRAPHICDRAWMODE_WATERMARK already handled)
     355           0 :             switch(aGraphicDrawMode)
     356             :             {
     357             :                 case GRAPHICDRAWMODE_GREYS:
     358             :                 {
     359             :                     // convert to grey
     360             :                     const Primitive2DReference aPrimitiveGrey(
     361             :                         new ModifiedColorPrimitive2D(
     362             :                             aRetval,
     363             :                             basegfx::BColorModifierSharedPtr(
     364           0 :                                 new basegfx::BColorModifier_gray())));
     365             : 
     366           0 :                     aRetval = Primitive2DSequence(&aPrimitiveGrey, 1);
     367           0 :                     break;
     368             :                 }
     369             :                 case GRAPHICDRAWMODE_MONO:
     370             :                 {
     371             :                     // convert to mono (black/white with threshold 0.5)
     372             :                     const Primitive2DReference aPrimitiveBlackAndWhite(
     373             :                         new ModifiedColorPrimitive2D(
     374             :                             aRetval,
     375             :                             basegfx::BColorModifierSharedPtr(
     376           0 :                                 new basegfx::BColorModifier_black_and_white(0.5))));
     377             : 
     378           0 :                     aRetval = Primitive2DSequence(&aPrimitiveBlackAndWhite, 1);
     379           0 :                     break;
     380             :                 }
     381             :                 case GRAPHICDRAWMODE_WATERMARK:
     382             :                 {
     383             :                     OSL_ENSURE(false, "OOps, GRAPHICDRAWMODE_WATERMARK should already be handled (see above)");
     384             :                     // fallthrough intended
     385             :                 }
     386             :                 default: // case GRAPHICDRAWMODE_STANDARD:
     387             :                 {
     388             :                     // nothing to do
     389           0 :                     break;
     390             :                 }
     391             :             }
     392             : 
     393             :             // mnContPercent, mnLumPercent, mnRPercent, mnGPercent, mnBPercent
     394             :             // handled in a single call
     395           0 :             if(!basegfx::fTools::equalZero(fLuminance)
     396           0 :                 || !basegfx::fTools::equalZero(fContrast)
     397           0 :                 || !basegfx::fTools::equalZero(fRed)
     398           0 :                 || !basegfx::fTools::equalZero(fGreen)
     399           0 :                 || !basegfx::fTools::equalZero(fBlue))
     400             :             {
     401             :                 const Primitive2DReference aPrimitiveRGBLuminannceContrast(
     402             :                     new ModifiedColorPrimitive2D(
     403             :                         aRetval,
     404             :                         basegfx::BColorModifierSharedPtr(
     405             :                             new basegfx::BColorModifier_RGBLuminanceContrast(
     406             :                                 fRed,
     407             :                                 fGreen,
     408             :                                 fBlue,
     409             :                                 fLuminance,
     410           0 :                                 fContrast))));
     411             : 
     412           0 :                 aRetval = Primitive2DSequence(&aPrimitiveRGBLuminannceContrast, 1);
     413             :             }
     414             : 
     415             :             // gamma (boolean)
     416           0 :             if(!basegfx::fTools::equal(fGamma, 1.0))
     417             :             {
     418             :                 const Primitive2DReference aPrimitiveGamma(
     419             :                     new ModifiedColorPrimitive2D(
     420             :                         aRetval,
     421             :                         basegfx::BColorModifierSharedPtr(
     422             :                             new basegfx::BColorModifier_gamma(
     423           0 :                                 fGamma))));
     424             : 
     425           0 :                 aRetval = Primitive2DSequence(&aPrimitiveGamma, 1);
     426             :             }
     427             : 
     428             :             // invert (boolean)
     429           0 :             if(bInvert)
     430             :             {
     431             :                 const Primitive2DReference aPrimitiveInvert(
     432             :                     new ModifiedColorPrimitive2D(
     433             :                         aRetval,
     434             :                         basegfx::BColorModifierSharedPtr(
     435           0 :                             new basegfx::BColorModifier_invert())));
     436             : 
     437           0 :                 aRetval = Primitive2DSequence(&aPrimitiveInvert, 1);
     438             :             }
     439             : 
     440           0 :             return aRetval;
     441             :         }
     442             : 
     443             :     } // end of namespace primitive2d
     444        1143 : } // end of namespace drawinglayer
     445             : 
     446             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10