Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/canvas/source/directx/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 26 kB image not shown  

Quelle  dx_impltools.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <sal/config.h>

#include <algorithm>
#include <memory>
#include <vector>


#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/range/b2irectangle.hxx>
#include <basegfx/utils/canvastools.hxx>
#include <com/sun/star/geometry/IntegerRectangle2D.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <comphelper/diagnose_ex.hxx>

#include <canvas/canvastools.hxx>
#include <verifyinput.hxx>

#include "dx_canvas.hxx"
#include "dx_canvasbitmap.hxx"
#include "dx_canvasfont.hxx"
#include "dx_impltools.hxx"
#include "dx_linepolypolygon.hxx"
#include "dx_spritecanvas.hxx"
#include "dx_vcltools.hxx"


using namespace ::com::sun::star;


namespace dxcanvas::tools
{
        ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
        {
            LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );

            if( pPolyImpl )
            {
                return pPolyImpl->getPolyPolygon();
            }
            else
            {
                const sal_Int32 nPolys( xPoly->getNumberOfPolygons() );

                // not a known implementation object - try data source
                // interfaces
                uno::Reference< rendering::XBezierPolyPolygon2D > xBezierPoly(
                    xPoly,
                    uno::UNO_QUERY );

                if( xBezierPoly.is() )
                {
                    return ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence(
                        xBezierPoly->getBezierSegments( 0,
                                                        nPolys,
                                                        0,
                                                        -1 ) );
                }
                else
                {
                    uno::Reference< rendering::XLinePolyPolygon2D > xLinePoly(
                        xPoly,
                        uno::UNO_QUERY );

                    // no implementation class and no data provider
                    // found - contract violation.
                    ENSURE_ARG_OR_THROW( xLinePoly.is(),
                                     "VCLCanvas::polyPolygonFromXPolyPolygon2D(): Invalid input "
                                     "poly-polygon, cannot retrieve vertex data" );

                    return ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence(
                        xLinePoly->getPoints( 0,
                                              nPolys,
                                              0,
                                              -1 ) );
                }
            }
        }

        void setupGraphics( Gdiplus::Graphics& rGraphics )
        {
            // setup graphics with (somewhat arbitrary) defaults
            //rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighQuality );
            rGraphics.SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
            //rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeHighQualityBilinear ); // with prefiltering for shrinks
            rGraphics.SetInterpolationMode( Gdiplus::InterpolationModeBilinear );

            // #122683# Switched precedence of pixel offset
            // mode. Seemingly, polygon stroking needs
            // PixelOffsetModeNone to achieve visually pleasing
            // results, whereas all other operations (e.g. polygon
            // fills, bitmaps) look better with PixelOffsetModeHalf.
            rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeHalf ); // Pixel center at (0.5, 0.5) etc.
            //rGraphics.SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );

            //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighSpeed ); // no line/curve antialiasing
            //rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
            rGraphics.SetSmoothingMode( Gdiplus::SmoothingModeAntiAlias );
            //rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintAntiAlias );
            rGraphics.SetTextRenderingHint( Gdiplus::TextRenderingHintSystemDefault );
            rGraphics.SetPageUnit(Gdiplus::UnitPixel);
        }

        Gdiplus::Graphics* createGraphicsFromHDC(HDC aHDC)
        {
            Gdiplus::Graphics* pRet = new Gdiplus::Graphics(aHDC);
            setupGraphics( *pRet );
            return pRet;
        }

        GraphicsSharedPtr createGraphicsFromBitmap(const BitmapSharedPtr& rBitmap)
        {
            GraphicsSharedPtr pRet(Gdiplus::Graphics::FromImage(rBitmap.get()));
            if( pRet )
                setupGraphics( *pRet );
            return pRet;
        }

        void gdiPlusMatrixFromB2DHomMatrix( Gdiplus::Matrix& rGdiplusMatrix, const ::basegfx::B2DHomMatrix& rMatrix )
        {
            rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.get(0,0)),
                                        static_cast<Gdiplus::REAL>(rMatrix.get(1,0)),
                                        static_cast<Gdiplus::REAL>(rMatrix.get(0,1)),
                                        static_cast<Gdiplus::REAL>(rMatrix.get(1,1)),
                                        static_cast<Gdiplus::REAL>(rMatrix.get(0,2)),
                                        static_cast<Gdiplus::REAL>(rMatrix.get(1,2)) );
        }

        void gdiPlusMatrixFromAffineMatrix2D( Gdiplus::Matrix&                  rGdiplusMatrix,
                                              const geometry::AffineMatrix2D&   rMatrix )
        {
            rGdiplusMatrix.SetElements( static_cast<Gdiplus::REAL>(rMatrix.m00),
                                        static_cast<Gdiplus::REAL>(rMatrix.m10),
                                        static_cast<Gdiplus::REAL>(rMatrix.m01),
                                        static_cast<Gdiplus::REAL>(rMatrix.m11),
                                        static_cast<Gdiplus::REAL>(rMatrix.m02),
                                        static_cast<Gdiplus::REAL>(rMatrix.m12) );
        }

        namespace
        {
            // TODO(P2): Check whether this gets inlined. If not, make functor
            // out of it
            Gdiplus::PointF implGdiPlusPointFromRealPoint2D( const css::geometry::RealPoint2D&&nbsp;rPoint )
            {
                return Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.X),
                                        static_cast<Gdiplus::REAL>(rPoint.Y) );
            }

            void graphicsPathFromB2DPolygon( GraphicsPathSharedPtr const & rOutput,
                                             std::vector< Gdiplus::PointF >&  rPoints,
                                             const ::basegfx::B2DPolygon&       rPoly,
                                             bool bNoLineJoin)
            {
                const sal_uInt32 nPoints( rPoly.count() );

                if( nPoints < 2 )
                    return;

                rOutput->StartFigure();

                const bool bClosedPolygon( rPoly.isClosed() );

                if( rPoly.areControlPointsUsed() )
                {
                    // control points used -> for now, add all
                    // segments as curves to GraphicsPath

                    // If the polygon is closed, we need to add the
                    // first point, thus, one more (can't simply
                    // GraphicsPath::CloseFigure() it, since the last
                    // point cannot have any control points for GDI+)
                    rPoints.resize( 3*nPoints + (bClosedPolygon ? 1 : 0) );

                    sal_uInt32 nCurrOutput=0;
                    for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
                    {
                        const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
                        rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
                                                                  static_cast<Gdiplus::REAL>(rPoint.getY()) );

                        const ::basegfx::B2DPoint& rControlPointA( rPoly.getNextControlPoint( nCurrPoint ) );
                        rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointA.getX()),
                                                                  static_cast<Gdiplus::REAL>(rControlPointA.getY()) );

                        const ::basegfx::B2DPoint& rControlPointB( rPoly.getPrevControlPoint( (nCurrPoint + 1) % nPoints) );
                        rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rControlPointB.getX()),
                                                                  static_cast<Gdiplus::REAL>(rControlPointB.getY()) );
                    }

                    if( bClosedPolygon )
                    {
                        // add first point again (to be able to pass
                        // control points for the last point, see
                        // above)
                        const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint(0) );
                        rPoints[nCurrOutput++] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
                                                                  static_cast<Gdiplus::REAL>(rPoint.getY()) );

                        if(bNoLineJoin && nCurrOutput > 7)
                        {
                            for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
                            {
                                rOutput->StartFigure();
                                rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
                            }
                        }
                        else
                        {
                            rOutput->AddBeziers( rPoints.data(), nCurrOutput );
                        }
                    }
                    else
                    {
                        // GraphicsPath expects 3(n-1)+1 points (i.e. the
                        // last point must not have any trailing control
                        // points after it).
                        // Therefore, simply don't pass the last two
                        // points here.
                        if( nCurrOutput > 3 )
                        {
                            if(bNoLineJoin && nCurrOutput > 7)
                            {
                                for(sal_uInt32 a(3); a < nCurrOutput; a+=3)
                                {
                                    rOutput->StartFigure();
                                    rOutput->AddBezier(rPoints[a - 3], rPoints[a - 2], rPoints[a - 1], rPoints[a]);
                                }
                            }
                            else
                            {
                                rOutput->AddBeziers( rPoints.data(), nCurrOutput-2 );
                            }
                        }
                    }
                }
                else
                {
                    // no control points -> no curves, simply add
                    // straight lines to GraphicsPath
                    rPoints.resize( nPoints );

                    for( sal_uInt32 nCurrPoint=0; nCurrPoint<nPoints; ++nCurrPoint )
                    {
                        const ::basegfx::B2DPoint& rPoint( rPoly.getB2DPoint( nCurrPoint ) );
                        rPoints[nCurrPoint] = Gdiplus::PointF( static_cast<Gdiplus::REAL>(rPoint.getX()),
                                                               static_cast<Gdiplus::REAL>(rPoint.getY()) );
                    }

                    if(bNoLineJoin && nPoints > 2)
                    {
                        for(sal_uInt32 a(1); a < nPoints; a++)
                        {
                            rOutput->StartFigure();
                            rOutput->AddLine(rPoints[a - 1], rPoints[a]);
                        }

                        if(bClosedPolygon)
                        {
                            rOutput->StartFigure();
                            rOutput->AddLine(rPoints[nPoints - 1], rPoints[0]);
                        }
                    }
                    else
                    {
                        rOutput->AddLines( rPoints.data(), nPoints );
                    }
                }

                if( bClosedPolygon && !bNoLineJoin )
                    rOutput->CloseFigure();
            }
        }

        Gdiplus::Rect gdiPlusRectFromIntegerRectangle2D( const geometry::IntegerRectangle2D&&nbsp;rRect )
        {
            return Gdiplus::Rect( rRect.X1,
                                  rRect.Y1,
                                  rRect.X2 - rRect.X1,
                                  rRect.Y2 - rRect.Y1 );
        }

        Gdiplus::RectF gdiPlusRectFFromRectangle2D( const geometry::RealRectangle2D& rRect )
        {
            return Gdiplus::RectF( static_cast<Gdiplus::REAL>(rRect.X1),
                                   static_cast<Gdiplus::REAL>(rRect.Y1),
                                   static_cast<Gdiplus::REAL>(rRect.X2 - rRect.X1),
                                   static_cast<Gdiplus::REAL>(rRect.Y2 - rRect.Y1) );
        }

        RECT gdiRectFromB2IRect( const ::basegfx::B2IRange& rRect )
        {
            RECT aRect = {rRect.getMinX(),
                          rRect.getMinY(),
                          rRect.getMaxX(),
                          rRect.getMaxY()};

            return aRect;
        }

        geometry::RealPoint2D realPoint2DFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
        {
            return geometry::RealPoint2D( rPoint.X, rPoint.Y );
        }

        geometry::RealRectangle2D realRectangle2DFromGdiPlusRectF( const Gdiplus::RectF& ;rRect )
        {
            return geometry::RealRectangle2D( rRect.X, rRect.Y,
                                              rRect.X + rRect.Width,
                                              rRect.Y + rRect.Height );
        }

        ::basegfx::B2DPoint b2dPointFromGdiPlusPointF( const Gdiplus::PointF& rPoint )
        {
            return ::basegfx::B2DPoint( rPoint.X, rPoint.Y );
        }

        ::basegfx::B2DRange b2dRangeFromGdiPlusRectF( const Gdiplus::RectF& rRect )
        {
            return ::basegfx::B2DRange( rRect.X, rRect.Y,
                                        rRect.X + rRect.Width,
                                        rRect.Y + rRect.Height );
        }

        uno::Sequence< sal_Int8 > argbToIntSequence( Gdiplus::ARGB rColor )
        {
            // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
            return
            {
                static_cast<sal_Int8>((rColor >> 16) & 0xFF), // red
                static_cast<sal_Int8>((rColor >> 8) & 0xFF),  // green
                static_cast<sal_Int8>(rColor & 0xFF),         // blue
                static_cast<sal_Int8>((rColor >> 24) & 0xFF)  // alpha
            };
        }

        Gdiplus::ARGB sequenceToArgb( const uno::Sequence< sal_Int8 >& rColor )
        {
            ENSURE_OR_THROW( rColor.getLength() > 2,
                              "sequenceToArgb: need at least three channels" );

            // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
            Gdiplus::ARGB aColor;

            aColor = (static_cast<sal_uInt8>(rColor[0]) << 16) | (static_cast<sal_uInt8>(rColor[1]) << 8) | static_cast<sal_uInt8>(rColor[2]);

            if( rColor.getLength() > 3 )
                aColor |= static_cast<sal_uInt8>(rColor[3]) << 24;

            return aColor;
        }

        Gdiplus::ARGB sequenceToArgb( const uno::Sequence< double >& rColor )
        {
            ENSURE_OR_THROW( rColor.getLength() > 2,
                              "sequenceToColor: need at least three channels" );

            // TODO(F1): handle color space conversions, when defined on canvas/graphicDevice
            Gdiplus::ARGB aColor;

            ::canvas::tools::verifyRange(rColor[0],0.0,1.0);
            ::canvas::tools::verifyRange(rColor[1],0.0,1.0);
            ::canvas::tools::verifyRange(rColor[2],0.0,1.0);

            aColor =
                (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[0] ) ) << 16) |
                (static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[1] ) ) << 8) |
                static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[2] ) );

            if( rColor.getLength() > 3 )
            {
                ::canvas::tools::verifyRange(rColor[3],0.0,1.0);
                aColor |= static_cast<sal_uInt8>( ::basegfx::fround( 255*rColor[3] ) ) << 24;
            }

            return aColor;
        }

        GraphicsPathSharedPtr graphicsPathFromRealPoint2DSequence( const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
        {
            GraphicsPathSharedPtr pRes = std::make_shared<Gdiplus::GraphicsPath>();
            std::vector< Gdiplus::PointF > aPoints;

            for( uno::Sequence< geometry::RealPoint2D > const & seqPoints : points )
            {
                const sal_Int32 nCurrSize( seqPoints.getLength() );
                if( nCurrSize )
                {
                    aPoints.resize( nCurrSize );

                    // TODO(F1): Closed/open polygons

                    // convert from RealPoint2D array to Gdiplus::PointF array
                    std::transform( seqPoints.getConstArray(),
                                      seqPoints.getConstArray()+nCurrSize,
                                      aPoints.begin(),
                                      implGdiPlusPointFromRealPoint2D );

                    pRes->AddLines( aPoints.data(), nCurrSize );
                }
            }

            return pRes;
        }

        GraphicsPathSharedPtr graphicsPathFromB2DPolygon( const ::basegfx::B2DPolygon& rPoly, bool bNoLineJoin )
        {
            GraphicsPathSharedPtr               pRes = std::make_shared<Gdiplus::GraphicsPath>();
            std::vector< Gdiplus::PointF >    aPoints;

            graphicsPathFromB2DPolygon( pRes, aPoints, rPoly, bNoLineJoin );

            return pRes;
        }

        GraphicsPathSharedPtr graphicsPathFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly, bool bNoLineJoin )
        {
            GraphicsPathSharedPtr               pRes = std::make_shared<Gdiplus::GraphicsPath>();
            std::vector< Gdiplus::PointF >    aPoints;

            const sal_uInt32 nPolies( rPoly.count() );
            for( sal_uInt32 nCurrPoly=0; nCurrPoly<nPolies; ++nCurrPoly )
            {
                graphicsPathFromB2DPolygon( pRes,
                                            aPoints,
                                            rPoly.getB2DPolygon( nCurrPoly ),
                                            bNoLineJoin);
            }

            return pRes;
        }

        GraphicsPathSharedPtr graphicsPathFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly, bool bNoLineJoin )
        {
            LinePolyPolygon* pPolyImpl = dynamic_cast< LinePolyPolygon* >( xPoly.get() );

            if( pPolyImpl )
            {
                return pPolyImpl->getGraphicsPath( bNoLineJoin );
            }
            else
            {
                return tools::graphicsPathFromB2DPolyPolygon(
                    polyPolygonFromXPolyPolygon2D( xPoly ), bNoLineJoin );
            }
        }

        bool drawGdiPlusBitmap( const GraphicsSharedPtr& rGraphics,
                                const BitmapSharedPtr&   rBitmap )
        {
            Gdiplus::PointF aPoint;
            return (Gdiplus::Ok == rGraphics->DrawImage( rBitmap.get(),
                                                         aPoint ) );
        }

        bool drawDIBits( const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
                         const BITMAPINFO&        rBI,
                         const void*              pBits )
        {
            BitmapSharedPtr pBitmap(
                Gdiplus::Bitmap::FromBITMAPINFO( &rBI,
                                                 const_cast<void*>(pBits) ) );

            return drawGdiPlusBitmap( rGraphics,
                                      pBitmap );
        }

        bool drawRGBABits( const std::shared_ptr<Gdiplus::Graphics>& rGraphics,
                           const RawRGBABitmap&     rRawRGBAData )
        {
            BitmapSharedPtr pBitmap = std::make_shared<Gdiplus::Bitmap>( rRawRGBAData.mnWidth,
                                                          rRawRGBAData.mnHeight,
                                                          PixelFormat32bppARGB );

            Gdiplus::BitmapData aBmpData;
            aBmpData.Width       = rRawRGBAData.mnWidth;
            aBmpData.Height      = rRawRGBAData.mnHeight;
            aBmpData.Stride      = 4*aBmpData.Width; // bottom-up format
            aBmpData.PixelFormat = PixelFormat32bppARGB;
            aBmpData.Scan0       = const_cast<sal_uInt8*>(rRawRGBAData.maBitmapData.data());

            const Gdiplus::Rect aRect( 0,0,aBmpData.Width,aBmpData.Height );
            if( Gdiplus::Ok != pBitmap->LockBits( &aRect,
                                                  Gdiplus::ImageLockModeWrite | Gdiplus::ImageLockModeUserInputBuf,
                                                  PixelFormat32bppARGB,
                                                  &aBmpData ) )
            {
                return false;
            }

            // commit data to bitmap
            pBitmap->UnlockBits( &aBmpData );

            return drawGdiPlusBitmap( rGraphics,
                                      pBitmap );
        }

        BitmapSharedPtr bitmapFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
        {
            BitmapProvider* pBitmapProvider = dynamic_cast< BitmapProvider* >(xBitmap.get());

            if( pBitmapProvider )
            {
                IBitmapSharedPtr pBitmap( pBitmapProvider->getBitmap() );
                return pBitmap->getBitmap();
            }
            else
            {
                // not a native CanvasBitmap, extract VCL bitmap and
                // render into GDI+ bitmap of similar size
                // =================================================

                const geometry::IntegerSize2D aBmpSize( xBitmap->getSize() );
                BitmapSharedPtr               pBitmap;

                if( xBitmap->hasAlpha() )
                {
                    // TODO(P2): At least for the alpha bitmap case, it
                    // would be possible to generate the corresponding
                    // bitmap directly
                    pBitmap = std::make_shared<Gdiplus::Bitmap>( aBmpSize.Width,
                                                        aBmpSize.Height,
                                                        PixelFormat32bppARGB );
                }
                else
                {
                    // TODO(F2): Might be wise to create bitmap compatible
                    // to the VCL bitmap. Also, check whether the VCL
                    // bitmap's system handles can be used to create the
                    // GDI+ bitmap (currently, it does not seem so).
                    pBitmap = std::make_shared<Gdiplus::Bitmap>( aBmpSize.Width,
                                                        aBmpSize.Height,
                                                        PixelFormat24bppRGB );
                }

                GraphicsSharedPtr pGraphics(createGraphicsFromBitmap(pBitmap));
                tools::setupGraphics(*pGraphics);
                if( !drawVCLBitmapFromXBitmap(
                        pGraphics,
                        xBitmap) )
                {
                    pBitmap.reset();
                }

                return pBitmap;
            }
        }

        CanvasFont::ImplRef canvasFontFromXFont( const uno::Reference< rendering::XCanvasFont >&&nbsp;xFont )
        {
            CanvasFont* pCanvasFont = dynamic_cast< CanvasFont* >(xFont.get());

            ENSURE_ARG_OR_THROW( pCanvasFont,
                             "canvasFontFromXFont(): Invalid XFont (or incompatible font for this XCanvas)" );

            return CanvasFont::ImplRef( pCanvasFont );
        }

        void setModulateImageAttributes( Gdiplus::ImageAttributes& o_rAttr,
                                         double                    nRedModulation,
                                         double                    nGreenModulation,
                                         double                    nBlueModulation,
                                         double                    nAlphaModulation )
        {
            // This gets rather verbose, but we have to setup a color
            // transformation matrix, in order to incorporate the global
            // alpha value mfAlpha into the bitmap rendering.
            Gdiplus::ColorMatrix     aColorMatrix;

            aColorMatrix.m[0][0] = static_cast<Gdiplus::REAL>(nRedModulation);
            aColorMatrix.m[0][1] = 0.0;
            aColorMatrix.m[0][2] = 0.0;
            aColorMatrix.m[0][3] = 0.0;
            aColorMatrix.m[0][4] = 0.0;

            aColorMatrix.m[1][0] = 0.0;
            aColorMatrix.m[1][1] = static_cast<Gdiplus::REAL>(nGreenModulation);
            aColorMatrix.m[1][2] = 0.0;
            aColorMatrix.m[1][3] = 0.0;
            aColorMatrix.m[1][4] = 0.0;

            aColorMatrix.m[2][0] = 0.0;
            aColorMatrix.m[2][1] = 0.0;
            aColorMatrix.m[2][2] = static_cast<Gdiplus::REAL>(nBlueModulation);
            aColorMatrix.m[2][3] = 0.0;
            aColorMatrix.m[2][4] = 0.0;

            aColorMatrix.m[3][0] = 0.0;
            aColorMatrix.m[3][1] = 0.0;
            aColorMatrix.m[3][2] = 0.0;
            aColorMatrix.m[3][3] = static_cast<Gdiplus::REAL>(nAlphaModulation);
            aColorMatrix.m[3][4] = 0.0;

            aColorMatrix.m[4][0] = 0.0;
            aColorMatrix.m[4][1] = 0.0;
            aColorMatrix.m[4][2] = 0.0;
            aColorMatrix.m[4][3] = 0.0;
            aColorMatrix.m[4][4] = 1.0;

            o_rAttr.SetColorMatrix( &aColorMatrix );
        }

// namespace dxcanvas::tools

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=90 H=93 G=91

¤ Dauer der Verarbeitung: 0.23 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.