#include-once
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <GDIPlusConstants.au3>

Func _LEDTXT_Step(ByRef $aLed, $iDir = 1)
	$aLed[6] -= $aLed[8] * $iDir
	Select
		Case $aLed[6] + $aLed[7] < 0
			$aLed[6] = 0
		Case $aLed[6] > 0
			$aLed[6] = -$aLed[7]
	EndSelect
EndFunc   ;==>_LEDTXT_Step

Func _LEDTXT_Draw($aLed)
	Local $iPos = Round($aLed[6]) - Mod(Round($aLed[6]), $aLed[8])
	Switch $aLed[10]
		Case True
			Switch $iPos
				Case -$aLed[7] To -$aLed[7] + $aLed[4]
					_GDIPlus_GraphicsDrawImageRectRect($aLed[0], $aLed[1], -$iPos, 0, $iPos + $aLed[7], $aLed[5], $aLed[2], $aLed[3], $iPos + $aLed[7], $aLed[5])
					If $aLed[6] + $aLed[7] < $aLed[4] Then _GDIPlus_GraphicsDrawImageRectRect($aLed[0], $aLed[1], 0, 0, $aLed[4] - ($iPos + $aLed[7]), $aLed[5], $aLed[2] + $iPos + $aLed[7], $aLed[3], $aLed[4] - ($iPos + $aLed[7]), $aLed[5])
				Case Else
					_GDIPlus_GraphicsDrawImageRectRect($aLed[0], $aLed[1], -$iPos, 0, $aLed[4], $aLed[5], $aLed[2], $aLed[3], $aLed[4], $aLed[5])
			EndSwitch
		Case Else
			Switch $iPos
				Case -$aLed[7] To -$aLed[7] + $aLed[4]
					_WinAPI_BitBlt($aLed[0], $aLed[2], $aLed[3], $aLed[2] + $iPos + $aLed[7], $aLed[5], $aLed[1], -$iPos, 0, $MERGECOPY)
					If $aLed[6] + $aLed[7] < $aLed[4] Then _WinAPI_BitBlt($aLed[0], $aLed[2] + $iPos + $aLed[7], $aLed[3], $aLed[4] - ($iPos + $aLed[7]), $aLed[5], $aLed[1], 0, 0, $MERGECOPY)
				Case Else
					_WinAPI_BitBlt($aLed[0], $aLed[2], $aLed[3], $aLed[4], $aLed[5], $aLed[1], -$iPos, 0, $MERGECOPY)
			EndSwitch
	EndSwitch
EndFunc   ;==>_LEDTXT_Draw


Func _LEDTXT_Create_GdiPlus($hGui, $sText, $iX, $iY, $iW, $iH, $iType, $iLedW = 8, $iLedH = 8, $nLedOnCol1 = 0xFFFFAA00, $nLedOnCol2 = 0xFF000000, $nLedOffCol1 = 0xAA111122, $nLedOffCol2 = 0xAA000000, $nBkColor = 0xFF000000, $iDistW = 0, $iDistH = 0, $sFont = "Arial", $iTextSize = 0, $iTextOpt = 1, $iTextOffY = 0)
	Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
	Local $hLedOn = _LEDTXT_Create_Led($hGraphics, $iType, $iLedW - $iDistW, $iLedH - $iDistH, $nLedOnCol1, $nLedOnCol2)
	Local $hLedOff = _LEDTXT_Create_Led($hGraphics, $iType, $iLedW - $iDistW, $iLedH - $iDistH, $nLedOffCol1, $nLedOffCol2)
	Local $hLed, $iWidth
	$hLed = _LEDTXT_Create_Bmp($hGraphics, $sText, $iW, $iH, $iLedW, $iLedH, $hLedOn, $hLedOff, $iDistW, $iDistH, $sFont, $iTextSize, $iTextOpt, $iTextOffY, $nBkColor, $iWidth)
	Local $aReturn[11]
	$aReturn[0] = $hGraphics
	$aReturn[1] = $hLed
	$aReturn[2] = $iX
	$aReturn[3] = $iY
	$aReturn[4] = $iW
	$aReturn[5] = $iH
	$aReturn[6] = 0
	$aReturn[7] = $iWidth
	$aReturn[8] = $iLedW + $iDistW
	$aReturn[9] = 0
	$aReturn[10] = True ; True = _GdiPlus, False=_WinApi
	Return $aReturn
EndFunc   ;==>_LEDTXT_Create_GdiPlus



