• Welcome to PowerBasic Museum 2020-A.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

D2D demos for Windows7

Started by Patrice Terrier, December 05, 2009, 10:52:01 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

José, Petr,

When you will have moved to Seven, here are a few Direct2D demos that i have compiled with Visual Studio 2010 - ENU, in Win32 mode.

The GPU is being used instead of CPU, with latest graphic card generation when they are D2D compatible.

To better see the hardware antialias, play the demos full screen.

Note: The demos are part of the latest Windows Seven SDK.

...

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

Thanks Patrice,

I will try it in school, we have terrible intel cards there, so at least I will see if it runs on it.

I will upgrade to Windows 7, but with new PC ... which doesn't seem to happen very soon sadly.
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

#2
My first step with Direct2D and PB...

--José

Do you think that would be the correct way to create the initial D2D1CreateFactory with PB using the C Flat API syntax?

I am using $IID_ID2D1RenderTarget because what i want to create here is a render target that draws to a Windows Graphics Device Interface (GDI) device context.

I am using BYVAL %NULL, because i don't care of the "debug layer DLL".


    GLOBAL gpD2F AS IUnknown
    LOCAL hr AS LONG
'   // Create a Direct2D factory.
   hr = D2D1CreateFactory(%D2D1_FACTORY_TYPE_SINGLE_THREADED, $IID_ID2D1Factory, BYVAL %NULL,  gpD2F)
    gpD2F = NOTHING


Added:
There was a typo in $IID constant being used.
...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca

Quote
(the PB syntax to use is so different than C++ encapsulation)

Because, like they did with GDI+, they have written some wrapper classes and only have documented them. C++ uses 4 overloaded functions on top of the D2D1CreateFactory function, and documents them but not the API function, that is the one that really does the work.

They have also messed other things, like a couple of equates that have different values in different files, an interface with duplicated method names and some classes for DirectX 10 implemented as C++ classes instead of COM classes.

Patrice Terrier

#4
When i wrote my GDIPLUS helper, back in 2002, i had an MSDN CD-rom that gave me the right syntax to use with the Flat API, however since that time i never found it again on MSDN dvd, only wrapper classes.
I was also able to translate ALL the GDI+ examples to PB and the source code was provided with the old WinLIFT Pro version. This is how Rainer was able to write a nice charting tool DLL with PB  ;)

The demo was named "picture.exe" and must be still hanging somewhere around.
May be i shall post it back, after full completion of the new WSA.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca

#5
Quote
In d2d1Helper.inc, don't you think that dxgiFormat parameter of the PixelFormat method should be passed BYVAL instead of BYREF?

Yes, I have changed it.

Quote
Note: It is a real pain to translate the Direct2D VS C++ examples to PB, especially when they use default parameters like in the code below:

They have the advantage of default parameters and overloaded methods. I already had a hard time translating the GDI+ examples. Guess I will have to write a reference guide showing the PB syntax, because the MSDN documentation is for the C++ wrapper classes.

Using my upcoming updated headers, the translation of the CreateDeviceResources procedure will be:

I have translated GdiInteropSample.cpp to test if my translation of the Direct2D interfaces and the helper class works.

This is the original C++ code:


// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved

#include "GdiInteropSample.h"

/******************************************************************
*                                                                 *
*  WinMain                                                        *
*                                                                 *
*  Application entrypoint                                         *
*                                                                 *
******************************************************************/

int WINAPI WinMain(
    HINSTANCE /*hInstance*/,
    HINSTANCE /*hPrevInstance*/,
    LPSTR /*lpCmdLine*/,
    int /*nCmdShow*/
    )
{
    // Ignore the return value because we want to continue running even in the
    // unlikely event that HeapSetInformation fails.
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);

    if (SUCCEEDED(CoInitialize(NULL)))
    {
        {
            DemoApp app;

            if (SUCCEEDED(app.Initialize()))
            {
                app.RunMessageLoop();
            }
        }
        CoUninitialize();
    }

    return 0;
}

/******************************************************************
*                                                                 *
*  DemoApp::DemoApp constructor                                   *
*                                                                 *
*  Initialize member data                                         *
*                                                                 *
******************************************************************/

DemoApp::DemoApp() :
    m_hwnd(NULL),
    m_pD2DFactory(NULL),
    m_pDCRT(NULL),
    m_pBlackBrush(NULL)
{
}

/******************************************************************
*                                                                 *
*  DemoApp::~DemoApp destructor                                   *
*                                                                 *
*  Tear down resources                                            *
*                                                                 *
******************************************************************/

DemoApp::~DemoApp()
{
    SafeRelease(&m_pD2DFactory);
    SafeRelease(&m_pDCRT);
    SafeRelease(&m_pBlackBrush);
}

/******************************************************************
*                                                                 *
*  DemoApp::Initialize                                            *
*                                                                 *
*  Create the application window and device-independent resources *
*                                                                 *
******************************************************************/
HRESULT DemoApp::Initialize()
{
    HRESULT hr;

    hr = CreateDeviceIndependentResources();
    if (SUCCEEDED(hr))
    {
        // Register the window class.
        WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
        wcex.style         = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc   = DemoApp::WndProc;
        wcex.cbClsExtra    = 0;
        wcex.cbWndExtra    = sizeof(LONG_PTR);
        wcex.hInstance     = HINST_THISCOMPONENT;
        wcex.hbrBackground = NULL;
        wcex.lpszMenuName  = NULL;
        wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcex.lpszClassName = L"D2DDemoApp";

        RegisterClassEx(&wcex);

        // Create the application window.
        //
        // Because the CreateWindow function takes its size in pixels, we
        // obtain the system DPI and use it to scale the window size.
        FLOAT dpiX, dpiY;
        m_pD2DFactory->GetDesktopDpi(&dpiX, &dpiY);

        m_hwnd = CreateWindow(
            L"D2DDemoApp",
            L"Direct2D Demo App",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            static_cast<UINT>(ceil(640.f * dpiX / 96.f)),
            static_cast<UINT>(ceil(480.f * dpiY / 96.f)),
            NULL,
            NULL,
            HINST_THISCOMPONENT,
            this
            );

        hr = m_hwnd ? S_OK : E_FAIL;
        if (SUCCEEDED(hr))
        {
            ShowWindow(m_hwnd, SW_SHOWNORMAL);

            UpdateWindow(m_hwnd);
        }
    }

    return hr;
}

