Friday, 30 December 2011

Finite automata to Regular Grammar with Thundax P-Zaggy

Moving ahead with FA, now we can generate the right-linear grammar that corresponds to the finite automata generated. The system is pretty simple and basically what the algorithm does is to go recursively through every state and to store the production (A → bC) using the info from the transition and both states.

P-Zaggy will use description text to assign unique variable names to each state. Each transition in the graph matches a production in the right-linear grammar. For example (right side image), the transition from “A” to “B” along the transition “a” matches the production “A → aB”. This production will be automatically added into the production list in the "Finite Automaton (simulation)" tab. To generate the full grammar, just open your finite automata and press "Get grammar" button to get the linear grammar. Now as any final state carries the production to λ, λ symbol has been added to the system as empty string.

In the following image you will see a general example with the automatically generated grammar:


Example with λ string:


Demo video:

Get the latest version from here:

Looking back/ahead:
This would be the last post of the year 2011 and I'm taking this moment to review all the good stuff I have been publishing in my blog, from the physics engine to different code snippets and all of them with the help of a big an bright Delphi community. I always find difficult to get round to writing more often but I always have my notebook with me and every time and idea pops out I am there to catch it. I have an endless list of really interesting stuff I would like to tackle and I hope next year would be more fruitful as there are less than 50 articles for this year (even though the visits have been increased to almost 6K per month wow!, I am grateful for that!). I am also blissfully happy for putting grain of salt in the community as I have widely used the knowledge of others and it is great to pay back.
Next year I will be implementing different algorithms and I will be focusing on grammars, compilers and AI as I am very keen on those subjects and as you already know I like a lot visual stuff (And everything or almost everything with my loved Delphi). I'm preparing a roadmap about different utilities I have in mind and stay tuned for new and very interesting stuff!.
Happy new year 2012!.
Jordi Corbilla

Related links:

Thursday, 29 December 2011

Finite Automata with Thundax P-Zaggy part II

Going on with the further enhancement of P-Zaggy (part I) to use its graph creation capability to run and simulate DFA, I have released a new version (v1.2.0 build 180) which allows you to check a bunch of strings in batch. One the DFA is defined, we can easily test our input strings by adding them into the list and the application will check every item and it will populate the status with "accepted/rejected" message. This version still only works with one char regular expressions (^[A-Z]$) so more complex expressions (^[A-Z]+$) will be used but not correctly adapted.

Examples:


Related links:

Finite Automata with Thundax P-Zaggy part I

I have moved forward the development of Thundax P-Zaggy with the addition of a Finite Automata builder and simulator. "A deterministic finite automaton (DFA) also known as deterministic finite state machine is a finite state machine that accepts/rejects finite strings of symbols and only produces a unique computation (or run) of the automaton for each input string. (wikipedia)". Building the automata with P-Zaggy is quite simple, so let's start by building a DFA for the following language: 
L = {ba | abna, n > 0}.
As it is shown in the previous image, the DFA would be as follows:


With the tool we would be able to create our diagrams placing the states and transitions. Once the diagram is set up, all transitions need to have the transition string to change the ongoing state and initial and final states need to be selected (using right click and selecting "Mark as Start Node" for Initial state and "Mark as End Node" for Final state).



We can start the simulation with very simple steps. Firstly, select the tab called "Finite Automaton (simulation)" and enter the test input string to test. Then press start button to internally initialize the graph as a DFA and press step to process every character of the input string while the diagram is changing states and showing you which is the actual state and whether the string is being accepted or rejected. To set up a single loop transition, select the node and with right click select "Set connector loop" and add text for the transition.


In this beta version, we can also use Regular Expressions in our transitions thanks to the widespread use of regular expressions inside Delphi XE. 


From the same screen we can test our regular expressions and check whether if they match or not. There are still some issues to tackle like "empty string" and other considerations that I would be delving into detail in the following days. I am also working on a Layered-Tree-Draw Algorithm using Reingold-Tilford Algorithm and the enhancement of the better recognition of more complex regular expressions.

Have a look at this preview of the functioning of the graph, it is really worth it:


Stay tuned and give P-Zaggy a try from here:
Related links:

Saturday, 10 December 2011

Install multiple instances of the same Delphi application service

In this article you will find an example on How to install multiple instances of the same Delphi application service under Windows. This topic was raised a few years ago in StackOverflow and I have decided to give more details about how to use multiple instances of the same service.
The service needs to be unique in name and the best way to sort this out is using a parameter to describe the service in a unique way. The service itself will use this parameter to compose its name even though it is using the same  executable. In this example I will identify the services when installing the service using the command line with the following instruction: "myService /install Param1". Param1 will be used to compose the internal service name as myServiceParam1. If we want to use another instance, just install a second service with a different param name as: myService /install Param2.

To achieve this is pretty simple, just create the service using your Delphi XE and then create the methods ServiceBeforeUninstall and ServiceCreate:


Notice the System.ParamStr(2) that will use the second parameter which was input from the command line. The first parameter is the /install command needed to install the service.

After the execution of the following commands:

myService /install Param1
myService /install Param2

You will see two installed services using the same executable:


To uninstall them, use the opposite command:

myService /uninstall Param1
myService /uninstall Param2

But this is not ending here. Now the services are installed, but neither the service name is set nor the description. To achieve this, we need to use the ChangeServiceConfig functions from WinSvc - Service Control Manager unit.

Have a look at the complete source code:

This solution is using the example provided by koochangmin on his Delphi blog. If you have a closer look at the ServiceAfterInstall method, you will find the composition of the name and description which will be used to populate the values in the service:


That is the way the service needs to be created in order to let the application use the parameters in runtime.

If you have any problem uninstalling the services, just use the SC command to delete the service:

sc delete ServiceExampleParam1

Related links:

Monday, 7 November 2011

Monday, 17 October 2011

Monitoring Desktop Heap Memory and troubleshooting issues (part II)

Now that we know what Desktop Heap Memory is and How works (Monitoring Desktop Heap Memory and troubleshooting issues (part I)), we can extend this functionality and retrieve the Heap size from our Delphi app and even better, create a new desktop with a specified heap size.

To achieve this I am going to use the public API functions introduced in Windows Vista: CreateDesktopEx, which allows the caller to specify the size of desktop heap.And, GetUserObjectInformation that includes a  flag for retrieving the desktop heap size (UOI_HEAPSIZE).

Get Heap Size:
To get the heap size, we just need to invoke the GetUserObjectInformation using the UOI_HEAPSIZE flag:

procedure GetHeapSizeClick();
var
  HDesktop: HDESK;
  UHeapSize: ULong;
  tempDword: DWORD;
begin
  HDesktop := OpenInputDesktop(0, False, DESKTOP_CREATEMENU or
    DESKTOP_CREATEWINDOW or DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or
    DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS or DESKTOP_SWITCHDESKTOP or
    GENERIC_WRITE);

  GetUserObjectInformation(HDesktop, UOI_HEAPSIZE, @UHeapSize, SizeOf(UHeapSize), tempDword);
  OutputDebugString(PChar('UOI_HEAPSIZE ' + Inttostr(UHeapSize)));
  CloseDesktop(HDesktop);
end;

The output of the string is as follows:
Debug Output: UOI_HEAPSIZE 12288 Process Project1.exe (4224)

Where the value highlighted in bold, is the predefined size of your heap in the SubSystems\Windows registry key.

Create a new desktop with a specific heap size:
Using the CreateDesktopEx or CreateDesktopExW (Unicode):

var
  HDesktopglobal: HDESK;

procedure CreateDesktop();
var
  UHeapSize: ULong;
  tempDword: DWORD;
begin
  try
    HDesktopglobal := CreateDesktopExW('Z', nil, nil, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, nil, 3052, nil);
  except
    on e: exception do
      ShowMessage(SysErrorMessage(GetLastError));
  end;
  if HDesktopglobal <> 0 then
  begin
    GetUserObjectInformation(HDesktopglobal, UOI_HEAPSIZE, @UHeapSize, SizeOf(UHeapSize), tempDword);
    OutputDebugString(PChar('UOI_HEAPSIZE ' + Inttostr(UHeapSize)));
  end;