Func _LEDTXT_Create_Gdi($hGui, $sText, $iX, $iY, $iW, $iH, $iType, $iLedW = 8, $iLedH = 8, $nLedOnCol1 = 0xFFFFAA00, $nLedOnCol2 = 0xFF000000, $nLedOffCol1 = 0xAA111122, $nLedOffCol2 = 0xAA000000, $nBkColor = 0xFF000000, $iDistW = 0, $iDistH = 0, $sFont = "Arial", $iTextSize = 0, $iTextOpt = 1, $iTextOffY = 0)
	Local $bGdiStarted = True
	If Not $ghGDIPDll Then
		$bGdiStarted = False
		_GDIPlus_Startup()
	EndIf
	Local $hDC = _WinAPI_GetDC($hGui)
	Local $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC)
	Local $hLedOn = _LEDTXT_Create_Led($hGraphics, $iType, $iLedW - $iDistW, $iLedH - $iDistH, $nLedOnCol1, $nLedOnCol2)
	Local $hLedOff = _LEDTXT_Create_Led($hGraphics, $iType, $iLedW - $iDistW, $iLedH - $iDistH, $nLedOffCol1, $nLedOffCol2)
	Local $hLed, $iWidth
	$hLed = _LEDTXT_Create_Bmp($hGraphics, $sText, $iW, $iH, $iLedW, $iLedH, $hLedOn, $hLedOff, $iDistW, $iDistH, $sFont, $iTextSize, $iTextOpt, $iTextOffY, $nBkColor, $iWidth)

	Local $hBmpDC = _WinAPI_CreateCompatibleDC($hDC)
	Local $hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hLed)
	_WinAPI_SelectObject($hBmpDC, $hBmp)
	Local $hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hLed)
	Local $aReturn[11]
	$aReturn[0] = $hDC
	$aReturn[1] = $hBmpDC
	$aReturn[2] = $iX
	$aReturn[3] = $iY
	$aReturn[4] = $iW
	$aReturn[5] = $iH
	$aReturn[6] = 0
	$aReturn[7] = $iWidth
	$aReturn[8] = $iLedW + $iDistW
	$aReturn[9] = $hBmp ; zum späteren destroy?!
	$aReturn[10] = False ; True = _GdiPlus, False=_WinApi
	_GDIPlus_GraphicsDispose($hGraphics)
	If Not $bGdiStarted Then _GDIPlus_Shutdown()
	Return $aReturn
EndFunc   ;==>_LEDTXT_Create_Gdi



Func _LEDTXT_Destroy($aLed)
	Switch $aLed[10]
		Case True
			_GDIPlus_BitmapDispose($aLed[1])
			_GDIPlus_GraphicsDispose($aLed[0])
		Case Else
			_WinAPI_DeleteObject($aLed[9])
			_WinAPI_ReleaseDC(0, $aLed[1])
			_WinAPI_DeleteDC($aLed[0])
	EndSwitch
EndFunc   ;==>_LEDTXT_Destroy





Func _LEDTXT_Create_Bmp($hGraphics, $sText, $iW, $iH, $iLedW, $iLedH, $hLedOn, $hLedOff, $iDistW, $iDistH, $sFont, $iTextSize, $iTextOpt, $iTextOffY, $nBkColor, ByRef $iReturnW)
	$sText = StringReplace($sText, @LF, "")
	$iW -= Mod($iW, $iLedW + $iDistW)
	If Not $iTextSize Then $iTextSize = $iH
	Local $hFormat = _GDIPlus_StringFormatCreate()
	Local $hFamily = _GDIPlus_FontFamilyCreate($sFont)
	Local $hFont = _GDIPlus_FontCreate($hFamily, $iTextSize, $iTextOpt, 2)
	Local $tLayout = _GDIPlus_RectFCreate($iW, 0, 0, 0)
	Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $sText, $hFont, $tLayout, $hFormat)
	Local $iWidth = Ceiling(DllStructGetData($aInfo[0], "Width")) + $iW
	$iWidth -= Mod($iWidth, $iLedW + $iDistW)
	Local $iHeight = $iH;Ceiling(DllStructGetData($aInfo[0], "Height"))
	DllStructSetData($aInfo[0], "Y", $iTextOffY)
	Local $hBmpTxt = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
	Local $hBmpLed = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
	Local $hBmpTmp = _GDIPlus_BitmapCreateFromGraphics($iLedW, $iHeight, $hGraphics)
	Local $hGfxTxt = _GDIPlus_ImageGetGraphicsContext($hBmpTxt)
	Local $hGfxLed = _GDIPlus_ImageGetGraphicsContext($hBmpLed)
	Local $hGfxTmp = _GDIPlus_ImageGetGraphicsContext($hBmpTmp)
	Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
	_GDIPlus_GraphicsClear($hGfxTxt, 0xFF000000)
	If $nBkColor Then _GDIPlus_GraphicsClear($hGfxLed, $nBkColor)
	_GDIPlus_GraphicsDrawStringEx($hGfxTxt, $sText, $hFont, $aInfo[0], $hFormat, $hBrush)
	Local $BitmapData = _GDIPlus_BitmapLockBits($hBmpTxt, $iW, 0, $iWidth - $iW, $iHeight, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
	Local $Stride = DllStructGetData($BitmapData, "Stride")
	Local $Width = DllStructGetData($BitmapData, "Width")
	Local $Height = DllStructGetData($BitmapData, "Height")
	Local $Scan0 = DllStructGetData($BitmapData, "Scan0")
	Local $PixelData = DllStructCreate("ubyte lData[" & (Abs($Stride) * $Height - 1) & "]", $Scan0)
	If $hLedOff Then
		For $i = 0 To $Height - 1 Step $iLedH + $iDistH
			_GDIPlus_GraphicsDrawImage($hGfxTmp, $hLedOff, 0, $i)
		Next
		For $i = 0 To $iW - 1 Step $iLedW + $iDistW
			_GDIPlus_GraphicsDrawImage($hGfxLed, $hBmpTmp, $i, 0)
		Next
	EndIf
	For $col = 0 To $Width - 1 Step $iLedW + $iDistW
		If $hLedOff Then _GDIPlus_GraphicsDrawImage($hGfxLed, $hBmpTmp, $col + $iW, 0)
		For $row = 0 To $Height - 1 Step $iLedH + $iDistH
			If DllStructGetData($PixelData, 1, $row * $Stride + ($col * 4) + 1) Then _GDIPlus_GraphicsDrawImage($hGfxLed, $hLedOn, $col + $iW, $row)
		Next
	Next
	_GDIPlus_BitmapUnlockBits($hBmpTxt, $BitmapData)
	_GDIPlus_FontDispose($hFont)
	_GDIPlus_FontFamilyDispose($hFamily)
	_GDIPlus_StringFormatDispose($hFormat)
	_GDIPlus_BrushDispose($hBrush)
	_GDIPlus_BitmapDispose($hBmpTxt)
	_GDIPlus_GraphicsDispose($hGfxTxt)
	_GDIPlus_BitmapDispose($hBmpTmp)
	_GDIPlus_GraphicsDispose($hGfxTmp)
	_GDIPlus_GraphicsDispose($hGfxLed)
	$iReturnW = $iWidth
	Return $hBmpLed
EndFunc   ;==>_LEDTXT_Create_Bmp



Func _LEDTXT_Create_Led($hGraphics, $iType, $iWidth, $iHeight, $nColor1, $nColor2)
	If Not $nColor1 And Not $nColor2 Then Return 0
	Local $hBmp = _GDIPlus_BitmapCreateFromGraphics($iWidth + 1, $iHeight + 1, $hGraphics)
	Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hBmp)
	Switch $iType
		Case 0
			Local $hPen = _GDIPlus_PenCreate()
			Local $hPath = _GDIPlus_CreatePath()
			_GDIPlus_AddPathEllipse($hPath, 0, 0, $iWidth, $iHeight)
			Local $hBrushGrad = _GDIPlus_CreatePathGradientFromPath($hPath)
			_GDIPlus_SetLineGammaCorrection($hBrushGrad, True)
			_GDIPlus_SetPathGradientSurroundColorsWithCount($hBrushGrad, $nColor2)
			_GDIPlus_SetPathGradientCenterColor($hBrushGrad, $nColor1)
			_GDIPlus_FillPath($hGfx, $hBrushGrad, $hPath)
			_GDIPlus_ClosePathFigure($hPath)
			_GDIPlus_GraphicsDrawEllipse($hGfx, 0, 0, $iWidth, $iHeight, $hPen)
			_GDIPlus_PenDispose($hPen)
			_GDIPlus_BrushDispose($hBrushGrad)
			_GDIPlus_PathDispose($hPath)
		Case 1
			Local $hPen = _GDIPlus_PenCreate()
			Local $hPath = _GDIPlus_CreatePath()
			_GDIPlus_AddPathRectangle($hPath, 0, 0, $iWidth, $iHeight)
			Local $hBrushGrad = _GDIPlus_CreatePathGradientFromPath($hPath)
			_GDIPlus_SetLineGammaCorrection($hBrushGrad, True)
			_GDIPlus_SetPathGradientSurroundColorsWithCount($hBrushGrad, $nColor2)
			_GDIPlus_SetPathGradientCenterColor($hBrushGrad, $nColor1)
			_GDIPlus_FillPath($hGfx, $hBrushGrad, $hPath)
			_GDIPlus_ClosePathFigure($hPath)
			_GDIPlus_GraphicsDrawRect($hGfx, 0, 0, $iWidth, $iHeight, $hPen)
			_GDIPlus_PenDispose($hPen)
			_GDIPlus_BrushDispose($hBrushGrad)
			_GDIPlus_PathDispose($hPath)
		Case 2
			If $nColor1 Then
				Local $hBrush = _GDIPlus_BrushCreateSolid($nColor1)
				_GDIPlus_GraphicsFillEllipse($hGfx, 0, 0, $iWidth, $iHeight, $hBrush)
				_GDIPlus_BrushDispose($hBrush)
			EndIf
			If $nColor2 Then
				Local $hPen = _GDIPlus_PenCreate($nColor2)
				_GDIPlus_GraphicsDrawEllipse($hGfx, 0, 0, $iWidth, $iHeight, $hPen)
				_GDIPlus_PenDispose($hPen)
			EndIf
		Case 3
			If $nColor1 Then
				Local $hBrush = _GDIPlus_BrushCreateSolid($nColor1)
				_GDIPlus_GraphicsFillRect($hGfx, 0, 0, $iWidth, $iHeight, $hBrush)
				_GDIPlus_BrushDispose($hBrush)
			EndIf
			If $nColor2 Then
				Local $hPen = _GDIPlus_PenCreate($nColor2)
				_GDIPlus_GraphicsDrawRect($hGfx, 0, 0, $iWidth, $iHeight, $hPen)
				_GDIPlus_PenDispose($hPen)
			EndIf
	EndSwitch
	_GDIPlus_GraphicsDispose($hGfx)
	Return $hBmp