/******************************************************************
*                                                                 *
*  DemoApp::CreateDeviceIndependentResources                      *
*                                                                 *
*  This method is used to create resources which are not bound    *
*  to any device. Their lifetime effectively extends for the      *
*  duration of the app.                                           *
*                                                                 *
******************************************************************/

HRESULT DemoApp::CreateDeviceIndependentResources()
{
    // Create D2D factory
    return D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
}

/******************************************************************
*                                                                 *
*  DemoApp::CreateDeviceResources                                 *
*                                                                 *
*  This method creates resources which are bound to a particular  *
*  D3D device. It's all centralized here, in case the resources   *
*  need to be recreated in case of D3D device loss (eg. display   *
*  change, remoting, removal of video card, etc).                 *
*                                                                 *
******************************************************************/

HRESULT DemoApp::CreateDeviceResources()
{
    HRESULT hr = S_OK;

    if (!m_pDCRT)
    {
        // Create a DC render target.
        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
            D2D1_RENDER_TARGET_TYPE_DEFAULT,
            D2D1::PixelFormat(
                DXGI_FORMAT_B8G8R8A8_UNORM,
                D2D1_ALPHA_MODE_IGNORE),
            0,
            0,
            D2D1_RENDER_TARGET_USAGE_NONE,
            D2D1_FEATURE_LEVEL_DEFAULT
            );

        hr = m_pD2DFactory->CreateDCRenderTarget(&props, &m_pDCRT);
        if (SUCCEEDED(hr))
        {
            // Create a black brush.
            hr = m_pDCRT->CreateSolidColorBrush(
                D2D1::ColorF(D2D1::ColorF::Black),
                &m_pBlackBrush
                );
        }
    }

    return hr;
}

/******************************************************************
*                                                                 *
*  DemoApp::DiscardDeviceResources                                *
*                                                                 *
*  Discard device-specific resources which need to be recreated   *
*  when a D3D device is lost                                      *
*                                                                 *
******************************************************************/

void DemoApp::DiscardDeviceResources()
{
    SafeRelease(&m_pDCRT);
    SafeRelease(&m_pBlackBrush);
}

/******************************************************************
*                                                                 *
*  DemoApp::RunMessageLoop                                        *
*                                                                 *
*  Main window message loop                                       *
*                                                                 *
******************************************************************/

void DemoApp::RunMessageLoop()
{
    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}


/******************************************************************
*                                                                 *
*  DemoApp::OnRender                                              *
*                                                                 *
*  This method draws Direct2D content to a GDI HDC.               *
*                                                                 *
*  This method will automatically discard device-specific         *
*  resources if the D3D device disappears during function         *
*  invocation, and will recreate the resources the next time it's *
*  invoked.                                                       *
*                                                                 *
******************************************************************/
HRESULT DemoApp::OnRender(const PAINTSTRUCT &ps)
{

    HRESULT hr;
    RECT rc;

    // Get the dimensions of the client drawing area.
    GetClientRect(m_hwnd, &rc);

    //
    // Draw the pie chart with Direct2D.
    //

    // Create the DC render target.
    hr = CreateDeviceResources();

    if (SUCCEEDED(hr))
    {
        // Bind the DC to the DC render target.
        hr = m_pDCRT->BindDC(ps.hdc, &rc);

        m_pDCRT->BeginDraw();

        m_pDCRT->SetTransform(D2D1::Matrix3x2F::Identity());

        m_pDCRT->Clear(D2D1::ColorF(D2D1::ColorF::White));

        m_pDCRT->DrawEllipse(
            D2D1::Ellipse(
                D2D1::Point2F(150.0f, 150.0f),
                100.0f,
                100.0f),
            m_pBlackBrush,
            3.0
            );

        m_pDCRT->DrawLine(
            D2D1::Point2F(150.0f, 150.0f),
            D2D1::Point2F(
                (150.0f + 100.0f * 0.15425f),
                (150.0f - 100.0f * 0.988f)),
            m_pBlackBrush,
            3.0
            );

        m_pDCRT->DrawLine(
            D2D1::Point2F(150.0f, 150.0f),
            D2D1::Point2F(
                (150.0f + 100.0f * 0.525f),
                (150.0f + 100.0f * 0.8509f)),
            m_pBlackBrush,
            3.0
            );

        m_pDCRT->DrawLine(
            D2D1::Point2F(150.0f, 150.0f),
            D2D1::Point2F(
                (150.0f - 100.0f * 0.988f),
                (150.0f - 100.0f * 0.15425f)),
            m_pBlackBrush,
            3.0
            );

        hr = m_pDCRT->EndDraw();
        if (SUCCEEDED(hr))
        {
            //
            // Draw the pie chart with GDI.
            //

            // Save the original object.
            HGDIOBJ original = NULL;
            original = SelectObject(
                ps.hdc,
                GetStockObject(DC_PEN)
                );

            HPEN blackPen = CreatePen(PS_SOLID, 3, 0);
            SelectObject(ps.hdc, blackPen);

            Ellipse(ps.hdc, 300, 50, 500, 250);

            POINT pntArray1[2];
            pntArray1[0].x = 400;
            pntArray1[0].y = 150;
            pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);
            pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);

            POINT pntArray2[2];
            pntArray2[0].x = 400;
            pntArray2[0].y = 150;
            pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);
            pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);


            POINT pntArray3[2];
            pntArray3[0].x = 400;
            pntArray3[0].y = 150;
            pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);
            pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);

            Polyline(ps.hdc, pntArray1, 2);
            Polyline(ps.hdc, pntArray2, 2);
            Polyline(ps.hdc, pntArray3, 2);

            DeleteObject(blackPen);

            // Restore the original object.
            SelectObject(ps.hdc, original);
        }
    }

    if (hr == D2DERR_RECREATE_TARGET)
    {
        hr = S_OK;
        DiscardDeviceResources();
    }

    return hr;
}


/******************************************************************
*                                                                 *
*  DemoApp::WndProc                                               *
*                                                                 *
*  Window message handler                                         *
*                                                                 *
******************************************************************/

