Fast Line Rendering in WPF

February 14th, 2012

Fast Rendering in WPF using GDI using a Background Thread

 The Problem

Rendering tens of thousands of lines was taking several seconds to render in WPF.

I was trying to draw a graph with a dozen series or so in real-time (the data comes in at 10Hz, but we’d settle for 1 or 2 frames per second as a worst case). Each series had over 1,000 data points which I represented as a line graph, and implemented with a Path object that had a StreamGeometry. This should have been the fastest way to draw a path, and profiling my code it was pretty fast. However, the actual rendering on the render thread took a many seconds and this made the UI unresponsive (it needs the render thread too, of course).

What I did

I looked at Petzold’s article and it made drawing the paths very fast. The hang up was still in the render thread. That solution helps if you have a lot of objects. I actually have about 12 paths, but they are composed of 10s of 1000′s of lines. My best theory is that the GPU is turning all those lines into pairs of triangles and that’s surprising slower than doing Bresenham’s algorithm in software. See Jeremiah Morril’s deep dive into wpf rendering.

It’s shocking (to me) that software rendering would be so much faster than hardware rendering. I haven’t verified this, but I believe the GPU is rendering each line as two triangles as if it were a rectangle. And apparently this is much slower than drawing a simple line.

Using GDI+ to draw the lines on a bitmap gave me performance improvement of two orders of magnitude. (I guess GPU development has been driving the game world whereas fast rendering of polygons for 3D is where the money is at.)

I’m hoping to get some time to try out Direct2D to see how it performs at drawing lines. Alas, that wouldn’t work for my project because Direct2D isn’t supported in older versions of windows. I don’t know if it would help since it uses the two-triangle method of drawing lines.

A huge bonus using the GDI library is that I can chose which thread to do the line rendering. Using a background thread keeps the rest of the UI responsive. Once the bitmap is rendered, it’s copied to the screen in an Image control (the render thread then renders this image, which is a super fast bitmap copy). Since I only allow one background thread, additional requests to draw are ignored until my renderer has finished: A simple way to adjust the frame-rate for the CPU.

Acknowledgements and References

Thanks for Tamir Khason for pointing me in the right direction for creating an interop bitmap. Thanks to Dwayne Need for getting me going with a HostVisual to draw into.

And see this blog for an excellent analysis of the speed of different techniques. For me drawing direct aliased lines was the key. So GDI+ was the way to go. I considered Direct2D, but if it uses the GPU, it may turn out to have the same problem WPF did. I’m hoping to try that eventually, but Direct2D doesn’t work in XP, and we have to stay compatible.

The Code

See my test program here

Here are some of the key bits in the code:

GraphCanvas.xaml is the user control for drawing the lines. All it has is an image control to host the bitmap. Just this:
Xaml Code for  graphics canvas

The code behind GraphControl.cs has a BackgroundWorker called RenderWorker that draws the paths with a couple of GDI calls.

When that’s done, you just copy the bitmap into the image control.

 

RenderData is my own structure, like Path it has figures and points to draw between. Normally I’d use a Path but it’s a dependency object and doesn’t move easily between threads.

Initialize() creates the bitmaps in a few lines of code. This is what Tamir and Dwayne Need’s blogs helped me with. See the code for the details.

The background rendering technique is a really powerful technique whenever you have to draw something that takes any length of time. The rest is all about getting fast lines.

I hope you find that useful. Please leave me a reply if you do.

 

 

Glenn

NTG becomes an Appcelerator Partner

February 3rd, 2012

NTG is pleased to announce a partnership with Appcelerator!

While the market for mobile applications is larger than ever before, developing and supporting multiple platforms can be complicated and expensive.  Appcelerator is a new software company that is enabling businesses to employ Web developers to build intuitive, content-rich native applications for multiple devices using a common cross-platform code base. By using Appcelerator products, Web developers are able to:

  • Cut development time in half by building apps once and deploying on multiple platforms.
  • Drive down development costs.
  • Avoid vendor lock-in by using an open platform that maximizes choices.

NTG looks forward to reselling the Appcelerator platform and providing Appcelerator-related development and enablement services.

chadu

How to Disable Design View in Flash Builder

January 30th, 2012

By Chad Upton – senior consultant

Disable Flash Builder’s “Design Mode” if you want to save some memory or avoid some errors that some plugins cause when using design view. It’s pretty straight forward, go to the Window menu and click “Enable Design Mode” to remove the checkmark:

alaint

Flex Mobile: Skinning the ActionBar

January 25th, 2012

By Alain Thibodeau – Consultant

In a Flex mobile application, the ActionBar is the main bar at the top which contains several content areas. These areas consists of the titleDisplay, actionGroup, titleGroup and navigationGroup skin parts. With a custom skin you can move these skin parts where you need them and add background images.

I first hit Photoshop and created my visuals for the ActionBar as shown below. (I know most of you designers out there will give me the “eye brow” with my design, but go easy on me please…)

I sliced out the logo and a 3 pixel slice of the bar. Looking like this:

      

I then created a Flex Mobile Project. In the main project file, I referenced a css file which contains this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@namespace s "library://ns.adobe.com/flex/spark";

s|ActionBar {
skinClass:ClassReference("skins.CustomActionBarSkin");
defaultButtonAppearance: beveled;
}

s|ActionBar #titleDisplay {
fontWeight:normal;
color: #000000;
}

s|ActionBar #titleGroup {
fontWeight:normal;
color: #FFFFFF;
}

The most important part of the css file is the declaration of the skin class for our custom skin. The other styles are for the text in the titleGroup  and titleDisplay groups.

Here is the custom action bar mxml skin.  It could have been written in ActionScript, however, I did not notice any performance issues with mxml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Metadata>
        [HostComponent("spark.components.ActionBar")]
    </fx:Metadata>

    <s:states>
        <s:State name="titleContentWithActionAndNavigation"/>
        <s:State name="titleContentWithNavigation"/>
        <s:State name="titleContentWithAction"/>
        <s:State name="titleContent"/>
        <s:State name="titleWithActionAndNavigation"/>
        <s:State name="titleWithNavigation"/>
        <s:State name="titleWithAction"/>
        <s:State name="title"/>
    </s:states>

    <s:Image source="@Embed('/assets/images/bar.png')"
             left="0"
             right="0"
             scaleMode="stretch"/>

    <s:Image source="@Embed('/assets/images/logo.png')"
             horizontalCenter="0"/>

    <s:Group id="navigationGroup"
             left="12"
             top="15"/>

    <s:Group id="titleGroup"
             left="10"
             top="68"/>

    <s:Group id="actionGroup"
             right="12"
             top="15"/>

    <s:Label id="titleDisplay"
             horizontalCenter="0"
             top="8"/>
</s:Skin>

The modifications to the skin are adding the background images and moving the skin parts where we need them. In this case, my slice of the background is stretched across the width of the application. The logo is then put on top of the bar and centered, aligning itself with the lines and shadows.

What I didn’t add is consideration for different dpis. This could be accomplished by having different images for the different screen resolutions.

Lastly, here is the view that defines what goes in the content areas. We could extend the ActionBar and add more skin parts as needed. In our case we are using the “titleContent” SkinPart for some form of subtitle text area.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        title="Action Bar Skin">

    <s:navigationContent>
        <s:Button label="Back"/>
    </s:navigationContent>

    <s:titleContent>
        <s:Label text="Some Text Here"/>
    </s:titleContent>

    <s:actionContent>
        <s:Button label="Action" />
    </s:actionContent>

</s:View>

Here is what the application looks like with the custom ActionBarSkin:

chadu

Creating an HRule in MXML with Spark Components

January 10th, 2012

By Chad Upton – senior consultant

Although there is an MX HRule component, there is not a Spark equivalent. You could still use the mx component, but it’s better to use a vector graphic for something as simple as a straight line – particularly if you’re building a mobile application.

For a horizontal rule, you can simple set the width of the line, the color, and the weight (stroke/thickness).

1
2
3
4
5
<s:Line width="100%">
    <s:stroke>
        <s:SolidColorStroke color="0x000000" weight="2"/>
    </s:stroke>
</s:Line>

You can also draw a line from point to point:

1
2
3
4
5
<s:Line xFrom="10" xTo="20" yFrom="10" yTo="20">
    <s:stroke>
        <s:SolidColorStroke color="0xFF0000" weight="1"/>
    </s:stroke>
</s:Line>

Be sure to “like” us on facebook to stay in the loop and checkout our course calendar for flex, html5, javascript, and other platform training programs — online and in the classroom.

Derek Santos

Flex IMXMLObject Interface

January 6th, 2012

