#include <GDIP.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

_CheckGDIpWarpBug("GDIp.au3")

Opt("GUIOnEventMode", 1)

_GDIPlus_Startup()

$iW = 600
$iH = 600

$hGui = GUICreate("GDI+ Rotated Letters by Eukalyptus", $iW, $iH)
GUISetOnEvent(-3, "_Exit")
GUISetState()

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphics)
$hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
_GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
_GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

$hBrush = _GDIPlus_BrushCreateSolid(0xFFFFAA00)
$hBrushTrans = _GDIPlus_BrushCreateSolid(0x66000000)

$sText = "Rotated Letters by Eukalyptus ;-)"

$hPath = _CreateTextPath($sText, 400, "Impact", 110)

$hMatrix = _GDIPlus_MatrixCreate()

GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND")

Global $aPoints[5][2]
$aPoints[0][0] = 4
$aPoints[1][0] = $iW / 2 - $iW * 0.2
$aPoints[1][1] = $iH / 2 - $iH * 0.2
$aPoints[2][0] = $iW / 2 + $iW * 0.2
$aPoints[2][1] = $iH / 2 - $iH * 0.2
$aPoints[3][0] = 0
$aPoints[3][1] = $iH
$aPoints[4][0] = $iW
$aPoints[4][1] = $iH

While 1
    _RotateMatrix()

    $hPathClone = _GDIPlus_PathClone($hPath)
    _GDIPlus_PathTransform($hPathClone, $hMatrix)
    _GDIPlus_PathWarp($hPathClone, 0, $aPoints, 0, 0, $iW, $iH + $iH * 0.3)

    _GDIPlus_GraphicsFillRect($hGfxBuffer, 0, 0, $iW, $iH, $hBrushTrans)
    _GDIPlus_GraphicsFillPath($hGfxBuffer, $hPathClone, $hBrush)

    _GDIPlus_PathDispose($hPathClone)

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    ;Sleep(10)
WEnd


Func _RotateMatrix()
    Local Static $iStep = 0
    $iStep += 0.003
    _GDIPlus_MatrixSetElements($hMatrix, 1, 0, 0, 1, 0, 0)
    _GDIPlus_MatrixTranslate($hMatrix, $iW / 2, $iH / 2)
    _GDIPlus_MatrixRotate($hMatrix, -(Sin($iStep) * 360))
    _GDIPlus_MatrixTranslate($hMatrix, -$iW / 2, -$iH / 2)
EndFunc   ;==>_RotateMatrix



Func _CreateTextPath($sText, $iR, $sFont, $fSize)
    Local $hPath = _GDIPlus_PathCreate()

    Local $hFormat = _GDIPlus_StringFormatCreate()
    Local $hFamily = _GDIPlus_FontFamilyCreate("Arial")
    Local $tLayout = _GDIPlus_RectFCreate(0, 0, 0, 0)

    Local $aSplit = StringSplit($sText, "")
    Local $aPath[$aSplit[0] + 1][2]
    Local $aBounds, $iLen = 0

    Local $hMatrix = _GDIPlus_MatrixCreate()

    For $i = 1 To $aSplit[0]
        $aPath[$i][0] = _GDIPlus_PathCreate()
        _GDIPlus_PathAddString($aPath[$i][0], $aSplit[$i], $tLayout, $hFamily, 0, $fSize, $hFormat)
        $aBounds = _GDIPlus_PathGetWorldBounds($aPath[$i][0])
        $aPath[$i][1] = $aBounds[2]
        If $aSplit[$i] = " " Then $aPath[$i][1] = $fSize / 3
        $iLen += $aPath[$i][1]
        _GDIPlus_MatrixTranslate($hMatrix, $iW / 2 - $aBounds[2], $iH / 2 - $iR)
        _GDIPlus_PathTransform($aPath[$i][0], $hMatrix)
        _GDIPlus_MatrixSetElements($hMatrix, 1, 0, 0, 1, 0, 0)
    Next

    For $i = 1 To $aSplit[0]
        _GDIPlus_MatrixTranslate($hMatrix, $iW / 2, $iH / 2)
        _GDIPlus_MatrixRotate($hMatrix, -($aPath[$i][1] * 340 / $iLen))
        _GDIPlus_MatrixTranslate($hMatrix, -$iW / 2, -$iH / 2)
        _GDIPlus_PathTransform($hPath, $hMatrix)

        _GDIPlus_PathAddPath($hPath, $aPath[$i][0], False)

        _GDIPlus_MatrixSetElements($hMatrix, 1, 0, 0, 1, 0, 0)
    Next

    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)

    _GDIPlus_MatrixDispose($hMatrix)
    For $i = 1 To $aSplit[0]
        _GDIPlus_PathDispose($aPath[$i][0])
    Next
    Return $hPath
EndFunc   ;==>_CreateTextPath


Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_PAINT

Func WM_ERASEBKGND($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return True
EndFunc   ;==>WM_ERASEBKGND



Func _Exit()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BrushDispose($hBrushTrans)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>_Exit


Func _CheckGDIpWarpBug($sPath)
    If Not FileExists($sPath) Then
        MsgBox(0, "error", $sPath & " not found")
        Return
    EndIf
    Local $sSource = FileRead($sPath)
    Local $aRegExp = StringRegExp($sSource, "(?is)Func\h+_GDIPlus_PathWarp(.*?)EndFunc", 3)
    If Not IsArray($aRegExp) Then
        MsgBox(0, "error", "Func _GDIPlus_PathWarp not found in" & @CRLF & $sPath)
        Return
    EndIf
    If StringRegExp($aRegExp[0], "(?i)\$iCount\h+<>\h+3\h+Or") Then
        $sSource = StringLeft($sSource, StringInStr($sSource, "Func _GDIPlus_PathWarp"))
        $aRegExp[0] = StringLeft($aRegExp[0], StringInStr($aRegExp[0], "If $iCount <> 3"))
        Local $iLine = 1
        StringRegExpReplace($sSource, "\r", "")
        $iLine += @extended
        StringRegExpReplace($aRegExp[0], "\r", "")
        $iLine += @extended
        MsgBox(0, "error found", "error in " & $sPath & @CRLF & "change line " & $iLine & @CRLF & "If $iCount <> 3 Or $iCount <> 4 Then" & @CRLF & "to:" & @CRLF & "If $iCount <> 3 And $iCount <> 4 Then")
    EndIf
EndFunc   ;==>_CheckGDIpWarpBug