LRESULT CALLBACK DemoApp::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT result = 0;

    if (message == WM_CREATE)
    {
        LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
        DemoApp *pDemoApp = (DemoApp *)pcs->lpCreateParams;

        ::SetWindowLongPtrW(
            hwnd,
            GWLP_USERDATA,
            PtrToUlong(pDemoApp)
            );

        result = 1;
    }
    else
    {
        DemoApp *pDemoApp = reinterpret_cast<DemoApp *>(static_cast<LONG_PTR>(
            ::GetWindowLongPtrW(
                hwnd,
                GWLP_USERDATA
                )));

        bool wasHandled = false;

        if (pDemoApp)
        {
            switch (message)
            {
            case WM_PAINT:
            case WM_DISPLAYCHANGE:
                {
                    PAINTSTRUCT ps;
                    BeginPaint(hwnd, &ps);
                    pDemoApp->OnRender(ps);
                    EndPaint(hwnd, &ps);
                }
                result = 0;
                wasHandled = true;
                break;

            case WM_DESTROY:
                {
                    PostQuitMessage(0);
                }
                result = 1;
                wasHandled = true;
                break;
            }
        }

        if (!wasHandled)
        {
            result = DefWindowProc(hwnd, message, wParam, lParam);
        }
    }

    return result;
}


And this is my translation to PB:


#COMPILE EXE
#DIM ALL
#INCLUDE "d2d1.inc"
#INCLUDE "d2d1Helper.inc"

GLOBAL g_pD2DFactory AS ID2D1Factory
GLOBAL g_pDCRT AS ID2D1DCRenderTarget
GLOBAL g_pBlackBrush AS ID2D1SolidColorBrush
GLOBAL g_pID2D1Helper AS ID2D1Helper

' ========================================================================================
'*
'*  This function creates resources which are bound to a particular D3D device. It's all
'*  centralized here, in case the resources need to be recreated in case of D3D device
'*  loss (eg. display change, remoting, removal of video card, etc).
'*
' ========================================================================================
FUNCTION CreateDeviceResources () AS LONG

   LOCAL hr AS LONG

   IF ISNOTHING(g_pDCRT) THEN
      ' // Create a DC render target.
      LOCAL props AS D2D1_RENDER_TARGET_PROPERTIES
      props = g_pID2D1Helper.RenderTargetProperties(%D2D1_RENDER_TARGET_TYPE_DEFAULT, _
              g_pID2D1Helper.PixelFormat(%DXGI_FORMAT_B8G8R8A8_UNORM, %D2D1_ALPHA_MODE_IGNORE), _
              0, 0, %D2D1_RENDER_TARGET_USAGE_NONE, %D2D1_FEATURE_LEVEL_DEFAULT)

      hr = g_pD2DFactory.CreateDCRenderTarget(props, g_pDCRT)
      IF SUCCEEDED(hr) THEN
         ' // Create a black brush.
         hr = g_pDCRT.CreateSolidColorBrush( _
              g_pID2D1Helper.ColorF_3(%D2D1_Black, 1.0!), _
              BYVAL %NULL, _
              g_pBlackBrush)
      END IF
   END IF

   FUNCTION = hr

END FUNCTION
' ========================================================================================

' ========================================================================================
'*
'*  Discard device-specific resources which need to be recreated when a D3D device is lost
'*
' ========================================================================================
SUB DiscardDeviceResources
   g_pDCRT = NOTHING
   g_pBlackBrush = NOTHING
END SUB
' ========================================================================================

' ========================================================================================
'*  This function draws Direct2D content to a GDI HDC.
'*
'*  This function will automatically discard device-specific resources if the D3D device
'*  disappears during function invocation, and will recreate the resources the next time
'*  it's invoked.
'*
' ========================================================================================
FUNCTION OnRender (BYVAL hwnd AS DWORD, BYREF ps AS PAINTSTRUCT) AS LONG

   LOCAL hr AS LONG
   LOCAL rc AS RECT

   ' // Get the dimensions of the client drawing area.
   GetClientRect(hwnd, rc)

   ' // Draw the pie chart with Direct2D.

   ' // Create the DC render target.
   hr = CreateDeviceResources

   IF SUCCEEDED(hr) THEN
      ' // Bind the DC to the DC render target.
      hr = g_pDCRT.BindDC(ps.hdc, rc)
      g_pDCRT.BeginDraw
      g_pDCRT.SetTransform(g_pID2D1Helper.IdentityMatrix)
      g_pDCRT.Clear(g_pID2D1Helper.ColorF_3(%D2D1_White, 1.0!))

      g_pDCRT.DrawEllipse( _
         g_pID2D1Helper.Ellipse( _
            g_pID2D1Helper.Point2F(150.0!, 150.0!), _
            100.0!, _
            100.0!), _
         g_pBlackBrush, 3.0!)

      LOCAL point0, point1 AS D2D1_POINT_2F
      point0 = g_pID2D1Helper.Point2F(150.0!, 150.0!)
      point1 = g_pID2D1Helper.Point2F( _
                  150.0! + 100.0! * 0.15425!, _
                  150.0! - 100.0! * 0.988!)
      g_pDCRT.DrawLine( _
         point0, _
         point1, _
         g_pBlackBrush, 3.0!)

      point0 = g_pID2D1Helper.Point2F(150.0!, 150.0!)
      point1 = g_pID2D1Helper.Point2F( _
                  150.0! + 100.0! * 0.525!, _
                  150.0! + 100.0! * 0.8509!)
      g_pDCRT.DrawLine( _
         point0, _
         point1, _
         g_pBlackBrush, 3.0!)

      point0 = g_pID2D1Helper.Point2F(150.0!, 150.0!)
      point1 = g_pID2D1Helper.Point2F( _
                  150.0! - 100.0! * 0.988!, _
                  150.0! - 100.0! * 0.15425!)
      g_pDCRT.DrawLine( _
         point0, _
         point1, _
         g_pBlackBrush, 3.0!)

      hr = g_pDCRT.EndDraw
      IF SUCCEEDED(hr) THEN
         ' //
         ' // Draw the pie chart with GDI.
         ' //

         ' // Save the original object.
         LOCAL original AS DWORD
         original = SelectObject(ps.hdc, GetStockObject(%DC_PEN))

         LOCAL blackPen AS WORD
         blackPen = CreatePen(%PS_SOLID, 3, 0)
         SelectObject(ps.hdc, blackPen)

         Ellipse(ps.hdc, 300, 50, 500, 250)

         DIM pntArray1(1) AS POINT
         pntArray1(0).x = 400
         pntArray1(0).y = 150
         pntArray1(1).x = 400 + 100 * 0.15425
         pntArray1(1).y = 150 - 100 * 0.9885

         DIM pntArray2(2) AS POINT
         pntArray2(0).x = 400
         pntArray2(0).y = 150
         pntArray2(1).x = 400 + 100 * 0.525
         pntArray2(1).y = 150 + 100 * 0.8509

         DIM pntArray3(2) AS POINT
         pntArray3(0).x = 400
         pntArray3(0).y = 150
         pntArray3(1).x = 400 - 100 * 0.988
         pntArray3(1).y = 150 - 100 * 0.15425

         Polyline(ps.hdc, pntArray1(0), 2)
         Polyline(ps.hdc, pntArray2(0), 2)
         Polyline(ps.hdc, pntArray3(0), 2)

         DeleteObject(blackPen)

         ' // Restore the original object.
         SelectObject(ps.hdc, original)
      END IF
   END IF

   IF hr = %D2DERR_RECREATE_TARGET THEN
      hr = %S_OK
      DiscardDeviceResources
   END IF

   FUNCTION = hr

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   LOCAL hr          AS LONG
   LOCAL hWndMain    AS DWORD
   LOCAL wcex        AS WNDCLASSEX
   LOCAL szClassName AS ASCIIZ * 80
   LOCAL rc          AS RECT
   LOCAL szCaption   AS ASCIIZ * 255

   ' // Create D2D factory