end;

procedure CloseDesk();
begin
  CloseDesktop(HDesktopglobal);
end;


We can check the result with dheapmon tool:
With more details using dheapmon -v and the looking for 'Z' desktop.


The output of the string is as follows:
Debug Output: UOI_HEAPSIZE 3052 Process Project1.exe (364)


Remember that the Desktop needs to be closed.

Related links:


Sunday, 16 October 2011

Open a list of URLs

Going on with my previous entries, in this post I am releasing a little tool to open a web browser (in this case google chrome) and populate it with a list of stored URLs. This tool would be the culmination of the articles: My first Google Chrome extension (Get all URLs from Google Chrome tabs) and Get Chrome active tab URL using Delphi. And as you know, I love automating and when I am surfing the internet I like keeping track of my URLs and being able to retrieving and saving them easily.

You can download the tool from here. The tool only needs the path to your browser (in my case google chrome) and a list of pre-saved urls (for example the output list from my chrome extension).

The tool looks like this:


And it uses the ShellExecute function from ShellAPI.

Enjoy it!.

Related Links:

Monitoring Desktop Heap Memory and troubleshooting issues (part I)

This article wants to put together a series of interesting articles to monitor the desktop heap memory and finally put forward a little in-house tool to monitor the output of Desktop Heap Information Monitor Tool v8.1 from AireSoft using the algorithm from "capturing output capture" from one of my previous posts.

Installing "Desktop Heap Information Monitor Tool v8.1:
To correctly install the tool (dheapdmp.zip), go to AireSoft web page and follow the installation steps from the web. If an error pops up, follow the guidelines from the following links:
- dheapInst - driver installation error occurred (2).
dheapinst - Driver Installation error occured (124).

If it helps, I got the error "Driver Installation error occured (124)" and I fixed it by changing the compatibility of dheapinst to Windows Server 2003 SP1.

Once installed, if we run dheapmon -l to install the monitor and then again dheapmon, we will see the heap memory information:


More about "Desktop heap memory":
The Desktop Heap Monitor is a tool that examines usage of desktop heap. 

WIN32 subsystem has internal heap area known as "desktop heap." When you run a large number of Windows-based programs, "Out Of Memory" error messages appear when you attempt to start new programs or try to use programs that are already running, even though you still have plenty of physical and pagefile memory available

This behavior can occur if the desktop heap in the WIN32 subsystem is depleted. To fix this problem follow the next workaround :
http://support.microsoft.com/kb/126962/
sourceMicrosoft.


Increasing "Desktop heap memory":

To increase desktop heap memory, we can use the tool "Microsoft Fix It 50496" that will increase the parameters automatically. If you want to fix it manually, you just need to go to the following registry path and tweak it:
- HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems

Where the default values for my windows vista are:

%SystemRoot%\system32\csrss.exe 
ObjectDirectory=\Windows 
SharedSection=1024,12288,512 
Windows=On 
SubSystemType=Windows 
ServerDll=basesrv,1 
ServerDll=winsrv:UserServerDllInitialization,3 
ServerDll=winsrv:ConServerDllInitialization,2 
ProfileControl=Off 
MaxRequestThreads=16



The first SharedSection value (1024) defines the heap size common to all desktops. This includes the global handle table.


The second SharedSection value (12288) controls the size of the desktop heap that is associated with an interactive window station (used for Windows objects). This static value is used to prevent ill- behaved applications from consuming too many resources. Because the desktop heap is mapped into each process' address space, this value should not be set to an arbitrarily high value (as it would decrease performance), but should only be increased sufficiently to allow all the desired applications to run.


The third SharedSection value (512) controls the size of the desktop heap for each desktop that is associated with a "non-interactive" window station.
source : microsoft.

Monitoring Desktop Heap Memory:
As it is quite difficult to monitor, I have developed a little tool that you can download from here, to log every change on the table result.

Just point the tool to the dheapmon executable and press start. Every 10s the output will be scanned and displayed into the component, taking into account the previous value, and if a change occurs it will be displayed in another colour.