By Derek Santos – Consultant

This hidden gem in Flex can really help keep your MXML code clean and separated from your view logic. A great way to use it is to encapsulate your view logic into a ViewHelper. IMXMLObject has only one function.

1
function initialized(document:Object, id:String):void;

Here is Adobe’s documentation for this function:

“Called after the implementing object has been created and all component properties specified on the MXML tag have been initialized.”

What this means is that once the parent is created and has intialized its properties, it will pass a reference of the parent to your IMXMLObject implementation. So, as an example, let’s create a simple ViewHelper. First, create a class and implement IMXMLObject.

ViewHelper.as

1
2
3
4
5
6
7
8
9
class ViewHelper implements IMXMLObject {
   
    public var view:MyView;

    public function initialized(document:Object, id:String):void {
        this.view = document as MyView;
    }
   
}

Notice that I am keeping a reference of the view by assigning the value of document to an instance variable called view. Once you do this, you can work with your view and apply any logic you may need.

Once you’ve created your ViewHelper, you simply need to declare it in your MXML file. In this case, that would be MyView.

MyView.mxml

1
2
3
4
5
6
7
8
9
10
11
<s:Group
   xmlns:fx="http://ns.adobe.com/mxml/2009"
   xmlns:s="library://ns.adobe.com/flex/spark"
   xmlns:local="*"
   >

    <fx:Declarations>
        <local:ViewHelper id="helper" />
    </fx:Declarations>
   
</s:Group>

Notice that you do not need to pass a reference to “this” anywhere. This keeps your MXML very clean and makes the ViewHelper a little more portable. Comments are welcome!

alaint

Flex Mobile: IconItemRenderer Example

January 5th, 2012

By Alain Thibodeau – Consultant

For Flex mobile applications you should use the mobile optimized item renderers. The default base class for mobile renderers is the LabelItemRenderer. Extending this is the IconItemRenderer, which is a handy renderer that includes an icon area, label and message.

Here is an example of using IconItemRenderer in the simplest form:

MyIconItemRenderer.mxml

1
2
3
4
5
6
7
8
9
10
<!--?xml version="1.0" encoding="utf-8"?-->
<s:IconItemRenderer
    xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    iconField="icon"
    labelField="label"
    messageField="message"
    iconWidth="45"
    iconHeight="45"
    />

HomeView.mxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark">
    <s:List
        width="100%"
        height="100%"
        itemRenderer="MyIconItemRenderer"
        >
        <s:dataProvider>
            <s:ArrayList>
                <fx:Object
                    label="Title 1"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
                <fx:Object
                    label="Title 2"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
                <fx:Object
                    label="Title 3"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
                <fx:Object
                    label="Title 4"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
                <fx:Object
                    label="Title 5"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
                <fx:Object
                    label="Title 6"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    />
            </s:ArrayList>
        </s:dataProvider>
    </s:List>
</s:View>

Outcome:

 
 

Here is an example of IconItemRenderer using messageFunction, labelFunction to display content other than what is directly in our dataprovider. I added a color property to my dataprovider objects.

Updated HomeView.mxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?xml version="1.0" encoding="utf-8"?>
<s:View
        xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    title="HomeView"
    >
           <s:List
        width="100%"
        height="100%"
        itemRenderer="MyIconItemRenderer"
        >
        <s:dataProvider>
            <s:ArrayList>
                <fx:Object
                    label="Title 1"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Red"
                    />
                <fx:Object
                    label="Title 2"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Blue"
                    />
                <fx:Object
                    label="Title 3"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Green"
                    />
                <fx:Object
                    label="Title 4"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Pink"
                    />
                <fx:Object
                    label="Title 5"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Brown"
                    />
                <fx:Object
                    label="Title 6"
                    icon="http://www.adobe.com/homepage/include/style/homepage/adobe_logo_45x45.jpg"
                    message="This is a message"
                    color="Yellow"
                    />
            </s:ArrayList>
        </s:dataProvider>
    </s:List>
</s:view>

And here is the modified MyIconItemRenderer.mxml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<s:IconItemRenderer
    xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    iconField="icon"
    labelField="label"
    labelFunction="getLabel"
    messageField="message"
    messageFunction="getMessage"
    iconWidth="45"
    iconHeight="45" >
    <fx:Script>
        <![CDATA[
            private function getMessage(item:Object):String {
                return item.message + " - " + new Date().toDateString();
            }
                          private function getLabel(item:Object):String {
                return item.message + " - " + item.color;
            }
        ]]>
    </fx:Script>