'   hr = D2D1CreateFactory(%D2D1_FACTORY_TYPE_SINGLE_THREADED, $IID_ID2D1Factory, BYVAL %NULL, g_pD2DFactory)
   hr = D2D1CreateFactory2(%D2D1_FACTORY_TYPE_SINGLE_THREADED, g_pD2DFactory)
   IF ISNOTHING(g_pD2DFactory) THEN EXIT FUNCTION

   ' // Create an instance of the CD2D1Helper class
   g_pID2D1Helper = CLASS "CD2D1Helper"
   IF ISNOTHING(g_pID2D1Helper) THEN EXIT FUNCTION

   ' Register the window class
   szClassName        = "D2DDemoApp"
   wcex.cbSize        = SIZEOF(wcex)
   wcex.style         = %CS_HREDRAW OR %CS_VREDRAW
   wcex.lpfnWndProc   = CODEPTR(WndProc)
   wcex.cbClsExtra    = 0
   wcex.cbWndExtra    = 0
   wcex.hInstance     = hInstance
   wcex.hCursor       = LoadCursor (%NULL, BYVAL %IDC_ARROW)
   wcex.hbrBackground = %COLOR_3DFACE + 1
   wcex.lpszMenuName  = %NULL
   wcex.lpszClassName = VARPTR(szClassName)
   wcex.hIcon         = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Sample, if resource icon: LoadIcon(hInst, "APPICON")
   wcex.hIconSm       = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Remember to set small icon too..
   RegisterClassEx wcex

   ' // Create the application window.
   ' //
   ' // Because the CreateWindow function takes its size in pixels, we
   ' // obtain the system DPI and use it to scale the window size.
   LOCAL dpiX, dpiY AS SINGLE
   g_pD2DFactory.GetDesktopDpi(dpiX, dpiY)

   ' Window caption
   szCaption = "Direct2D Demo App"

   ' Create a window using the registered class
   hWndMain = CreateWindowEx(%WS_EX_CONTROLPARENT, _           ' extended style
                             szClassName, _                    ' window class name
                             szCaption, _                      ' window caption
                             %WS_OVERLAPPEDWINDOW, _           ' window styles
                             %CW_USEDEFAULT, _                 ' initial x position
                             %CW_USEDEFAULT, _                 ' initial y position
                             CEIL(600 * dpiX / 96), _          ' initial x size
                             CEIL(400 * dpiY / 96), _          ' initial y size
                             %NULL, _                          ' parent window handle
                             0, _                              ' window menu handle
                             hInstance, _                      ' program instance handle
                             BYVAL %NULL)                      ' creation parameters

   ' Show the window
   ShowWindow hWndMain, nCmdShow
   UpdateWindow hWndMain

   ' Message handler loop
   LOCAL uMsg AS tagMsg
   WHILE GetMessage(uMsg, %NULL, 0, 0)
      IF ISFALSE IsDialogMessage(hWndMain, uMsg) THEN
         TranslateMessage uMsg
         DispatchMessage uMsg
      END IF
   WEND

   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   LOCAL rc AS RECT

   SELECT CASE wMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  SendMessage hWnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF

         END SELECT

      CASE %WM_SYSCOMMAND
         ' Capture this message and send a WM_CLOSE message
         IF (wParam AND &HFFF0) = %SC_CLOSE THEN
            SendMessage hWnd, %WM_CLOSE, 0, 0
            EXIT FUNCTION
         END IF

      CASE %WM_PAINT, %WM_DISPLAYCHANGE
         LOCAL ps AS PAINTSTRUCT
         BeginPaint(hwnd, ps)
         OnRender(hwnd, ps)
         EndPaint(hwnd, ps)
         EXIT FUNCTION

      CASE %WM_DESTROY
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


Patrice Terrier

#6
Here is my PB's translation of the SimplePathAnimationSample.cpp
(It is based on Windows SDK v7.0)

I had a hard time to do it, because MFC is realy not my cup of tea.

There is a small difference with the original, for the computation of the animation speed at the start/end of the geometry path.

Perhaps a C++ expert could tell me what the difference is :)



'+--------------------------------------------------------------------------+
'|                                                                          |
'|                               PathAnim                                   |
'|                                                                          |
'|           SDK example showing how to use the Direct2D API.               |
'|                                                                          |
'+--------------------------------------------------------------------------+
'|                                                                          |
'|                         Author Patrice TERRIER                           |
'|                            copyright(c) 2010                             |
'|                           www.zapsolution.com                            |
'|                        pterrier@zapsolution.com                          |
'|                                                                          |
'+--------------------------------------------------------------------------+
'|                  Project started on : 06-17-2009 (MM-DD-YYYY)            |
'|                        Last revised : 06-19-2010 (MM-DD-YYYY)            |
'+--------------------------------------------------------------------------+

#COMPILE EXE "PathAnim.exe"