Final notes:
Desktop Heap memory is related to "Out of Memory" issues and this article will help you to work with this parameter and how to deal with it and monitor it.

Stay tuned for Part 2, where I will go further with Desktop heap memory using Delphi.
Jordi Corbilla.

Related links:

Saturday, 8 October 2011

Sunday, 18 September 2011

Get Chrome active tab URL using Delphi

After developing my first Chrome extension to retrieve all URLs from Google chrome, I have been trying to reproduce the same behaviour using Delphi, but it was impossible. Chrome is still adding some new features and extending their extensions for developers. For example, others navigators such as Internet Explorer and Firefox they have a DDE extension to retrieve some of the properties but not available for Chrome.
The best way I found was using FindWindow and SendMessage windows functions to get the text from the tab and get tue URL. It's not a win solution but will help you to retrieve the URL of the active page without copy-paste action, just by switching to the next tab and retrieving data from the tool.

The basic code to achieve this is the following one:

function GetChromeActiveTabURL(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
  urls: TStrings;
  hWndMainWindow, hWndTab: HWND;
  Buffer : array[0..255] of Char;
  res : boolean;
begin
  res := true;
  urls := TStrings(Param);
  SendMessage(Wnd, WM_GETTEXT, Length(Buffer), integer(@Buffer[0]));
  hWndMainWindow := FindWindow('Chrome_WidgetWin_0', Buffer);
  application.ProcessMessages;
  if hWndMainWindow <> 0 then
  begin
    hWndTab := FindWindowEx(hWndMainWindow, 0, 'Chrome_AutocompleteEditView', nil);
    if hWndTab <> 0 then
    begin
      SendMessage(hWndTab, WM_GETTEXT, Length(Buffer), integer(@Buffer));
      urls.Add(Buffer);
      res := false;
    end;
  end;
  Result := res;
end;

procedure TUrlChrome.GetUrl(Sender: TObject);
var
  Urls: TStringList;
begin
  Urls := TStringList.Create;
  try
    EnumWindows(@GetChromeActiveTabURL, LParam(Urls));
    Memo1.Lines.AddStrings(Urls);
  finally
    FreeAndNil(Urls);
  end;
end;

To get the class name window, we can use Winspector to inspect chrome and get the names for the main window and for the tabs:

Chrome_WidgetWin_0:

Chrome_AutocompleteEditView:

And you can get the tool from here: ThundaxChromeURL.


I'm not proud of this solution, but at least it will work for current versions of Chrome. I also recommend to give a go to my chrome extension (It's not been published into Chrome market, it turns out that you have to pay a $5.00 fee), that is much better than the tool as it's able to get all urls.

Related links:

Saturday, 17 September 2011

My first Google Chrome extension (Get all URLs from Google Chrome tabs)

As a good internet researcher I always have hundreds of tabs opened in my Chrome navigator and sometimes I find a bit of chore to copy and paste all the URL that I have done a research on and that any other day I would be using again. So, that's my extension about, to display in a pop up window all the url's from all tabs to then copy them without problems (the correct name would be [search purposes] -> Get all URLs from Google Chrome tabs).
I have been struggling to write a little tool using Delphi, but it only works with Internet explorer and Mozilla firefox, so I thought it could be great to give chrome extensions a try. 
It is quite easy to develop and debug using all the development tools available from the navigator itself. As in the following example, I have opened 3 new tabs with the www.google.es URL, and if we click the extension button, will get a pop up list with the URLs from all tabs:

The source code is as follows:

manifest.json:
{
  "name": "Get All URL's Extension by Jordi Corbilla",
  "version": "1.0",
  "description": "Extension to display all the URL's from all TABs.",
  "browser_action": {
    "default_icon": "icon.ico",
    "popup": "urlList.html"
  },
  "permissions": [
    "tabs"
  ],
  "icons" : {

    "48" : "icon.ico",


    "128" : "icon.ico"


  }
}

urlList.html:
<!DOCTYPE>
<!--
 * Copyright (c) 2011 Jordi Corbilla. All rights reserved.  