</s:IconItemRenderer>

Outcome:

 

 

For online and in-person Flex and AIR training, checkout our course finder.

oliverm

JavaScript Developer Survey

December 4th, 2011

Looks like this is turning into an annual event. Given JavaScript’s importance in the Mobile/HTML5 space, it will be interesting to see how developers are using it:

http://dailyjs.com/2011/12/01/javascript-developer-survey-2011/

 

chadu

NFC vs QR Codes

December 4th, 2011

By Chad Upton – senior consultant

Smart phones brought the productivity of computers to our pockets, but their tiny size didn’t make any improvements to the full-size keyboards we leave at our desks. Smart phone users want quicker ways to enter text or website URLs.

QR Codes

Square bar codes, or QR codes are an easy way to “scan” text into your phone. This makes it easy for you to visit a website or copy useful text, such as phone numbers or contest entry codes into your phone without touching the keyboard.

QR codes have been around since they were invented by a Japanese company in 1994. Originally used to track products in warehouses, QR codes were designed to replace traditional “vertical line” bar codes. Traditional bar codes just represent numbers, which can be looked up in a database and translated into something meaningful. QR, or “Quick Response” bar codes were designed to contain the meaningful info right in the bar code.

They’ve been a successful marketing tool in Asia and Europe, but they’ve had limited success in North America. A recent survey of college students found that 81% of college students owned smart phones, but only 22% were able to successfully scan the QR code. Many students didn’t know a third party app was required on most platforms (iOS, Android, BlackBerry). Windows Phone is the only mobile platform that supports QR codes natively, and it has one of the smallest market shares.

Data types supported:

  • URL
  • Text
  • Phone Number
  • SMS Message

The support for Phone Numbers and SMS Messges is great, it allows you to scan a QR code and have that info pre-populated for you.

NFC

Near Field Communication (NFC) is a technology that offers similar use cases to QR codes, but through a different medium. While QR codes require a camera to “scan” the code, NFC uses a low powered magnetic field to send and receive data. That’s right, NFC has a peer to peer mode that allows bi-directional communication.

NFC is supported in the latest versions of Android, BlackBerry OS and Symbian. iPhone and Windows Phone support is expected next year. Although it has a lot of superior capabilities to QR codes, it does require specialized hardware in the phone. NFC is still fairly young and a little over a dozen handsets are currently available with the technology, but that number is expected to grow quickly.

Data types supported:

  • URL
  • Text
  • Phone Number
  • SMS Message
  • Email Message
  • Business Card/VCard
  • Signature
  • Bluetooth or Wifi connection parameters

As you can see, NFC supports a few more data types than QR codes. The vcard support is great, bump your phone with someone else’s to exchange contact info.

Comparison

QR codes and NFC offer some overlap in uses, but each one has fundamental advantages over the other for certain situations. If you’re running a contest and you want users to enter via text message, QR codes could be scanned from TV, magazines, newspapers, billboards, transit ads, etc. It would be more costly to put an NFC tag in every magazine or newspaper, so QR might be the right choice here.

But, lets say you were attending a large event and wanted to connect to the secure wifi network. You could flip through all the event info to find the SSID and password for the network, but you’d much prefer tapping your phone as you enter and have it automatically connect in seconds. This is how technology is supposed to work.

Both technologies help you get small amounts of info into your phone without typing it, but each one has pros and cons.

Technology Pros Cons
QR Codes inexpensive, print/display anywhere, all phones have the hardware, scan pre-composed SMS messages can be difficult or time consuming to scan, not always weatherproof
NFC good native device support, weatherproof, quick and easy to scan, two way communication possible more costly, cannot be used in as many ways as QR codes, limited phones supported at this time

Be sure to “like” us on facebook to stay in the loop.

edv

NTG developing 2 new Native PlayBook Dev courses

December 2nd, 2011

New Toronto Group, an Elite RIM Partner, is currently developing 2 new training courses for RIM. The first course will be focused on “Developing Native Games for the PlayBook” and will be available in March 2012. The second course will be focused on “Developing Native Applications for the PlayBook” and will be available in May 2012. Table of Contents coming soon.

  • Developing Native Games for the PlayBook (2 days)
  • Developing Native Applications for the PlayBook (2 days)