#INCLUDE "D2D1.inc"
#INCLUDE "DWMAPI.inc"
#INCLUDE "D2D1Helper.inc"

TYPE Animation
    rStart    AS SINGLE
    rEnd      AS SINGLE
    rDuration AS SINGLE
END TYPE

GLOBAL g_pD2DFactory AS ID2D1Factory
GLOBAL g_pPathGeometry AS ID2D1PathGeometry
GLOBAL g_pObjectGeometry AS ID2D1PathGeometry
GLOBAL g_pID2D1Helper AS ID2D1Helper
GLOBAL g_pRT AS ID2D1HwndRenderTarget
GLOBAL g_pRedBrush, g_pYellowBrush AS ID2D1SolidColorBrush

'GLOBAL g_pDCRT AS ID2D1DCRenderTarget

GLOBAL gAni AS Animation
GLOBAL gDwmTimingInfo AS DWM_TIMING_INFO

DECLARE FUNCTION zTrace LIB "zTrace.DLL" ALIAS "zTrace" (zMessage AS ASCIIZ) AS LONG

FUNCTION WinMain (BYVAL hInstance     AS LONG, _
                  BYVAL hPrevInstance AS LONG, _
                  BYVAL lpCmdLine     AS ASCIIZ PTR, _
                  BYVAL iCmdShow      AS LONG) AS LONG

    LOCAL rc          AS RECT
    LOCAL Msg         AS tagMsg
    LOCAL wc          AS WndClassEx
    LOCAL zClass      AS ASCIIZ * 80
    LOCAL hr, IsInitialized, x, y AS LONG, dwExStyle, dwStyle, hMain, hDC  AS DWORD
    LOCAL rLength AS SINGLE
'
    g_pID2D1Helper = CLASS "CD2D1Helper"
    IF ISNOTHING(g_pID2D1Helper) THEN
       MsgBox "Unable to create the D2D1Helper class"
       EXIT FUNCTION
    END IF

    hr = CreateDeviceIndependentResources()
    IF hr = 0 THEN

       zClass = "ZD2D1"
'     
       IsInitialized = GetClassInfoEx(hInstance, zClass, wc)
       IF IsInitialized&   = 0 THEN
          wc.cbSize        = SIZEOF(wc)
          wc.style         = %CS_HREDRAW OR %CS_VREDRAW
          wc.lpfnWndProc   = CODEPTR(WndProc)
          wc.cbClsExtra    = 0
          wc.cbWndExtra    = 0
          wc.hInstance     = hInstance
          wc.hIcon         = LoadIcon(wc.hInstance, "PROGRAM")
          wc.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
          wc.hbrBackground = %NULL ' GetStockObject(%BLACK_BRUSH)
          wc.lpszMenuName  = %NULL
          wc.lpszClassName = VARPTR(zClass)
          wc.hIconSm       = wc.hIcon
          IF RegisterClassEx(wc) THEN IsInitialized = %TRUE
       END IF
'     
       IF IsInitialized THEN
'     
        ' Window Extended Style
          dwExStyle = 0'%WS_EX_APPWINDOW OR %WS_EX_WINDOWEDGE
        ' Windows Style
          dwStyle = %WS_OVERLAPPEDWINDOW
'     
          CALL SetRect(rc, 0, 0, 512, 512)
          CALL AdjustWindowRectEx(rc, dwStyle, %FALSE, dwExStyle)  ' Adjust Window To True Requested Size
'     
          x = MAX&((GetSystemMetrics(%SM_CXSCREEN) - rc.nRight - rc.nLeft) \ 2, 0)
          y = MAX&((GetSystemMetrics(%SM_CYSCREEN) - rc.nBottom - rc.nTop) \ 2, 0)
'     
        ' Create The Window
          MyTitle$ = "PathAnimation"
          hMain = CreateWindowEx(dwExStyle, _            ' Extended Style For The Window
                                zClass, _                ' Class Name
                                (MyTitle$), _            ' Window Title
                                dwStyle OR _             ' Defined Window Style
                                %WS_CLIPSIBLINGS OR _    ' Required Window Style
                                %WS_CLIPCHILDREN, _      ' Required Window Style
                                x, y, _                  ' Window Position
                                rc.nRight - rc.nLeft, _  ' Calculate Window Width
                                rc.nBottom - rc.nTop, _  ' Calculate Window Height
                                %NULL, _                 ' No Parent Window
                                %NULL, _                 ' No Menu
                                wc.hInstance, _          ' Instance
                                BYVAL %NULL)             ' Dont Pass Anything To WM_CREATE
'     
          IF hMain THEN

             hr = g_pPathGeometry.ComputeLength(BYVAL %NULL, D2D1_DEFAULT_FLATTENING_TOLERANCE, rLength)

             IF hr = 0 THEN
                gAni.rStart = 0      '//start at begining of path
                gAni.rEnd = rLength  '//length at end of path
                gAni.rDuration = 5.0 '//seconds

                gDwmTimingInfo.cbSize = SIZEOF(DWM_TIMING_INFO)

                '// Get the composition refresh rate. If the DWM isn't running,
                '// get the refresh rate from GDI -- probably going to be 60Hz
                IF DwmGetCompositionTimingInfo(%NULL, gDwmTimingInfo) THEN
                    hDC = GetDC(hMain)
                    gDwmTimingInfo.rateCompose.uiDenominator = 1
                    gDwmTimingInfo.rateCompose.uiNumerator = GetDeviceCaps(hDC, %VREFRESH)
                    CALL ReleaseDC(hMain, hDC)
                END IF
             END IF

           ' Show the main window
             CALL ShowWindow(hMain, iCmdShow)
             CALL SetForegroundWindow(hMain)                  ' Slightly Higher Priority
   
             WHILE GetMessage(Msg, %NULL, 0, 0)
                 IF IsDialogMessage(hMain, Msg) = %FALSE THEN
                    CALL TranslateMessage(msg)                ' Translate The Message
                    CALL DispatchMessage(msg)                 ' Dispatch The Message
                 END IF
             WEND
     
             FUNCTION = msg.wParam

'            // Cleanup
             g_pD2DFactory     = NOTHING
             g_pPathGeometry   = NOTHING
             g_pObjectGeometry = NOTHING
             g_pID2D1Helper    = NOTHING
             g_pRT             = NOTHING
             g_pRedBrush       = NOTHING
             g_pYellowBrush    = NOTHING

          END IF
       END IF

    END IF
   
END FUNCTION


FUNCTION WndProc(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
    LOCAL ps AS PAINTSTRUCT

    SELECT CASE LONG Msg

    CASE %WM_SIZE
         OnResize(LO(INTEGER, lParam), HI(INTEGER, lParam))

    CASE %WM_COMMAND
         SELECT CASE LONG LOWRD(wParam)

         END SELECT

    CASE %WM_PAINT, %WM_DISPLAYCHANGE
         CALL BeginPaint(hWnd, ps)
         CALL OnRender(hWnd)
         CALL EndPaint(hWnd, ps)
         FUNCTION = 0: EXIT FUNCTION
    CASE %WM_CLOSE

    CASE %WM_DESTROY
         CALL PostQuitMessage(0)
         FUNCTION = 0: EXIT FUNCTION
    END SELECT

    FUNCTION = DefWindowProc(hWnd, Msg, wParam, lParam)

END FUNCTION

FUNCTION CreateDeviceIndependentResources() AS LONG

    LOCAL pSink AS ID2D1GeometrySink
    LOCAL hr AS LONG

'   // Create Direct2D factory.
    hr = D2D1CreateFactory(%D2D1_FACTORY_TYPE_SINGLE_THREADED, $IID_ID2D1Factory, BYVAL %NULL, g_pD2DFactory)

    IF hr = 0 THEN
'       // Create path geometry.
        hr = g_pD2DFactory.CreatePathGeometry(g_pPathGeometry)

    END IF
    IF hr = 0 THEN
'      // Write to the path geometry using the geometry sink. We are going to create a
'      // spiral
       hr = g_pPathGeometry.Open(pSink)

    END IF
    IF hr = 0 THEN
       LOCAL currentLocation, locSwap, locDelta AS D2D1_POINT_2F
       LOCAL radius AS SINGLE, i AS LONG
       LOCAL ArcSegment AS D2D1_ARC_SEGMENT

       currentLocation.x = 0
       currentLocation.y = 0   

       pSink.BeginFigure(currentLocation, %D2D1_FIGURE_BEGIN_FILLED)

       locDelta.x = 2
       locDelta.y = 2   

       radius = 3

       FOR i = 0 TO 29
     
           currentLocation.x += radius * locDelta.x
           currentLocation.y += radius * locDelta.y

           ArcSegment.point          = currentLocation
           ArcSegment.size.width     = 2 * radius
           ArcSegment.size.height    = 2 * radius
           ArcSegment.rotationAngle  = 0.0
           ArcSegment.sweepDirection = %D2D1_SWEEP_DIRECTION_CLOCKWISE
           ArcSegment.arcSize        = %D2D1_ARC_SIZE_SMALL
           pSink.AddArc(ArcSegment)
'// You can either use the José's helper method below.
'          pSink.AddArc(g_pID2D1Helper.ArcSegment(currentLocation, g_pID2D1Helper.SizeF(2 * radius, 2 * radius), 0.0, %D2D1_SWEEP_DIRECTION_CLOCKWISE, %D2D1_ARC_SIZE_SMALL))


           locSwap.x = -locDelta.y
           locSwap.y = locDelta.x
           locDelta.x = locSwap.x
           locDelta.y = locSwap.y
'// You can either use the José's helper method below.
'          locDelta = g_pID2D1Helper.Point2F(-locDelta.y, locDelta.x)

           radius += 3
       NEXT

       pSink.EndFigure(%D2D1_FIGURE_END_OPEN)

       hr = pSink.Close()

    END IF
    IF hr = 0 THEN
'      // Create the path geometry.
       hr = g_pD2DFactory.CreatePathGeometry(g_pObjectGeometry)

    END IF
    IF hr = 0 THEN
'      // Write to the object geometry using the geometry sink.
'      // We are going to create a simple triangle
       hr = g_pObjectGeometry.Open(pSink)

    END IF
    IF hr = 0 THEN
       currentLocation.x = 0
       currentLocation.y = 0   
       pSink.BeginFigure(currentLocation, %D2D1_FIGURE_BEGIN_FILLED)

       DIM ptTriangle(0 TO 2) AS D2D1_POINT_2F
       ptTriangle(0).x = -10.0: ptTriangle(0).y = -10.0
       ptTriangle(1).x = -10.0: ptTriangle(1).y = 10.0
       ptTriangle(2).x = 0.0:   ptTriangle(2).y = 0.0
       pSink.AddLines(ptTriangle(0), 3)

       pSink.EndFigure(%D2D1_FIGURE_END_OPEN)

       hr = pSink.Close()

    END IF

    pSink = NOTHING

    FUNCTION = hr

END FUNCTION

'/******************************************************************
'*                                                                 *
'*  DemoApp::CreateDeviceResources                                 *
'*                                                                 *
'*  This method creates resources which are bound to a particular  *
'*  D3D device. It's all centralized here, in case the resources   *
'*  need to be recreated in case of D3D device loss (eg. display   *
'*  change, remoting, removal of video card, etc).                 *
'*                                                                 *
'******************************************************************/
FUNCTION CreateDeviceResources(BYVAL hWnd AS LONG) AS LONG
    LOCAL hr AS LONG, uSize AS D2D1_SIZE_U
    LOCAL nType AS DWORD, pixelFormat AS D2D1_PIXEL_FORMAT, dpiX, dpiY AS SINGLE, usage, minlevel AS DWORD
    LOCAL dxgiFormat, alphaMode AS DWORD
    LOCAL brushProperties AS D2D1_BRUSH_PROPERTIES

    IF ISNOTHING(g_pRT) THEN

        LOCAL rc AS RECT
        CALL GetClientRect(hWnd, rc)

        uSize = g_pID2D1Helper.SizeU(rc.nRight - rc.nLeft, rc.nBottom - rc.nTop)

        '// Create a Direct2D render target
        nType = %D2D1_RENDER_TARGET_TYPE_DEFAULT
        dxgiFormat = %DXGI_FORMAT_UNKNOWN
        alphaMode = %D2D1_ALPHA_MODE_UNKNOWN
        pixelFormat = g_pID2D1Helper.PixelFormat(dxgiFormat, alphaMode)
        dpiX = 0.0
        dpiY = 0.0
        usage = %D2D1_RENDER_TARGET_USAGE_NONE
        minLevel = %D2D1_FEATURE_LEVEL_DEFAULT

        hr = g_pD2DFactory.CreateHwndRenderTarget( _
             g_pID2D1Helper.RenderTargetProperties(nType, pixelFormat, dpiX, dpiY, usage, minLevel), _
             g_pID2D1Helper.HwndRenderTargetProperties(hWnd, uSize, %D2D1_PRESENT_OPTIONS_NONE), _
             g_pRT)

        IF hr = 0 THEN
           '// Create a red brush.
           brushProperties.opacity = 1.0
           brushProperties.transform =  g_pID2D1Helper.IdentityMatrix()
           hr = g_pRT.CreateSolidColorBrush( _
                g_pID2D1Helper.ColorF_2(%D2D1_Red, 1.0), _
                brushProperties, _
                g_pRedBrush)
        END IF
        IF hr = 0 THEN
           '// Create a yellow brush.
           hr = g_pRT.CreateSolidColorBrush( _
                g_pID2D1Helper.ColorF_2(%D2D1_Yellow, 1.0), _
                brushProperties, _
                g_pYellowBrush)
        END IF

    END IF
    FUNCTION = hr
END FUNCTION

'/******************************************************************
'*                                                                 *
'*  DemoApp::DiscardDeviceResources                                *
'*                                                                 *
'*  Discard device-specific resources which need to be recreated   *
'*  when a D3D device is lost                                      *
'*                                                                 *
'******************************************************************/
SUB DiscardDeviceResources()
    g_pRT             = NOTHING
    g_pRedBrush       = NOTHING
    g_pYellowBrush    = NOTHING
END SUB

'/******************************************************************
'*                                                                 *
'*  DemoApp::OnRender                                              *
'*                                                                 *
'*  Called whenever the application needs to display the client    *
'*  window. This method draws a single frame of animated content   *
'*                                                                 *
'*  Note that this function will not render anything if the window *
'*  is occluded (e.g. when the screen is locked).                  *
'*  Also, this function will automatically discard device-specific *
'*  resources if the D3D device disappears during function         *
'*  invocation, and will recreate the resources the next time it's *
'*  invoked.                                                       *
'*                                                                 *
'******************************************************************/
FUNCTION OnRender(BYVAL hWnd AS LONG) AS LONG
    LOCAL hr AS LONG

    hr = CreateDeviceResources(hWnd)
    IF hr = 0 THEN
       IF (g_pRT.CheckWindowState() AND %D2D1_WINDOW_STATE_OCCLUDED) = 0 THEN
   
           LOCAL dPoint, tangent, center AS D2D1_POINT_2F

           LOCAL triangleMatrix AS D2D1_MATRIX_3X2_F
           LOCAL rtSize AS D2D1_SIZE_F
           LOCAL minWidthHeightScale, rlength AS SINGLE

           STATIC float_time AS SINGLE

           rtSize = g_pRT.GetSize()
           minWidthHeightScale = MIN(rtSize.width, rtSize.height) / 512
       
           LOCAL mScale AS D2D1_MATRIX_3X2_F
           mScale = g_pID2D1Helper.MatrixScale( _
                    minWidthHeightScale, _
                    minWidthHeightScale, _
                    center)

           LOCAL translation AS D2D1_MATRIX_3X2_F
           translation = g_pID2D1Helper.MatrixTranslation( _
                         rtSize.width / 2, _
                         rtSize.height / 2)
       
           '// Prepare to draw.
           g_pRT.BeginDraw()
       
           '// Reset to identity transform
           g_pRT.SetTransform(g_pID2D1Helper.IdentityMatrix())
       
           '//clear the render target contents
           g_pRT.Clear(g_pID2D1Helper.ColorF_2(%D2D1_Black, 1.0))
       
           '//center the path
           LOCAL centerpath AS D2D1_MATRIX_3X2_F
           centerpath = g_pID2D1Helper.MultiplyMatrices(mScale, translation)
           g_pRT.SetTransform(centerpath)
       
           '//draw the path in red
           g_pRT.DrawGeometry(g_pPathGeometry, g_pRedBrush, 1.0)
             
           '//rlength = m_Animation.GetValue(float_time)
           rlength = MIN(MAX(float_time, 0), gAni.rDuration)
           rlength = gAni.rStart + ((gAni.rEnd - gAni.rStart) * (rlength / gAni.rDuration))
           '// Ask the geometry to give us the point that corresponds with the
           '// length at the current time.
           hr = g_pPathGeometry.ComputePointAtLength(rlength, BYVAL %NULL, 0.0, dPoint, tangent)

           '//Assert(SUCCEEDED(hr))
           IF hr THEN MsgBox "Assert failed"
       
           '// Reorient the triangle so that it follows the
           '// direction of the path.
           triangleMatrix = g_pID2D1Helper.Matrix3x2F( _
                            tangent.x, tangent.y, _
                           -tangent.y, tangent.x, _
                            dPoint.x, dPoint.y)
       
           LOCAL m AS D2D1_MATRIX_3X2_F
           m = g_pID2D1Helper.MultiplyMatrices(triangleMatrix, centerpath)
           g_pRT.SetTransform(m) '// triangleMatrix * mScale * translation)
       
           '// Draw the yellow triangle.
           g_pRT.FillGeometry(g_pObjectGeometry, g_pYellowBrush)
       
           '// Commit the drawing operations.
           hr = g_pRT.EndDraw()
       
           IF hr = %D2DERR_RECREATE_TARGET THEN
              hr = 0
              DiscardDeviceResources()
           END IF
       
           '// When we reach the end of the animation, loop back to the beginning.
           IF float_time >= gAni.rDuration THEN
               float_time = 0.0
           ELSE
               float_time += gDwmTimingInfo.rateCompose.uiDenominator / gDwmTimingInfo.rateCompose.uiNumerator
           END IF
       END IF
    END IF

    CALL InvalidateRect(hWnd, BYVAL %NULL, %FALSE)

    FUNCTION = hr
END FUNCTION

'/******************************************************************
'*                                                                 *
'*  DemoApp::OnResize                                              *
'*                                                                 *
'*  If the application receives a WM_SIZE message, this method     *
'*  resize the render target appropriately.                        *
'*                                                                 *
'******************************************************************/
SUB OnResize(BYVAL nWidth AS LONG, BYVAL nHeight AS LONG)
    IF NOT ISNOTHING(g_pRT) THEN
       LOCAL su AS D2D1_SIZE_U

       su.width = nWidth
       su.height = nHeight
       '// Note: This method can fail, but it's okay to ignore the
       '// error here -- it will be repeated on the next call to
       '// EndDraw.
       g_pRT.Resize(su)
    END IF
END SUB


Note that the animation is not based on a timer, but on the DWM refresh rate (60 Hz)
Thus in this case 60 Hz = 60 FPS, because it is the maximum you can have in composited mode  ;D


...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#7
When translating D2D C++ examples to PB, be careful to the translation of matrix manipulation.

Here is an example

This easy to understand C++ syntax:
Quotem_pRT->SetTransform(triangleMatrix * scale * translation);

Must be translated to something like this in PB (using José's helper function):
QuoteLOCAL centerpath AS D2D1_MATRIX_3X2_F
centerpath = g_pID2D1Helper.MultiplyMatrices(mScale, translation)
g_pRT.SetTransform(centerpath)
LOCAL m AS D2D1_MATRIX_3X2_F
m = g_pID2D1Helper.MultiplyMatrices(triangleMatrix, centerpath)
g_pRT.SetTransform(m) '// triangleMatrix * mScale * translation)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

While we can emulate many of the D2D features with OpenGL, there is no comparison as soon as we want to use or manipulate text font.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#9
Attached to this post you will find the PB's translation of the SimpleDirect2DApplication.cpp

Note: Until José post a new D2D1Helper.inc, you must edit the "BezierSegment" method like this:
   ' =====================================================================================
   ' Creates a D2D1_BEZIER_SEGMENT structure.
   ' =====================================================================================
   METHOD BezierSegment ( _
      BYREF point1 AS D2D1_POINT_2F, _
      BYREF point2 AS D2D1_POINT_2F, _
      BYREF point3 AS D2D1_POINT_2F _
      ) AS D2D1_ARC_SEGMENT

      LOCAL bzseg AS D2D1_BEZIER_SEGMENT
      bzseg.point1 = point1
      bzseg.point2 = point2
      bzseg.point3 = point3
      METHOD = bzseg

   END METHOD


This demo shows you:

  • How to render WICbitmap from resource and/or from file.
  • How to render a text font at any handle.
  • How to render a path geometry.
  • How to fill a custom shape with gradient brush.
  • How to fill the background with a custom bitmap brush.


As a matter of comparison, here is the size of resulting EXE.

  • VS2010 C++ = 768 Kb
  • PB9 = 807 Kb
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

Thanks for the examples,

the antialiased look of primitives is nice, is there any way to determine the algorithm used for antialiasing?


Petr
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

#11
Quotethe antialiased look of primitives is nice, is there any way to determine the algorithm used for antialiasing?

' enum D2D1_ANTIALIAS_MODE
%D2D1_ANTIALIAS_MODE_PER_PRIMITIVE = 0???
%D2D1_ANTIALIAS_MODE_ALIASED = 1???

' enum D2D1_TEXT_ANTIALIAS_MODE
%D2D1_TEXT_ANTIALIAS_MODE_DEFAULT = 0???
%D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE = 1???
%D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE = 2???
%D2D1_TEXT_ANTIALIAS_MODE_ALIASED = 3???

' enum D2D1_BITMAP_INTERPOLATION_MODE
%D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR = 0???
%D2D1_BITMAP_INTERPOLATION_MODE_LINEAR = 1???


The resulting quality is the same than using GDI+ bicubic, but thanks to the GPU it is done almost instantaneously!

Applications that use Direct2D for graphics can deliver higher visual quality than what can be achieved using GDI. Direct2D uses per-primitive antialiasing to deliver smoother looking curves and lines in rendered content. There is also full support for transparency and alpha blending when rendering 2-D primitives.

Direct2D also makes it easy to use DirectWrite, the new text API, and the advanced imaging features of the Microsoft Windows Imaging Component (WIC).

Learn more about Direct2D here

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca

#12
 
I have modified d2d1Helper.inc to change many parameters as optional to take advantage of default values.

For example, this C++ code:


// Create a Direct2D render target.
hr = m_pD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(),
    D2D1::HwndRenderTargetProperties(m_hwnd, size),
    &m_pRenderTarget
    );


That previously needed to be translated as:


LOCAL nType AS DWORD, pixelFormat AS D2D1_PIXEL_FORMAT, dpiX, dpiY AS SINGLE, usage, minlevel AS DWORD
nType = %D2D1_RENDER_TARGET_TYPE_DEFAULT
dxgiFormat = %DXGI_FORMAT_UNKNOWN
alphaMode = %D2D1_ALPHA_MODE_UNKNOWN
pixelFormat = g_pID2D1Helper.PixelFormat(dxgiFormat, alphaMode)
dpiX = 0.0
dpiY = 0.0
usage = %D2D1_RENDER_TARGET_USAGE_NONE
minLevel = %D2D1_FEATURE_LEVEL_DEFAULT
hr = g_pD2DFactory.CreateHwndRenderTarget( _
    g_pID2D1Helper.RenderTargetProperties(nType, pixelFormat, dpiX, dpiY, usage, minLevel), _
    g_pID2D1Helper.HwndRenderTargetProperties(hWnd, uSize, %D2D1_PRESENT_OPTIONS_NONE), _
    g_pRenderTarget)


Now becomes:


hr = g_pD2DFactory.CreateHwndRenderTarget( _
     g_pID2D1Helper.RenderTargetProperties(), _
     g_pID2D1Helper.HwndRenderTargetProperties(hWnd, uSize), _
     g_pRenderTarget)


I also have added a new file, called d2dUtils.inc, that incorporates the functions D2D_LoadBitmapFromFile and D2D_LoadBitmapFromResource.

Patrice Terrier

#13
Attached to this post you will find the PB's translation of the TextAnimationSample.cpp

You can change the animations using these keys:

  • "R" to perform rotation.
  • "S" to perform scaling.
  • "T" to perform translation.

Added:
FPS counter to see the impact of changing the rendering method.

You can change the rendering method using these keys:

  • "1" use the Default method.
  • "2" use the Outline method.
  • "3" use the UseA8Target method.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#14
The examples have been edited, to let them work only with PB10+ and the latest José Roca's include files.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com