-->
<html>
  <head>
    <script>
      chrome.tabs.getAllInWindow(null, function(tabs) {
        tabs.forEach(function(tab){
          myFunction(tab.url);	
        });
      });

      function myFunction(tablink) {
        console.log(tablink);
        var oNewNode = document.createElement("LI");
        urlList.appendChild(oNewNode);
        oNewNode.innerText=tablink;  
      }
</script>
</head>
  <body>
    <div>URL List</div>
    <ul ID = urlList>
    </ul>
  </body>
</html>

You can download the extension from here: URLJCExtension.zip. To install, you only need to unzip the file and then go to chrome://extensions/, expand developer mode and load my extension (from the unzipped folder):

As the extension uses the console log method, you can see all the links in the console (just for debug purposes, but it's really good to have a go on it).

Just right click on the extension icon and then "Inspect Pop-up" and you'll see the following window with the current list of urls:



Enjoy the extension!.

Related links:

Friday, 26 August 2011

Fluent Interfaces example using Delphi part I

I was introduced to Fluent interfaces when I was developing with Java using Dependency Injection and somebody told me that it could be really interesting if I post an example using Delphi and chaining method, and here I am!. I have developed a simple example that uses chaining methods to populate a THouse object with TDoors and TWindows objects with the hope it will make it easy to understand the concept. There are several examples on the net, but I couldn't find any interesting enough. So this simple example will try to introduce you to "how to develop fluent interfaces using method chaining" with the aim of writing more readable code. The overview of the architecture is the following one, using UML notation:


The Fluent Interface unit example is as follows (uFI.pas) using generics and interfaces:

// ***********************************************
// @author  jordi corbilla
// @comment Fluent interface composition example
//
// ***********************************************

unit uFI;

interface

uses
    Graphics, Contnrs, Generics.Collections, Classes;

type
    TWindow = class;

    IWindow = interface
        function SetColor(color: TColor): TWindow;
        function ToString(): string;
    end;

    TWindow = class(TInterfacedObject, IWindow)
    private
        FColor: TColor;
    public
        function SetColor(color: TColor): TWindow;
        function ToString(): string; override;
        class function New: TWindow;
    end;

    TDoor = class;

    IDoor = interface
        function SetColor(color: TColor): TDoor;
        function ToString(): string;
    end;

    TDoor = class(TInterfacedObject, IDoor)
    private
        FColor: TColor;
    public
        function SetColor(color: TColor): TDoor;
        function ToString(): string; override;
        class function New: TDoor;

    end;

    IHouse = interface
        function AddWindow(window: TWindow): IHouse;
        function AddDoor(door: TDoor): IHouse;
        function ToString(): String;
    end;

    THouseItemsList<T> = class(TObjectList)
        function ToString(): string; override;
    end;

    TDoorList = class(THouseItemsList<IDoor>)
        function ToString(): string; override;
    public

    end;

    TWindowList = class(THouseItemsList<IWindow>)
        function ToString(): string; override;
    end;

    THouse = class(TInterfacedObject, IHouse)
    private
        FDoorList: TDoorList;
        FWindowList: TWindowList;
    protected
        function AddWindow(window: TWindow): IHouse;
        function AddDoor(door: TDoor): IHouse;
    public
        property WindowList: TWindowList read FWindowList;
        property DoorList: TDoorList read FDoorList;
        class function New: IHouse;
        function ToString(): String; override;
        constructor Create();
        destructor Destroy(); override;
    end;

implementation

uses
    SysUtils;

{ THouse }

function THouse.AddDoor(door: TDoor): IHouse;
begin
    Self.FDoorList.Add(door);
    result := Self;
end;

function THouse.AddWindow(window: TWindow): IHouse;
begin
    Self.FWindowList.Add(window);
    result := Self;
end;

constructor THouse.Create;
begin
    FDoorList := TDoorList.Create;
    FWindowList := TWindowList.Create;
end;

destructor THouse.Destroy;
begin
    FreeAndNil(FDoorList);
    FreeAndNil(FWindowList);
    inherited;
end;

class function THouse.New: IHouse;
begin
    result := Create;
end;

function THouse.ToString: String;
var
    description: TStringList;
begin
    description := TStringList.Create;
    try
        description.Add(Self.FDoorList.ToString);
        description.Add(Self.FWindowList.ToString);
    finally
        result := description.Text;
        description.Free;
    end;
end;

{ TWindow }

class function TWindow.New: TWindow;
begin
    result := Create;
end;

function TWindow.SetColor(color: TColor): TWindow;
begin
    Self.FColor := color;
    result := Self;
end;

function TWindow.ToString: string;
begin
    result := 'Window color ' + ColorToString(FColor) + sLineBreak;
end;

{ TDoor }

class function TDoor.New: TDoor;
begin
    result := Create;
end;

function TDoor.SetColor(color: TColor): TDoor;
begin
    Self.FColor := color;
    result := Self;
end;

function TDoor.ToString: string;
begin
    result := 'Door color ' + ColorToString(FColor) + sLineBreak;
end;

{ THouseItemsList }

function THouseItemsList<T>.ToString: string;
var
    i: Integer;
    description: String;
begin
    for i := 0 to Self.count - 1 do
        description := description + ' ' + Self[i].ToString;
    result := description;
end;

{ TDoorList }

function TDoorList.ToString: string;
var
    description: TStringList;
begin
    description := TStringList.Create;
    try
        description.Add('Number of doors: ' + inttostr(Self.count));
        description.Add('Descriptions: ');
        description.Add( inherited ToString);
    finally
        result := description.Text;
        FreeAndNil(description);
    end;
end;

{ TWindowList }

function TWindowList.ToString: string;
var
    description: TStringList;
begin
    description := TStringList.Create;
    try
        description.Add('Number of Windows: ' + inttostr(Self.count));
        description.Add('Descriptions: ');
        description.Add( inherited ToString);
    finally
        result := description.Text;
        FreeAndNil(description);
    end;
end;

end.

Now it comes when we can use the object using FI notation in a more readable way:

var
    House: IHouse;
begin
    House := THouse.New.AddWindow(TWindow.New.SetColor(clFuchsia)).AddDoor(TDoor.New.SetColor(clWhite))
        .AddWindow(TWindow.New.SetColor(clRed)).AddDoor(TDoor.New.SetColor(clGreen));
    Memo1.Lines.Add(House.ToString);
    House := nil;

    House := THouse.New;
    House.AddWindow(TWindow.New.SetColor(clRed)).AddWindow(TWindow.New.SetColor(clBlue)).AddWindow(TWindow.New.SetColor(clGreen));
    House.AddDoor(TDoor.New.SetColor(clRed)).AddDoor(TDoor.New.SetColor(clBlue)).AddDoor(TDoor.New.SetColor(clGreen));
    Memo1.Lines.Add(House.ToString);
    House := nil;

Notice that now, we can chain our objects, composing the structure of the House by using the AddWindow and AddDoor method. To display the result I'm using the ToString method that will do the job for my purpose.

And the result of the previous execution:


Number of doors: 2
Descriptions: 
 Door color clWhite
 Door color clGreen


Number of Windows: 2
Descriptions: 
 Window color clFuchsia
 Window color clRed


Number of doors: 3
Descriptions: 
 Door color clRed
 Door color clBlue
 Door color clGreen


Number of Windows: 3
Descriptions: 
 Window color clRed
 Window color clBlue
 Window color clGreen


Just play with it and you'll experience the powerfulness of this method. I hope you like it.

I'm looking forward to your comments.
Jordi

Monday, 22 August 2011

Building my own Delphi Physics Engine part IX

I'm quite familiar with GDI, the graphics provided under Microsoft and which is widely used in Windows applications. TDPE is now ready to use Direct2D as now it's fully supported by Delphi 2010 and XE. According to MSDN, Direct2D is: a hardware-accelerated, immediate-mode, 2-D graphics API that provides high performance and high quality rendering for 2-D geometry, bitmaps, and text. The Direct2D API is designed to interoperate well with GDI, GDI+, and Direct3D.
As I'm testing this under Windows Vista, I've had to upgrade my windows version to Service Pack 2 and then I've installed the following update (KB971512 - The Windows Graphics, Imaging, and XPS Library contain the latest advancements in modern graphics technologies for gaming, multimedia, imaging and printing applications.). Direct2D is already installed in Windows 7.

We can use the same methods from TCanvas for our TDirect2DCanvas as they derive from the same ancestor TCustomCanvas. But you need to check the documentation for differences in the way they work.

A simple way to use Direct2D is as follows:

uses
    Direct2D, D2D1;

procedure Paint();
begin
    if TDirect2DCanvas.Supported then
    begin
        d2dCanvas := TDirect2DCanvas.Create(Canvas, ClientRect);
        try
            d2dCanvas.RenderTarget.beginDraw;
            d2dCanvas.RenderTarget.Clear(D2D1ColorF(clBlack));
            d2dCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
            // drawing goes here
            Paint(d2dCanvas);
            d2dCanvas.RenderTarget.EndDraw;
        finally
            FreeAndNil(d2dCanvas);
        end;
    end;
end;

Here is the result of the Physics Engine using a Direct2D Render and a GDI Render:





You will see the difference when switching from GDI to Direct2D as the performance is quite different. When it comes to Direct2D, my computer is getting quite slower as my graphic card is not powerful at all and we can see that it takes a while to render the image.


GDI uses Pixel graphics but Direct2D can supports vector graphics as well, in which mathematical formulas are used to draw the lines and curves. Vector graphics provides high quality rendering independent of resolution of the device, while the pixelated graphics has dependency with resolution which may results in choppy graphics.

Most of the GDI APIs are not using anti-aliasing and transparency. Ofcrouse there are functions to do so but always there’s programming cost for taking advantage of these features. Also if we apply transparency and anti-aliasing, the computations are done using CPU. Direct2D can take advantage of graphics hardware and delegate the computationally intensive tasks to GPU


Get the latest version here: ThundaxBallDemo v1.584.
Interaction:
'd' will drop a box with a random colour and a constant angular velocity.
'f' will drop a circle with a random colour and a constant angular velocity.
'mouse interaction' mouse is able to grab items.
'q' Enable/Disable GDI or Direct2D rendering.

Note: You need to have installed Direct2D to run the app using Direct2D, otherwise GDI will be used.

Related links:

Wednesday, 10 August 2011

Building my own Delphi Physics Engine part VIII

TDPE is almost ready and it will not take long to release the first stable library!. I am eager to continue working on the project trying to sort out different physic scenarios  to make my dynamic engine even more realistic. Do not hesitate to give it a try as you will find the experience quite interesting. I am still working on the n-edge object and the cutting tool and trying to refactor all the code to cope with a layer architecture. Using this concept, I want to structure my system in a way that every component works using a certain level of abstraction. As you see in the next figure, every object is allocated in the screen while there is another layer which is responsible for the collision detection and another one for the forces interaction. You will notice in the video that there are still little issues to tackle regarding the object interaction as sometimes we can experience overlapping.


In the figure above, you can see that now the items are not rigid and they interact with each other as they were real items. Notice that the square item will go through the round shape of the circle.



Enjoy the video!.

Get the latest executable here: ThundaxBallDemo v1.504.
Interaction:
'd' will drop a box with a random color and a constant angular velocity
'f' will drop a circle with a random color and a constant angular velocity
'mouse interaction' mouse is able to grab items

Related links:

Sunday, 10 July 2011

Continuous Integration for your Delphi projects using Jenkins CI

Going on with the utilization of Msbuild, I'm putting forward this post using Jenkins CI (Continuous Integration) previously known as Hudson, for your Delphi projects under Windows Vista. In a nutshell, Jenkins provides an easy-to-use so-called continuous integration system, making it easier for developers to integrate changes to the project, and making it easier for users to obtain a fresh build. The automated, continuous build increases the productivity. (Source: What is Jenkins?). With these simple steps I'll lead you throughout the whole installation and configuration of your first Delphi built project using Jenkins CI and MsBuild.

1 . Download the latest version of Jenkins CI.
Use the following link to download the latest windows installer, in my case v1.419. The default installation path is C:\Program Files\Jenkins and there you'll find the service wrapper jenkins.exe and the Java web archive (jenkins.war) that is very useful to start the Jenkins if you have difficulties installing it with a container. It's very easy to run Jenkins by itself using the command: java -jar jenkins.war (which uses Winstone as a container).


2. Setting up environment variables.
To make sure that Jenkins runs perfectly, we need to set up the JENKINS_HOME environment variable:

3. Adding administrator privileges to Jenkins windows service.
We need to be sure that the service has enough permissions to be running. To do this, go to console and type down "services.msc". Then look for Jenkins service and add the log on information using an administrator account.
I had a lot of troubles trying to execute MSBuild from Jenkins until I realised that the service didn't have enough permissions.

4. Installing Jenkins CI plug-ins.
Once everything is done, we can go on with Jenkins and open a web explorer and type http://localhost:8080. Now we need to add the following plug-ins: Jenkins MSBuild Plugin and Hudson Setenv Plugin. To install them go to "Manage Jenkins"-> "Manage Pluggins" -> Available and look for them. Then, save the changes at the end of the page and reload Jenkins.
Once installed, you'll find them under the Installed section:

5. Configure MSBuild.
Now the plug-in is ready, and we need to supply the path of our MSBuild. Go to "Manage Jenkins" -> "Configure Jenkins" and add the Msbuild information in the MSbuild section:

6. Adding environment variables.
As we are trying to build Delphi projects we need to set up Jenkins with the same environment variables included in rsvars.bat batch file. Go to "Manage Jenkins" -> "Configure Jenkins" and add the following environment variables according to your Delphi version:

7. Setting up your project.
Start a new job with your project description and choose the "Build a free-style software project" type. And add the following MSbuild information to build your project (dproj file):

8. Build your Project.
Everything is ready to do the build. Now execute the "Build now" option and you'll see your project being compiled and built using MSBuild.

Now, you can add your Delphi projects and improve the quality of your software.

Related Links:

Monday, 4 July 2011

Delphi Msbuild

Msbuild has been included since Delphi 2007 to automate our Delphi builds and manage our projects in a better way. I have developed a custom application to provide automated Builds for Delphi (2007 / 2009 / 2010 / XE -Win32) using MSBuild. The app called Thundax Delphi Builder is available here for free. This little tool generates a batch file to call the list of projects and it displays the information using a TMemo getting the info from the console window using a pipe with the capture method from my previous post.
If you take a look at my application, you will see a output section and a configuration section. In the configuration section we need to add the list of projects to compile/build, the path of our Delphi binaries and the different MSBuild commands we want to execute.


As soon as all the parameters are correct, we can hit the "Build" button. The Build button generates a batch file called build.bat. This batch file contains the list of all our projects with the correct commands for MSBuild. Just take a look at the generated batch file and you will understand what is this doing.

First of all, it sets the environment variables for the target compiler. It means that if you enter in the "Bin" section  the path to your DelphiXE binaries, it will set MSBuild for DelphiXE. To do this, we only need to run rsvars.bat batch file which contains:

@SET BDS=C:\Program Files (x86)\Embarcadero\RAD Studio\7.0
@SET BDSCOMMONDIR=C:\Users\Public\Documents\RAD Studio\7.0
@SET FrameworkDir=C:\Windows\Microsoft.NET\Framework\v2.0.50727
@SET FrameworkVersion=v2.0.50727
@SET FrameworkSDKDir=
@SET PATH=%FrameworkDir%;%FrameworkSDKDir%;%PATH%
@SET LANGDIR=EN

Of course this tools is just a "little tool" to help you understand how Msbuild works and how to invoke it from the command line. I use continuous integration tools and some day I will talk about one of them, for example Hudson continuous integration.

PS: If you want to download the app, download my Calc Hash to make sure that the MD5 hash is correct. To check it, download the app, remove the " (0c3c3ab27a6000d8881974a411959828)." hash and check the file with the calc. If the app is correct, you should get the same hash.

Related links: