Copy Your Favorite Nokia Apps
                                09/25/09
Ariya Hidayat
Agenda

• Mobile platform challenges:
  – differences vs desktop
  – things to keep in mind
• Examples which demonstrate:
...
Spread the Love

        All examples are available from...




             labs.qt.nokia.com


            bit.ly/graphi...
Desktop vs Mobile Platforms

• Hardware power
• Screen size and resolutions
• Input method
• Network access




          ...
Nokia N95

• CPU: 332 MHz ARM11
• RAM: 128 MB
• Screen: 240 x 320 (QVGA)
• 9-Button keypad




                           ...
Nokia E71

• CPU: 369 MHz ARM11
• RAM: 128 MB
• Screen: 320x240 (QVGA)
• Full QWERTY Keypad




                          ...
Nokia 5800 XpressMusic

• CPU: 434 MHz ARM11
• RAM: 128 MB
• Screen: 360 x 640 (nHD)
• Touch interface




               ...
Processing Power

• ARM architecture
   – Different than x86
• Limited memory




                          8
Graphics Power

• Lower resolution
• Software rendering
   – hardware acceleration with OpenGL ES
• Font metrics




     ...
Input Methods

• Keypad, not keyboard
  – often not full QWERTY
• No mouse
   – don't bother with mouse move event
• Touch...
Network Access

• Wireless LAN
  – sometimes not available
• Other data access
  – slower data rate




                  ...
Development Flow

• Device emulator
• Remote debugging
• Performance test
• Profiling tools




                     12
Example #1
Digital Clock
Digital (Vintage) Clock




                          14
Framed Digits

      plain digits   with frame




                          gradient




                                ...
