/**************************************************************
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

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

#include <stdio.h>
#include <string.h>
#include <tools/svwin.h>
#include <tools/debug.hxx>
#include <win/wincomp.hxx>
#include <win/saldata.hxx>
#include <win/salgdi.h>
#include <win/salbmp.h>

#ifndef min
#define min(a,b)	(((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b)	(((a) > (b)) ? (a) : (b))
#endif

#if defined _MSC_VER
#pragma warning(push, 1)
#endif

#include <GdiPlus.h>
#include <GdiPlusEnums.h>
#include <GdiPlusColor.h>

#if defined _MSC_VER
#pragma warning(pop)
#endif

#include <basegfx/polygon/b2dpolygon.hxx>

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

void impAddB2DPolygonToGDIPlusGraphicsPathReal(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
{
    sal_uInt32 nCount(rPolygon.count());

    if(nCount)
    {
        const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1);
        const bool bControls(rPolygon.areControlPointsUsed());
        basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
        Gdiplus::PointF aFCurr(Gdiplus::REAL(aCurr.getX()), Gdiplus::REAL(aCurr.getY()));

        for(sal_uInt32 a(0); a < nEdgeCount; a++)
        {
	        const sal_uInt32 nNextIndex((a + 1) % nCount);
	        const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
	        const Gdiplus::PointF aFNext(Gdiplus::REAL(aNext.getX()), Gdiplus::REAL(aNext.getY()));

	        if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex)))
	        {
		        const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
		        const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));

		        rPath.AddBezier(
			        aFCurr, 
			        Gdiplus::PointF(Gdiplus::REAL(aCa.getX()), Gdiplus::REAL(aCa.getY())),
			        Gdiplus::PointF(Gdiplus::REAL(aCb.getX()), Gdiplus::REAL(aCb.getY())),
			        aFNext);
	        }
	        else
	        {
		        rPath.AddLine(aFCurr, aFNext);
	        }

	        if(a + 1 < nEdgeCount)
	        {
		        aFCurr = aFNext;

			    if(bNoLineJoin)
			    {
				    rPath.StartFigure();
			    }
	        }
        }
    }
}

void impAddB2DPolygonToGDIPlusGraphicsPathInteger(Gdiplus::GraphicsPath& rPath, const basegfx::B2DPolygon& rPolygon, bool bNoLineJoin)
{
    sal_uInt32 nCount(rPolygon.count());

    if(nCount)
    {
        const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nCount : nCount - 1);
        const bool bControls(rPolygon.areControlPointsUsed());
        basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
        Gdiplus::Point aICurr(INT(aCurr.getX()), INT(aCurr.getY()));

        for(sal_uInt32 a(0); a < nEdgeCount; a++)
        {
	        const sal_uInt32 nNextIndex((a + 1) % nCount);
	        const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
	        const Gdiplus::Point aINext(INT(aNext.getX()), INT(aNext.getY()));

	        if(bControls && (rPolygon.isNextControlPointUsed(a) || rPolygon.isPrevControlPointUsed(nNextIndex)))
	        {
		        const basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
		        const basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));

		        rPath.AddBezier(
			        aICurr, 
			        Gdiplus::Point(INT(aCa.getX()), INT(aCa.getY())),
			        Gdiplus::Point(INT(aCb.getX()), INT(aCb.getY())),
			        aINext);
	        }
	        else
	        {
		        rPath.AddLine(aICurr, aINext);
	        }

	        if(a + 1 < nEdgeCount)
	        {
		        aICurr = aINext;

			    if(bNoLineJoin)
			    {
				    rPath.StartFigure();
			    }
	        }
        }
    }
}

bool WinSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
{
	const sal_uInt32 nCount(rPolyPolygon.count());

	if(mbBrush && nCount && (fTransparency >= 0.0 && fTransparency < 1.0))
	{
		Gdiplus::Graphics aGraphics(getHDC());
		const sal_uInt8 aTrans((sal_uInt8)255 - (sal_uInt8)basegfx::fround(fTransparency * 255.0));
		Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maFillColor), SALCOLOR_GREEN(maFillColor), SALCOLOR_BLUE(maFillColor));
		Gdiplus::SolidBrush aTestBrush(aTestColor);
		Gdiplus::GraphicsPath aPath;

		for(sal_uInt32 a(0); a < nCount; a++)
		{
            if(0 != a)
            {
                aPath.StartFigure(); // #i101491# not needed for first run
            }

			impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolyPolygon.getB2DPolygon(a), false);
            aPath.CloseFigure();
		}

        if(getAntiAliasB2DDraw())
        {
            aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        }
        else
        {
    		aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
        }

        if(mbPrinter)
        {
            // #121591#
            // Normally GdiPlus should not be used for printing at all since printers cannot
            // print transparent filled polygon geometry and normally this does not happen
            // since OutputDevice::RemoveTransparenciesFromMetaFile is used as preparation
            // and no transparent parts should remain for printing. But this can be overriden
            // by the user and thus happens. This call can only come (currently) from 
            // OutputDevice::DrawTransparent, see comments sthere with the same TaskID.
            // If it is used, the mapping for the printer is wrong and needs to be corrected. I
            // checked that there is *no* transformation set (testcode commented out below) and
            // estimated that a stable factor dependent of the printer's DPI is used. Create
            // and set a transformation here to correct this
            const Gdiplus::REAL aDpiX(aGraphics.GetDpiX());
            const Gdiplus::REAL aDpiY(aGraphics.GetDpiY());

            // test code to check the current transformation at the graphics device
            //Gdiplus::Matrix matrix;
            //aGraphics.GetTransform(&matrix);
            //Gdiplus::REAL elements[6];
            //matrix.GetElements(elements);

            Gdiplus::Matrix aPrinterTransform;
            aPrinterTransform.Scale(Gdiplus::REAL(100.0) / aDpiX, Gdiplus::REAL(100.0) / aDpiY);
            aGraphics.SetTransform(&aPrinterTransform);
        }

		aGraphics.FillPath(&aTestBrush, &aPath);
	}

 	return true;
}

bool WinSalGraphics::drawPolyLine( 
    const basegfx::B2DPolygon& rPolygon, 
    double fTransparency, 
    const basegfx::B2DVector& rLineWidths, 
    basegfx::B2DLineJoin eLineJoin,
    com::sun::star::drawing::LineCap eLineCap)
{
    const sal_uInt32 nCount(rPolygon.count());

	if(mbPen && nCount)
	{
		Gdiplus::Graphics aGraphics(getHDC());
		const sal_uInt8 aTrans = (sal_uInt8)basegfx::fround( 255 * (1.0 - fTransparency) );
		Gdiplus::Color aTestColor(aTrans, SALCOLOR_RED(maLineColor), SALCOLOR_GREEN(maLineColor), SALCOLOR_BLUE(maLineColor));
		Gdiplus::Pen aTestPen(aTestColor, Gdiplus::REAL(rLineWidths.getX()));
		Gdiplus::GraphicsPath aPath;
		bool bNoLineJoin(false);

		switch(eLineJoin)
		{
			default : // basegfx::B2DLINEJOIN_NONE :
			{
				if(basegfx::fTools::more(rLineWidths.getX(), 0.0))
				{
					bNoLineJoin = true;
				}
				break;
			}
			case basegfx::B2DLINEJOIN_BEVEL :
			{
				aTestPen.SetLineJoin(Gdiplus::LineJoinBevel);
				break;
			}
			case basegfx::B2DLINEJOIN_MIDDLE :
			case basegfx::B2DLINEJOIN_MITER :
			{
				const Gdiplus::REAL aMiterLimit(15.0);
				aTestPen.SetMiterLimit(aMiterLimit);
				aTestPen.SetLineJoin(Gdiplus::LineJoinMiter);
				break;
			}
			case basegfx::B2DLINEJOIN_ROUND :
			{
				aTestPen.SetLineJoin(Gdiplus::LineJoinRound);
				break;
			}
		}

        switch(eLineCap)
        {
            default: /*com::sun::star::drawing::LineCap_BUTT*/
            {
                // nothing to do
                break;
            }
            case com::sun::star::drawing::LineCap_ROUND:
            {
                aTestPen.SetStartCap(Gdiplus::LineCapRound);
                aTestPen.SetEndCap(Gdiplus::LineCapRound);
                break;
            }
            case com::sun::star::drawing::LineCap_SQUARE:
            {
                aTestPen.SetStartCap(Gdiplus::LineCapSquare);
                aTestPen.SetEndCap(Gdiplus::LineCapSquare);
                break;
            }
        }

		if(nCount > 250 && basegfx::fTools::more(rLineWidths.getX(), 1.5))
        {
    		impAddB2DPolygonToGDIPlusGraphicsPathInteger(aPath, rPolygon, bNoLineJoin);
        }
        else
        {
    		impAddB2DPolygonToGDIPlusGraphicsPathReal(aPath, rPolygon, bNoLineJoin);
        }

        if(rPolygon.isClosed() && !bNoLineJoin)
        {
            // #i101491# needed to create the correct line joins
            aPath.CloseFigure();
        }
		
        if(getAntiAliasB2DDraw())
        {
    		aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
        }
        else
        {
    		aGraphics.SetSmoothingMode(Gdiplus::SmoothingModeNone);
        }

		aGraphics.DrawPath(&aTestPen, &aPath);
	}

	return true;
}

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

void paintToGdiPlus(
    Gdiplus::Graphics& rGraphics,
    const SalTwoRect& rTR,
    Gdiplus::Bitmap& rBitmap)
{
    // only parts of source are used
    Gdiplus::PointF aDestPoints[3];
    Gdiplus::ImageAttributes aAttributes;

    // define target region as paralellogram
    aDestPoints[0].X = Gdiplus::REAL(rTR.mnDestX);
    aDestPoints[0].Y = Gdiplus::REAL(rTR.mnDestY);
    aDestPoints[1].X = Gdiplus::REAL(rTR.mnDestX + rTR.mnDestWidth);
    aDestPoints[1].Y = Gdiplus::REAL(rTR.mnDestY);
    aDestPoints[2].X = Gdiplus::REAL(rTR.mnDestX);
    aDestPoints[2].Y = Gdiplus::REAL(rTR.mnDestY + rTR.mnDestHeight);

    aAttributes.SetWrapMode(Gdiplus::WrapModeTileFlipXY);

    rGraphics.DrawImage(
        &rBitmap, 
        aDestPoints,
        3,
        Gdiplus::REAL(rTR.mnSrcX),
        Gdiplus::REAL(rTR.mnSrcY),
        Gdiplus::REAL(rTR.mnSrcWidth),
        Gdiplus::REAL(rTR.mnSrcHeight),
        Gdiplus::UnitPixel,
        &aAttributes,
        0,
        0);
}

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

void setInterpolationMode(
    Gdiplus::Graphics& rGraphics,
    const long& rSrcWidth,
    const long& rDestWidth,
    const long& rSrcHeight,
    const long& rDestHeight)
{
    const bool bSameWidth(rSrcWidth == rDestWidth);
    const bool bSameHeight(rSrcHeight == rDestHeight);

    if(bSameWidth && bSameHeight)
    {
        rGraphics.SetInterpolationMode(Gdiplus::InterpolationModeInvalid);
    }
    else if(rDestWidth > rSrcWidth && rDestHeight > rSrcHeight)
    {
        rGraphics.SetInterpolationMode(Gdiplus::InterpolationModeDefault);
    }
    else if(rDestWidth < rSrcWidth && rDestHeight < rSrcHeight)
    {
        rGraphics.SetInterpolationMode(Gdiplus::InterpolationModeBicubic);
    }
    else
    {
        rGraphics.SetInterpolationMode(Gdiplus::InterpolationModeDefault);
    }
}


bool WinSalGraphics::tryDrawBitmapGdiPlus(const SalTwoRect& rTR, const SalBitmap& rSrcBitmap)
{
    if(rTR.mnSrcWidth && rTR.mnSrcHeight && rTR.mnDestWidth && rTR.mnDestHeight)
    {
        const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSrcBitmap);
        GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap());

        if(aARGB.get())
        {
            Gdiplus::Graphics aGraphics(getHDC());

            setInterpolationMode(
                aGraphics, 
                rTR.mnSrcWidth,
                rTR.mnDestWidth, 
                rTR.mnSrcHeight,
                rTR.mnDestHeight);

            paintToGdiPlus(
                aGraphics, 
                rTR, 
                *aARGB.get());

            return true;
        }
    }

    return false;
}

bool WinSalGraphics::drawAlphaBitmap( 
    const SalTwoRect& rTR,
    const SalBitmap& rSrcBitmap, 
    const SalBitmap& rAlphaBmp)
{
    if(rTR.mnSrcWidth && rTR.mnSrcHeight && rTR.mnDestWidth && rTR.mnDestHeight)
    {
        const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSrcBitmap);
        const WinSalBitmap& rSalAlpha = static_cast< const WinSalBitmap& >(rAlphaBmp);
        GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap(&rSalAlpha));

        if(aARGB.get())
        {
            Gdiplus::Graphics aGraphics(getHDC());

            setInterpolationMode(
                aGraphics, 
                rTR.mnSrcWidth,
                rTR.mnDestWidth, 
                rTR.mnSrcHeight,
                rTR.mnDestHeight);

            paintToGdiPlus(
                aGraphics, 
                rTR, 
                *aARGB.get());

            return true;
        }
    }

    return false;
}

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

bool WinSalGraphics::drawTransformedBitmap(
    const basegfx::B2DPoint& rNull,
    const basegfx::B2DPoint& rX,
    const basegfx::B2DPoint& rY,
    const SalBitmap& rSourceBitmap,
    const SalBitmap* pAlphaBitmap)
{
    const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSourceBitmap);
    const WinSalBitmap* pSalAlpha = static_cast< const WinSalBitmap* >(pAlphaBitmap);
    GdiPlusBmpPtr aARGB(rSalBitmap.ImplGetGdiPlusBitmap(pSalAlpha));

    if(aARGB.get())
    {
        const long nSrcWidth(aARGB->GetWidth());
        const long nSrcHeight(aARGB->GetHeight());

        if(nSrcWidth && nSrcHeight)
        {
            const long nDestWidth(basegfx::fround(basegfx::B2DVector(rX - rNull).getLength()));
            const long nDestHeight(basegfx::fround(basegfx::B2DVector(rY - rNull).getLength()));

            if(nDestWidth && nDestHeight)
            {
                Gdiplus::Graphics aGraphics(getHDC());
                Gdiplus::PointF aDestPoints[3];
                Gdiplus::ImageAttributes aAttributes;

                setInterpolationMode(
                    aGraphics, 
                    nSrcWidth,
                    nDestWidth, 
                    nSrcHeight,
                    nDestHeight);

                // this mode is only capable of drawing the whole bitmap to a paralellogram
                aDestPoints[0].X = Gdiplus::REAL(rNull.getX());
                aDestPoints[0].Y = Gdiplus::REAL(rNull.getY());
                aDestPoints[1].X = Gdiplus::REAL(rX.getX());
                aDestPoints[1].Y = Gdiplus::REAL(rX.getY());
                aDestPoints[2].X = Gdiplus::REAL(rY.getX());
                aDestPoints[2].Y = Gdiplus::REAL(rY.getY());

                aAttributes.SetWrapMode(Gdiplus::WrapModeTileFlipXY);

                aGraphics.DrawImage(
                    aARGB.get(), 
                    aDestPoints, 
                    3,
                    Gdiplus::REAL(0.0),
                    Gdiplus::REAL(0.0),
                    Gdiplus::REAL(nSrcWidth),
                    Gdiplus::REAL(nSrcHeight),
                    Gdiplus::UnitPixel,
                    &aAttributes,
                    0,
                    0);
            }
        }

        return true;
    }

    return false;
}

// -----------------------------------------------------------------------
// eof