EndFunc   ;==>_LEDTXT_Create_Led


Func _GDIPlus_CreatePath($brushMode = 0)
	Local $hPath
	$hPath = DllCall($ghGDIPDll, "int", "GdipCreatePath", "int", $brushMode, "handle*", 0)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($hPath[0], 0, $hPath[2])
EndFunc   ;==>_GDIPlus_CreatePath

Func _GDIPlus_AddPathEllipse($hPath, $iX, $iY, $iWidth, $iHeight)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathEllipse", "handle", $hPath, "float", $iX, "float", $iY, "float", $iWidth, "float", $iHeight)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_AddPathEllipse


Func _GDIPlus_AddPathRectangle($hPath, $iX, $iY, $iWidth, $iHeight)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipAddPathRectangle", "handle", $hPath, "float", $iX, "float", $iY, "float", $iWidth, "float", $iHeight)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_AddPathRectangle


Func _GDIPlus_CreatePathGradientFromPath($hPath)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreatePathGradientFromPath", "handle", $hPath, "int*", 0)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[2])
EndFunc   ;==>_GDIPlus_CreatePathGradientFromPath

Func _GDIPlus_SetLineGammaCorrection($hBrush, $useGammaCorrection = True)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipSetLineGammaCorrection", "handle", $hBrush, "int", $useGammaCorrection)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_SetLineGammaCorrection

Func _GDIPlus_SetPathGradientCenterColor($hBrush, $iARGB)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipSetPathGradientCenterColor", "handle", $hBrush, "int", $iARGB)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_SetPathGradientCenterColor

Func _GDIPlus_FillPath($hGraphic, $hBrushGrad, $hPath)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipFillPath", "handle", $hGraphic, "handle", $hBrushGrad, "handle", $hPath)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_FillPath

Func _GDIPlus_SetPathGradientSurroundColorsWithCount($hBrush, $aArgb)
	Local $iI, $iCount, $aResult, $res, $x, $pArgb
	If IsArray($aArgb) Then
		$iCount = UBound($aArgb)
		$tArgb = DllStructCreate("int[" & $iCount & "]")
		$pArgb = DllStructGetPtr($tArgb)
		For $iI = 0 To $iCount - 1
			DllStructSetData($tArgb, 1, $aArgb[$iI], $iI + 1)
		Next
	Else
		$iCount = 1
		$tArgb = DllStructCreate("int")
		$pArgb = DllStructGetPtr($tArgb)
		DllStructSetData($tArgb, 1, $aArgb, 1)
	EndIf
	$aResult = DllCall($ghGDIPDll, "int", "GdipSetPathGradientSurroundColorsWithCount", "handle", $hBrush, "int", $pArgb, "int*", $iCount)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], $aResult[3], $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_SetPathGradientSurroundColorsWithCount

Func _GDIPlus_ClosePathFigure($hPath)
	Local $aResult = DllCall($ghGDIPDll, "int", "GdipClosePathFigure", "handle", $hPath)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_ClosePathFigure

Func _GDIPlus_PathDispose($hPath)
	Local $aResult = DllCall($ghGDIPDll, "uint", "GdipDeletePath", "handle", $hPath)
	If @error Then Return SetError(1, @error, 0)
	Return SetError($aResult[0], 0, $aResult[0] = 0)
EndFunc   ;==>_GDIPlus_PathDispose