Gradient is Expensive, so...
QLinearGradient gr(QPoint(0, 0), QPoint(0, height));
gr.setColorAt(0.00, QColor(128, 128, 128...
Sliding Effect




            translating both pixmaps



                                       17
Sliding Effect: The Code
QPainter p(this);
int y = height() * currentFrame / 100;
p.drawPixmap(0, y, m_lastPixmap);
p.draw...
Rotation

           transform.rotate(30, Qt::ZAxis)




                                             19
Perspective Transformation



transform.rotate
(60, Qt::XAxis)




                   transform.rotate(60, Qt::YAxis)


  ...
Rotating Effect




              rotating pixmaps



                                 21
Rotating Effect: The Code
QTransform transform;
transform.translate(width() / 2, height() / 2);
transform.rotate(angle, Qt...
Flipping Effect




            rotating and interleaving
                  two pixmaps

                                 ...
A Trick with QBasicTimer
QBasicTimer ticker;
ticker.start(1000, this);

void timerEvent(QTimerEvent*)
{
  // update the cl...
QTimeLine for Frame-based Animation
QTimeLine animator;
animator.setFrameRange(0, 100);
animator.setDuration(600);
animato...
Sacrifice Quality for Speed

       Beauty is in the eye of the beholder.




                                            ...
Aliasing during Animation
QPainter p(this);
p.setRenderHint(QPainter::SmoothPixmapTransform, false);
p.setRenderHint(QPain...
Example #2
Weather Info
Weather Info




               29
Screen Orientation




       requires different layout strategy




                                            30
Lock the Orientation

                           S60-specific, usually you do
                              NOT need to do...
Animation with Graphics View


                          item movement &
                               opacity




      ...
Using Web Service
<weather>
<forecast_information>
  <city data="Oslo, Oslo"/>
  <postal_code data="Oslo"/>
  <latitude_e6...
Create the Network Request
     http://www.google.com/ig/api?hl=en&weather=oslo

QUrl url("http://www.google.com/ig/api");...
Handle the Network Reply
     http://www.google.com/ig/api?hl=en&weather=oslo

QUrl url = networkReply->url();
data = QStr...
XML Stream Reader for Parsing


QXmlStreamReader xml(data);
while (!xml.atEnd()) {
  xml.readNext();
  if (xml.tokenType()...
Scalable Icons with SVG

             bitmap vs vector




                                37
Optimize Your SVG
<g>
      <ellipse cx="10" cy="10" rx=2" ry="2"/>
</g>




<ellipse cx="10" cy="10" rx=2" ry="2"/>



  ...
SVG Loading Time Comparison




             Use tools like:
           codedread.com/scour
          svgmin.googlecode.co...
Example #3
Flight Tracking
Flight Tracking




                  41
No Web Service?
      Use “mobile” version of the web site.




                                              42
Web Scraping

• Grab the HTML contents
• Scrap it
   – remove unnecessary clutters
   – parse and extract the interesting ...
Parsing HTML with XML Stream Reader

• HTML != XML
• Potentially provoke the parser (→ errors)
  – Solution: “scrub it”, i...
The Usual Tricks

• Use network request and reply
• Contents
   – Construct the request
   – Get the HTML data
   – Clean ...
Beware of Different Font Metrics




                                   46
Example #4
Magnifying Glass
Image Zoom




             48
Shadow with Radial Gradient




                              magnifier




                                          49
Shadow with Radial Gradient
 Prepare the gradient brush
QRadialGradient g;
g.setCenter(radius, radius);
g.setFocalPoint(ra...
Panning with Mouse/Finger/Stylus
                 Record the tap position
void mousePressEvent(QMouseEvent *event) {
    i...
Avoid Accidental Panning




   panning is not started   past the threshold




                                          ...
Turbo Downscaling (We're Cheating!)




     With filtering



                        Fast, no filtering



             ...
Example #5
  Maps
Maps (with OpenStreetMap)




                            55
OpenStreetMap vs [Google,Yahoo]Maps

• Free content
   – Creative Commons Attribution-ShareAlike 2.0
• API does not requir...
Getting the Rendered Tiles

• Each tile is 256 x 256 pixels
• Zoom level of 0 → the whole world
• Zoom level of 17 → most ...
Rendering and Caching Strategy




          cached tiles   application window
                                           ...
Avoid Accidental Panning




   panning is not started   past the threshold




                                          ...
Night Mode




             60
Night Mode: The Code
                 Color channel inversion

QPainter p(this);
p.setCompositionMode
  (QPainter::Composi...
Example #6
Kinetic Scrolling
Kinetic Scrolling




                    63
State Machine for Scrolling

                                              Mouse move
 Mouse press             Pressed

  ...
Example #7
Parallax Sliding
Parallax Sliding




                   66
Slow-moving Background




         1               5
             2       4
                 3
                          ...
Example #8
Web Technologies
Web Browser

• QtWebKit:
  – Standard compliant, fast rendering engine
  – Used in Apple Safari, Google Chrome, …
  – S60 ...
Google Chat Client




                     70
We Cheat (Again)!

• Use QWebView from QtWebKit
• Show the “mobile” version
• Add custom login page




                  ...
Example #9
Unfinished Mini-game
Ray Casting




              73
Made Popular in (DOS) Wolfenstein 3-D

• A single ray is traced for every column
• Grid-based world, uniform height → fast...
Shading Trick




                75
Direct Screen Blit

          Don't bother “clearing” the widget!
setAttribute(Qt::WA_OpaquePaintEvent, true);




       ...
Bypass Alpha-Blending
       Since we handle each and every pixel, ...

QPainter p(this);
p.setCompositionMode(QPainter::C...
Storing Pixels in Image




                          78
Memory Access Optimization
        Minimize location (in memory) between
            two vertically separated pixels




 ...
Inner Loop Approach
      Use only simple, 12-bits fixed-point arithmetics

while (y1 >= 0 && y2 < bufh && p1 >= 0) {
    ...
Conclusion



      Mobile application development
              with Qt is FUN




                                      ...
That's all, folks...




        Thank You!


                       82
Bleeding-Edge




           labs.qt.nokia.com


           bit.ly/graphicsdojo




                                 83
Upcoming SlideShare
Loading in...5
×

Copy Your Favourite Nokia App with Qt

2,787

Published on

Weather service, maps and navigation, photo viewer, instant messaging, web browser, flick list or kinetic scrolling. You want all these with Qt? You get it!

Presentation by Ariya Hidayat held during Qt Developer Days 2009.

http://qt.nokia.com/developer/learning/elearning

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,787
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
77
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Copy Your Favourite Nokia App with Qt

  1. 1. Copy Your Favorite Nokia Apps 09/25/09 Ariya Hidayat
  2. 2. Agenda • Mobile platform challenges: – differences vs desktop – things to keep in mind • Examples which demonstrate: – Low-level painting – Graphics View – Network and web stack 2
  3. 3. Spread the Love All examples are available from... labs.qt.nokia.com bit.ly/graphicsdojo 3
  4. 4. Desktop vs Mobile Platforms • Hardware power • Screen size and resolutions • Input method • Network access 4
  5. 5. Nokia N95 • CPU: 332 MHz ARM11 • RAM: 128 MB • Screen: 240 x 320 (QVGA) • 9-Button keypad 5
  6. 6. Nokia E71 • CPU: 369 MHz ARM11 • RAM: 128 MB • Screen: 320x240 (QVGA) • Full QWERTY Keypad 6
  7. 7. Nokia 5800 XpressMusic • CPU: 434 MHz ARM11 • RAM: 128 MB • Screen: 360 x 640 (nHD) • Touch interface 7
  8. 8. Processing Power • ARM architecture – Different than x86 • Limited memory 8
  9. 9. Graphics Power • Lower resolution • Software rendering – hardware acceleration with OpenGL ES • Font metrics 9
  10. 10. Input Methods • Keypad, not keyboard – often not full QWERTY • No mouse – don't bother with mouse move event • Touch interface – single vs multitouch – stylus vs finger • Sensors: accelerometer, GPS, compass, ... 10
  11. 11. Network Access • Wireless LAN – sometimes not available • Other data access – slower data rate 11
  12. 12. Development Flow • Device emulator • Remote debugging • Performance test • Profiling tools 12
  13. 13. Example #1 Digital Clock
  14. 14. Digital (Vintage) Clock 14
  15. 15. Framed Digits plain digits with frame gradient 15
  16. 16. Gradient is Expensive, so... QLinearGradient gr(QPoint(0, 0), QPoint(0, height)); gr.setColorAt(0.00, QColor(128, 128, 128)); gr.setColorAt(0.49, QColor(64, 64, 64)); gr.setColorAt(0.51, QColor(128, 128, 128)); gr.setColorAt(1.00, QColor(16, 16, 16)); QPainter p; Cache to a p.begin(&pixmap); pixmap p.setFont(font); QPen pen; pen.setBrush(QBrush(gr)); p.setPen(pen); p.drawText(pixmap.rect(), Qt::AlignCenter, str); p.end(); 16
  17. 17. Sliding Effect translating both pixmaps 17
  18. 18. Sliding Effect: The Code QPainter p(this); int y = height() * currentFrame / 100; p.drawPixmap(0, y, m_lastPixmap); p.drawPixmap(0, y - height(), m_pixmap); p.end(); 18
  19. 19. Rotation transform.rotate(30, Qt::ZAxis) 19
  20. 20. Perspective Transformation transform.rotate (60, Qt::XAxis) transform.rotate(60, Qt::YAxis) 20
  21. 21. Rotating Effect rotating pixmaps 21
  22. 22. Rotating Effect: The Code QTransform transform; transform.translate(width() / 2, height() / 2); transform.rotate(angle, Qt::XAxis); QPainter p(this); p.setTransform(transform); p.drawPixmap(-width() / 2, -height() / 2, pixmap); p.end(); 22
  23. 23. Flipping Effect rotating and interleaving two pixmaps 23
  24. 24. A Trick with QBasicTimer QBasicTimer ticker; ticker.start(1000, this); void timerEvent(QTimerEvent*) { // update the clock } No need for QTimer, a slot, and periodic triggering of signal/slot ! 24
  25. 25. QTimeLine for Frame-based Animation QTimeLine animator; animator.setFrameRange(0, 100); animator.setDuration(600); animator.setCurveShape(QTimeLine::EaseInOutCurve); int progress = animator.currentFrame(); Linear EaseInOut deacceleration acceleration 25
  26. 26. Sacrifice Quality for Speed Beauty is in the eye of the beholder. 26
  27. 27. Aliasing during Animation QPainter p(this); p.setRenderHint(QPainter::SmoothPixmapTransform, false); p.setRenderHint(QPainter::Antialiasing, false); 27
  28. 28. Example #2 Weather Info
  29. 29. Weather Info 29
  30. 30. Screen Orientation requires different layout strategy 30
  31. 31. Lock the Orientation S60-specific, usually you do NOT need to do this! #include <eikenv.h> #include <eikappui.h> #include <aknenv.h> #include <aknappui.h> CAknAppUi* appUi = dynamic_cast<CAknAppUi*> (CEikonEnv::Static()->AppUi()); appUi->SetOrientationL (CAknAppUi::EAppUiOrientationPortrait); 31
  32. 32. Animation with Graphics View item movement & opacity 32
  33. 33. Using Web Service <weather> <forecast_information> <city data="Oslo, Oslo"/> <postal_code data="Oslo"/> <latitude_e6 data=""/><longitude_e6 data=""/> <forecast_date data="2009-09-15"/> <current_date_time data="2009-09-15 13:40:00 +0000"/> <unit_system data="US"/> </forecast_information> <current_conditions> <condition data="Clear"/> <temp_f data="61"/><temp_c data="16"/> <humidity data="Humidity: 55%"/> <icon data="/ig/images/weather/sunny.gif"/> <wind_condition data="Wind: S at 12 mph"/> </current_conditions> <forecast_conditions> ... 33
  34. 34. Create the Network Request http://www.google.com/ig/api?hl=en&weather=oslo QUrl url("http://www.google.com/ig/api"); url.addEncodedQueryItem("hl", "en"); url.addEncodedQueryItem("weather", QUrl::toPercentEncoding(location)); QNetworkAccessManager *manager; manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(handleNetworkData(QNetworkReply*))); manager->get(QNetworkRequest(url)); 34
  35. 35. Handle the Network Reply http://www.google.com/ig/api?hl=en&weather=oslo QUrl url = networkReply->url(); data = QString::fromUtf8(networkReply->readAll()); networkReply->deleteLater(); networkReply->manager()->deleteLater(); 35
  36. 36. XML Stream Reader for Parsing QXmlStreamReader xml(data); while (!xml.atEnd()) { xml.readNext(); if (xml.tokenType() == QXmlStreamReader::StartElement) if (xml.name() == "city") city = xml.attributes().value("data").toString() } faster and requires less memory than using QDom! 36
  37. 37. Scalable Icons with SVG bitmap vs vector 37
  38. 38. Optimize Your SVG <g> <ellipse cx="10" cy="10" rx=2" ry="2"/> </g> <ellipse cx="10" cy="10" rx=2" ry="2"/> Because one element in a group often does not make sense! 38
  39. 39. SVG Loading Time Comparison Use tools like: codedread.com/scour svgmin.googlecode.com 39
  40. 40. Example #3 Flight Tracking
  41. 41. Flight Tracking 41
  42. 42. No Web Service? Use “mobile” version of the web site. 42
  43. 43. Web Scraping • Grab the HTML contents • Scrap it – remove unnecessary clutters – parse and extract the interesting bits • Legal aspect – some sites explicitly prohibit the use other than in a web browser 43
  44. 44. Parsing HTML with XML Stream Reader • HTML != XML • Potentially provoke the parser (→ errors) – Solution: “scrub it”, i.e. clean up the raw HTML // remove all inline frames while (true) { i = data.indexOf("<iframe"); if (i < 0) break; data.remove(i, data.indexOf("</iframe>") - i + 8); } 44
  45. 45. The Usual Tricks • Use network request and reply • Contents – Construct the request – Get the HTML data – Clean it up and then parse it • Flight map – Construct the request – Get data and feed it to a QPixmap – Display the pixmap, e.g. with QLabel 45
  46. 46. Beware of Different Font Metrics 46
  47. 47. Example #4 Magnifying Glass
  48. 48. Image Zoom 48
  49. 49. Shadow with Radial Gradient magnifier 49
  50. 50. Shadow with Radial Gradient Prepare the gradient brush QRadialGradient g; g.setCenter(radius, radius); g.setFocalPoint(radius, radius); g.setRadius(radius); g.setColorAt(1.0, QColor(255, 255, 255, 0)); g.setColorAt(0.5, QColor(128, 128, 128, 255)); Draw the shadow p.setCompositionMode (QPainter::CompositionMode_Source); p.setBrush(g); p.drawRect(maskPixmap.rect()); Carve the “hole” p.setBrush(QColor(Qt::transparent)); p.drawEllipse(g.center(), radius-15, radius-15); 50
  51. 51. Panning with Mouse/Finger/Stylus Record the tap position void mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::LeftButton) return; pressed = true; pressPos = dragPos = event->pos(); } Pan the map based on the movement void mouseMoveEvent(QMouseEvent *event) { if (!event->buttons()) return; QPoint delta = event->pos() - pressPos; pressPos = event->pos(); pan(delta); } 51
  52. 52. Avoid Accidental Panning panning is not started past the threshold 52
  53. 53. Turbo Downscaling (We're Cheating!) With filtering Fast, no filtering Up to 200x faster, see http://bit.ly/cheatscale for details! 53
  54. 54. Example #5 Maps
  55. 55. Maps (with OpenStreetMap) 55
  56. 56. OpenStreetMap vs [Google,Yahoo]Maps • Free content – Creative Commons Attribution-ShareAlike 2.0 • API does not require the license key • Available in – rendered images – vector data More info at www.openstreetmap.org ! 56
  57. 57. Getting the Rendered Tiles • Each tile is 256 x 256 pixels • Zoom level of 0 → the whole world • Zoom level of 17 → most detailed QPointF tileForCoordinate(qreal lat, qreal lng, int zoom) { qreal zn = static_cast<qreal>(1 << zoom); qreal tx = (lng + 180.0) / 360.0; qreal ty = (1.0 - log(tan(lat * M_PI / 180.0) + 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0; return QPointF(tx * zn, ty * zn); } 57
  58. 58. Rendering and Caching Strategy cached tiles application window 58
  59. 59. Avoid Accidental Panning panning is not started past the threshold 59
  60. 60. Night Mode 60
  61. 61. Night Mode: The Code Color channel inversion QPainter p(this); p.setCompositionMode (QPainter::CompositionMode_Difference); p.fillRect(event->rect(), Qt::white); p.end(); red = 255 – red green = 255 – green blue = 255 - blue 61
  62. 62. Example #6 Kinetic Scrolling
  63. 63. Kinetic Scrolling 63
  64. 64. State Machine for Scrolling Mouse move Mouse press Pressed Manual Scroll Mouse release Steady Mouse release Mouse move Auto Scroll Mouse release Mouse press Stop Timer tick 64
  65. 65. Example #7 Parallax Sliding
  66. 66. Parallax Sliding 66
  67. 67. Slow-moving Background 1 5 2 4 3 67
  68. 68. Example #8 Web Technologies
  69. 69. Web Browser • QtWebKit: – Standard compliant, fast rendering engine – Used in Apple Safari, Google Chrome, … – S60 Browser, Apple iPhone, Google Android, Palm WebOS, … • Use QWebView and you are done! • Add flick support for kinetic scrolling 69
  70. 70. Google Chat Client 70
  71. 71. We Cheat (Again)! • Use QWebView from QtWebKit • Show the “mobile” version • Add custom login page 71
  72. 72. Example #9 Unfinished Mini-game
  73. 73. Ray Casting 73
  74. 74. Made Popular in (DOS) Wolfenstein 3-D • A single ray is traced for every column • Grid-based world, uniform height → fast 74
  75. 75. Shading Trick 75
  76. 76. Direct Screen Blit Don't bother “clearing” the widget! setAttribute(Qt::WA_OpaquePaintEvent, true); Faster direct screen access using CDirectScreenBitmap or Anti-Tearing API 76
  77. 77. Bypass Alpha-Blending Since we handle each and every pixel, ... QPainter p(this); p.setCompositionMode(QPainter::Composition_Source) p.drawImage(0, 0, buffer); 77
  78. 78. Storing Pixels in Image 78
  79. 79. Memory Access Optimization Minimize location (in memory) between two vertically separated pixels Jump several Jump few hundreds bytes bytes only 79
  80. 80. Inner Loop Approach Use only simple, 12-bits fixed-point arithmetics while (y1 >= 0 && y2 < bufh && p1 >= 0) { *pixel1 = tex[p1 >> 12]; *pixel2 = tex[p2 >> 12]; p1 -= dy; p2 += dy; --y1; ++y2; pixel1 -= stride; pixel2 += stride; } 80
  81. 81. Conclusion Mobile application development with Qt is FUN 81
  82. 82. That's all, folks... Thank You! 82
  83. 83. Bleeding-Edge labs.qt.nokia.com bit.ly/graphicsdojo 83
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×