[haiku-commits] haiku: hrev43928 - src/servers/app/drawing/html5

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 1 Apr 2012 11:06:38 +0200 (CEST)

hrev43928 adds 1 changeset to branch 'master'
old head: d1abffcaa267478916c5922ec1712cf27509bcec
new head: 8d33dc2971c49b5fe2eb9401e77406199d524d8f

----------------------------------------------------------------------------

8d33dc2: An html5 <canvas> based drawing engine
  
  This implements an html5 rendering engine.
  Inspired by the Broadway GDK backend for Gnome.
  Work in progress. For now it just connects and dumps debug output.

                                          [ François Revol <revol@xxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev43928
Commit:      8d33dc2971c49b5fe2eb9401e77406199d524d8f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8d33dc2
Author:      François Revol <revol@xxxxxxx>
Date:        Sun Apr  1 09:04:41 2012 UTC

----------------------------------------------------------------------------

28 files changed, 4477 insertions(+), 2 deletions(-)
src/servers/app/Jamfile                            |    3 +-
src/servers/app/ScreenManager.cpp                  |   11 +-
src/servers/app/drawing/Jamfile                    |    1 +
.../app/drawing/html5/CanvasEventStream.cpp        |  218 +++
src/servers/app/drawing/html5/CanvasEventStream.h  |   45 +
src/servers/app/drawing/html5/CanvasMessage.cpp    |  500 +++++++
src/servers/app/drawing/html5/CanvasMessage.h      |  371 +++++
.../app/drawing/html5/HTML5DrawingEngine.cpp       | 1117 ++++++++++++++++
src/servers/app/drawing/html5/HTML5DrawingEngine.h |  180 +++
src/servers/app/drawing/html5/HTML5HWInterface.cpp |  612 +++++++++
src/servers/app/drawing/html5/HTML5HWInterface.h   |  131 ++
src/servers/app/drawing/html5/Jamfile              |   32 +
src/servers/app/drawing/html5/NetSender.cpp        |   75 +
src/servers/app/drawing/html5/NetSender.h          |   34 +
.../app/drawing/html5/StreamingRingBuffer.cpp      |  176 +++
.../app/drawing/html5/StreamingRingBuffer.h        |   47 +
src/servers/app/drawing/html5/WebHandler.cpp       |   85 ++
src/servers/app/drawing/html5/WebHandler.h         |   58 +
src/servers/app/drawing/html5/WebServer.cpp        |  155 +++
src/servers/app/drawing/html5/WebServer.h          |   47 +
src/servers/app/drawing/html5/WebWorker.cpp        |  152 +++
src/servers/app/drawing/html5/WebWorker.h          |   39 +
src/servers/app/drawing/html5/base64.cpp           |  115 ++
src/servers/app/drawing/html5/base64.h             |   15 +
src/servers/app/drawing/html5/desktop.html         |   29 +
src/servers/app/drawing/html5/desktop.html.h       |   30 +
src/servers/app/drawing/html5/haiku.js             |  100 ++
src/servers/app/drawing/html5/haiku.js.h           |  101 ++

----------------------------------------------------------------------------

diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile
index f31ebbb..0b917f3 100644
--- a/src/servers/app/Jamfile
+++ b/src/servers/app/Jamfile
@@ -84,7 +84,8 @@ Server app_server :
        # libraries
        :
        libtranslation.so libbe.so libbnetapi.so
-       libasdrawing.a libasremote.a libpainter.a libagg.a $(HAIKU_FREETYPE_LIB)
+       libasdrawing.a libasremote.a libashtml5.a 
+       libpainter.a libagg.a $(HAIKU_FREETYPE_LIB)
        libstackandtile.a liblinprog.a libtextencoding.so libshared.a
        $(TARGET_LIBSTDC++)
 
diff --git a/src/servers/app/ScreenManager.cpp 
b/src/servers/app/ScreenManager.cpp
index 308939a..064bb79 100644
--- a/src/servers/app/ScreenManager.cpp
+++ b/src/servers/app/ScreenManager.cpp
@@ -15,6 +15,7 @@
 #include "ServerConfig.h"
 
 #include "remote/RemoteHWInterface.h"
+#include "html5/HTML5HWInterface.h"
 
 #include <Autolock.h>
 #include <Entry.h>
@@ -109,7 +110,15 @@ ScreenManager::AcquireScreens(ScreenOwner* owner, int32* 
wishList,
                // there's a specific target screen we want to initialize
                // TODO: right now we only support remote screens, but we could
                // also target specific accelerants to support other graphics 
cards
-               RemoteHWInterface* interface = new(nothrow) 
RemoteHWInterface(target);
+               HWInterface* interface;
+               /*
+               if (strncmp(target, "vnc:", 4) == 0)
+                       interface = new(nothrow) VNCHWInterface(target);
+               else*/
+               if (strncmp(target, "html5:", 6) == 0)
+                       interface = new(nothrow) HTML5HWInterface(target);
+               else
+                       interface = new(nothrow) RemoteHWInterface(target);
                if (interface != NULL) {
                        screen_item* item = _AddHWInterface(interface);
                        if (item != NULL && list.AddItem(item->screen)) {
diff --git a/src/servers/app/drawing/Jamfile b/src/servers/app/drawing/Jamfile
index ee5c465..f84cc4f 100644
--- a/src/servers/app/drawing/Jamfile
+++ b/src/servers/app/drawing/Jamfile
@@ -30,3 +30,4 @@ StaticLibrary libasdrawing.a :
 
 SubInclude HAIKU_TOP src servers app drawing Painter ;
 SubInclude HAIKU_TOP src servers app drawing remote ;
+SubInclude HAIKU_TOP src servers app drawing html5 ;
diff --git a/src/servers/app/drawing/html5/CanvasEventStream.cpp 
b/src/servers/app/drawing/html5/CanvasEventStream.cpp
new file mode 100644
index 0000000..ec9cc99
--- /dev/null
+++ b/src/servers/app/drawing/html5/CanvasEventStream.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ */
+
+#include "CanvasEventStream.h"
+
+#include "CanvasMessage.h"
+#include "StreamingRingBuffer.h"
+
+#include <Autolock.h>
+
+#include <new>
+
+
+CanvasEventStream::CanvasEventStream()
+       :
+       fEventList(10, true),
+       fEventListLocker("canvas event list"),
+       fEventNotification(-1),
+       fWaitingOnEvent(false),
+       fLatestMouseMovedEvent(NULL),
+       fMousePosition(0, 0),
+       fMouseButtons(0),
+       fModifiers(0)
+{
+       fEventNotification = create_sem(0, "canvas event notification");
+}
+
+
+CanvasEventStream::~CanvasEventStream()
+{
+       delete_sem(fEventNotification);
+}
+
+
+void
+CanvasEventStream::UpdateScreenBounds(BRect bounds)
+{
+}
+
+
+bool
+CanvasEventStream::GetNextEvent(BMessage** _event)
+{
+       BAutolock lock(fEventListLocker);
+       while (fEventList.CountItems() == 0) {
+               fWaitingOnEvent = true;
+               lock.Unlock();
+
+               status_t result;
+               do {
+                       result = acquire_sem(fEventNotification);
+               } while (result == B_INTERRUPTED);
+
+               lock.Lock();
+               if (!lock.IsLocked())
+                       return false;
+       }
+
+       *_event = fEventList.RemoveItemAt(0);
+       return true;
+}
+
+
+status_t
+CanvasEventStream::InsertEvent(BMessage* event)
+{
+       BAutolock lock(fEventListLocker);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       if (!fEventList.AddItem(event))
+               return B_ERROR;
+
+       if (event->what == B_MOUSE_MOVED)
+               fLatestMouseMovedEvent = event;
+
+       return B_OK;
+}
+
+
+BMessage*
+CanvasEventStream::PeekLatestMouseMoved()
+{
+       return fLatestMouseMovedEvent;
+}
+
+
+bool
+CanvasEventStream::EventReceived(CanvasMessage& message)
+{
+       uint16 code = message.Code();
+       uint32 what = 0;
+       switch (code) {
+               case RP_MOUSE_MOVED:
+                       what = B_MOUSE_MOVED;
+                       break;
+               case RP_MOUSE_DOWN:
+                       what = B_MOUSE_DOWN;
+                       break;
+               case RP_MOUSE_UP:
+                       what = B_MOUSE_UP;
+                       break;
+               case RP_MOUSE_WHEEL_CHANGED:
+                       what = B_MOUSE_WHEEL_CHANGED;
+                       break;
+               case RP_KEY_DOWN:
+                       what = B_KEY_DOWN;
+                       break;
+               case RP_KEY_UP:
+                       what = B_KEY_UP;
+                       break;
+               case RP_MODIFIERS_CHANGED:
+                       what = B_MODIFIERS_CHANGED;
+                       break;
+       }
+
+       if (what == 0)
+               return false;
+
+       BMessage* event = new BMessage(what);
+       if (event == NULL)
+               return false;
+
+       event->AddInt64("when", system_time());
+
+       switch (code) {
+               case RP_MOUSE_MOVED:
+               case RP_MOUSE_DOWN:
+               case RP_MOUSE_UP:
+               {
+                       message.Read(fMousePosition);
+                       if (code != RP_MOUSE_MOVED)
+                               message.Read(fMouseButtons);
+
+                       event->AddPoint("where", fMousePosition);
+                       event->AddInt32("buttons", fMouseButtons);
+                       event->AddInt32("modifiers", fModifiers);
+
+                       if (code == RP_MOUSE_DOWN) {
+                               int32 clicks;
+                               if (message.Read(clicks) == B_OK)
+                                       event->AddInt32("clicks", clicks);
+                       }
+
+                       if (code == RP_MOUSE_MOVED)
+                               fLatestMouseMovedEvent = event;
+                       break;
+               }
+
+               case RP_MOUSE_WHEEL_CHANGED:
+               {
+                       float xDelta, yDelta;
+                       message.Read(xDelta);
+                       message.Read(yDelta);
+                       event->AddFloat("be:wheel_delta_x", xDelta);
+                       event->AddFloat("be:wheel_delta_y", yDelta);
+                       break;
+               }
+
+               case RP_KEY_DOWN:
+               case RP_KEY_UP:
+               {
+                       int32 numBytes;
+                       if (message.Read(numBytes) != B_OK)
+                               break;
+
+                       char* bytes = (char*)malloc(numBytes + 1);
+                       if (bytes == NULL)
+                               break;
+
+                       if (message.ReadList(bytes, numBytes) != B_OK) {
+                               free(bytes);
+                               break;
+                       }
+
+                       for (int32 i = 0; i < numBytes; i++)
+                               event->AddInt8("byte", (int8)bytes[i]);
+
+                       bytes[numBytes] = 0;
+                       event->AddData("bytes", B_STRING_TYPE, bytes, numBytes 
+ 1, false);
+                       event->AddInt32("modifiers", fModifiers);
+
+                       int32 rawChar;
+                       if (message.Read(rawChar) == B_OK)
+                               event->AddInt32("raw_char", rawChar);
+
+                       int32 key;
+                       if (message.Read(key) == B_OK)
+                               event->AddInt32("key", key);
+
+                       free(bytes);
+                       break;
+               }
+
+               case RP_MODIFIERS_CHANGED:
+               {
+                       event->AddInt32("be:old_modifiers", fModifiers);
+                       message.Read(fModifiers);
+                       event->AddInt32("modifiers", fModifiers);
+                       break;
+               }
+       }
+
+       BAutolock lock(fEventListLocker);
+       fEventList.AddItem(event);
+       if (fWaitingOnEvent) {
+               fWaitingOnEvent = false;
+               lock.Unlock();
+               release_sem(fEventNotification);
+       }
+
+       return true;
+}
diff --git a/src/servers/app/drawing/html5/CanvasEventStream.h 
b/src/servers/app/drawing/html5/CanvasEventStream.h
new file mode 100644
index 0000000..68d0050
--- /dev/null
+++ b/src/servers/app/drawing/html5/CanvasEventStream.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ */
+#ifndef CANVAS_EVENT_STREAM_H
+#define CANVAS_EVENT_STREAM_H
+
+#include "EventStream.h"
+
+#include <Locker.h>
+#include <ObjectList.h>
+
+class CanvasMessage;
+
+class CanvasEventStream : public EventStream {
+public:
+                                                               
CanvasEventStream();
+virtual                                                        
~CanvasEventStream();
+
+virtual        bool                                    IsValid() { return 
true; }
+virtual        void                                    SendQuit() {}
+
+virtual        void                                    
UpdateScreenBounds(BRect bounds);
+virtual        bool                                    GetNextEvent(BMessage** 
_event);
+virtual        status_t                                InsertEvent(BMessage* 
event);
+virtual        BMessage*                               PeekLatestMouseMoved();
+
+               bool                                    
EventReceived(CanvasMessage& message);
+
+private:
+               BObjectList<BMessage>   fEventList;
+               BLocker                                 fEventListLocker;
+               sem_id                                  fEventNotification;
+               bool                                    fWaitingOnEvent;
+               BMessage*                               fLatestMouseMovedEvent;
+
+               BPoint                                  fMousePosition;
+               uint32                                  fMouseButtons;
+               uint32                                  fModifiers;
+};
+
+#endif // CANVAS_EVENT_STREAM_H
diff --git a/src/servers/app/drawing/html5/CanvasMessage.cpp 
b/src/servers/app/drawing/html5/CanvasMessage.cpp
new file mode 100644
index 0000000..367d0d4
--- /dev/null
+++ b/src/servers/app/drawing/html5/CanvasMessage.cpp
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ *             François Revol <revol@xxxxxxx>
+ */
+
+#include "CanvasMessage.h"
+
+#include "DrawState.h"
+#include "ServerBitmap.h"
+#include "ServerCursor.h"
+
+#include <Bitmap.h>
+#include <Font.h>
+#include <View.h>
+
+#include <Gradient.h>
+#include <GradientLinear.h>
+#include <GradientRadial.h>
+#include <GradientRadialFocus.h>
+#include <GradientDiamond.h>
+#include <GradientConic.h>
+
+#include <new>
+
+
+status_t
+CanvasMessage::NextMessage(uint16& code)
+{
+       if (fDataLeft > 0) {
+               // discard remainder of message
+               int32 readSize = fSource->Read(NULL, fDataLeft);
+               if (readSize < 0)
+                       return readSize;
+       }
+
+       static const uint32 kHeaderSize = sizeof(uint16) + sizeof(uint32);
+
+       fDataLeft = kHeaderSize;
+       Read(code);
+       uint32 dataLeft;
+       status_t result = Read(dataLeft);
+       if (result != B_OK)
+               return result;
+
+       if (dataLeft < kHeaderSize)
+               return B_ERROR;
+
+       fDataLeft = dataLeft - kHeaderSize;
+       fCode = code;
+       return B_OK;
+}
+
+
+void
+CanvasMessage::Cancel()
+{
+       fAvailable += fWriteIndex;
+       fWriteIndex = 0;
+}
+
+
+void
+CanvasMessage::AddBitmap(const ServerBitmap& bitmap, bool minimal)
+{
+       //TODO:send PNG / as data: or as http: url
+       Add(bitmap.Width());
+       Add(bitmap.Height());
+       Add(bitmap.BytesPerRow());
+
+       if (!minimal) {
+               Add(bitmap.ColorSpace());
+               Add(bitmap.Flags());
+       }
+
+       uint32 bitsLength = bitmap.BitsLength();
+       Add(bitsLength);
+
+       if (!_MakeSpace(bitsLength))
+               return;
+
+       memcpy(fBuffer + fWriteIndex, bitmap.Bits(), bitsLength);
+       fWriteIndex += bitsLength;
+       fAvailable -= bitsLength;
+}
+
+
+void
+CanvasMessage::AddFont(const ServerFont& font)
+{
+       //TODO:Use TTF/WOFF URL
+       Add(font.Direction());
+       Add((uint8)font.Encoding());
+       Add(font.Flags());
+       Add((uint8)font.Spacing());
+       Add(font.Shear());
+       Add(font.Rotation());
+       Add(font.FalseBoldWidth());
+       Add(font.Size());
+       Add(font.Face());
+       Add(font.GetFamilyAndStyle());
+}
+
+
+void
+CanvasMessage::AddDrawState(const DrawState& drawState)
+{
+       Add(drawState.PenSize());
+       Add(drawState.SubPixelPrecise());
+       Add(drawState.GetDrawingMode());
+       Add(drawState.AlphaSrcMode());
+       Add(drawState.AlphaFncMode());
+       AddPattern(drawState.GetPattern());
+       Add(drawState.LineCapMode());
+       Add(drawState.LineJoinMode());
+       Add(drawState.MiterLimit());
+       Add(drawState.HighColor());
+       Add(drawState.LowColor());
+}
+
+
+void
+CanvasMessage::AddArrayLine(const ViewLineArrayInfo& line)
+{
+       Add(line.startPoint);
+       Add(line.endPoint);
+       Add(line.color);
+}
+
+
+void
+CanvasMessage::AddCursor(const ServerCursor& cursor)
+{
+       //TODO:send as .cur data:
+       Add(cursor.GetHotSpot());
+       AddBitmap(cursor);
+}
+
+
+void
+CanvasMessage::AddPattern(const Pattern& pattern)
+{
+       Add(pattern.GetPattern());
+}
+
+
+void
+CanvasMessage::AddGradient(const BGradient& gradient)
+{
+       Add(gradient.GetType());
+
+       switch (gradient.GetType()) {
+               case BGradient::TYPE_NONE:
+                       break;
+
+               case BGradient::TYPE_LINEAR:
+               {
+                       const BGradientLinear* linear
+                               = dynamic_cast<const BGradientLinear 
*>(&gradient);
+                       if (linear == NULL)
+                               return;
+
+                       Add(linear->Start());
+                       Add(linear->End());
+                       break;
+               }
+
+               case BGradient::TYPE_RADIAL:
+               {
+                       const BGradientRadial* radial
+                               = dynamic_cast<const BGradientRadial 
*>(&gradient);
+                       if (radial == NULL)
+                               return;
+
+                       Add(radial->Center());
+                       Add(radial->Radius());
+                       break;
+               }
+
+               case BGradient::TYPE_RADIAL_FOCUS:
+               {
+                       const BGradientRadialFocus* radialFocus
+                               = dynamic_cast<const BGradientRadialFocus 
*>(&gradient);
+                       if (radialFocus == NULL)
+                               return;
+
+                       Add(radialFocus->Center());
+                       Add(radialFocus->Focal());
+                       Add(radialFocus->Radius());
+                       break;
+               }
+
+               case BGradient::TYPE_DIAMOND:
+               {
+                       const BGradientDiamond* diamond
+                               = dynamic_cast<const BGradientDiamond 
*>(&gradient);
+                       if (diamond == NULL)
+                               return;
+
+                       Add(diamond->Center());
+                       break;
+               }
+
+               case BGradient::TYPE_CONIC:
+               {
+                       const BGradientConic* conic
+                               = dynamic_cast<const BGradientConic 
*>(&gradient);
+                       if (conic == NULL)
+                               return;
+
+                       Add(conic->Center());
+                       Add(conic->Angle());
+                       break;
+               }
+       }
+
+       int32 stopCount = gradient.CountColorStops();
+       Add(stopCount);
+
+       for (int32 i = 0; i < stopCount; i++) {
+               BGradient::ColorStop* stop = gradient.ColorStopAt(i);
+               if (stop == NULL)
+                       return;
+
+               Add(stop->color);
+               Add(stop->offset);
+       }
+}
+
+
+status_t
+CanvasMessage::ReadString(char** _string, size_t& _length)
+{
+       uint32 length;
+       status_t result = Read(length);
+       if (result != B_OK)
+               return result;
+
+       if (length > fDataLeft)
+               return B_ERROR;
+
+       char *string = (char *)malloc(length + 1);
+       if (string == NULL)
+               return B_NO_MEMORY;
+
+       int32 readSize = fSource->Read(string, length);
+       if (readSize < 0) {
+               free(string);
+               return readSize;
+       }
+
+       if ((uint32)readSize != length) {
+               free(string);
+               return B_ERROR;
+       }
+
+       fDataLeft -= readSize;
+
+       string[length] = 0;
+       *_string = string;
+       _length = length;
+       return B_OK;
+}
+
+
+status_t
+CanvasMessage::ReadBitmap(BBitmap** _bitmap, bool minimal,
+       color_space colorSpace, uint32 flags)
+{
+       uint32 bitsLength;
+       int32 width, height, bytesPerRow;
+
+       Read(width);
+       Read(height);
+       Read(bytesPerRow);
+
+       if (!minimal) {
+               Read(colorSpace);
+               Read(flags);
+       }
+
+       Read(bitsLength);
+
+       if (bitsLength > fDataLeft)
+               return B_ERROR;
+
+#ifndef CLIENT_COMPILE
+       flags = B_BITMAP_NO_SERVER_LINK;
+#endif
+
+       BBitmap *bitmap = new(std::nothrow) BBitmap(
+               BRect(0, 0, width - 1, height - 1), flags, colorSpace, 
bytesPerRow);
+       if (bitmap == NULL)
+               return B_NO_MEMORY;
+
+       status_t result = bitmap->InitCheck();
+       if (result != B_OK) {
+               delete bitmap;
+               return result;
+       }
+
+       if (bitmap->BitsLength() < (int32)bitsLength) {
+               delete bitmap;
+               return B_ERROR;
+       }
+
+       int32 readSize = fSource->Read(bitmap->Bits(), bitsLength);
+       if ((uint32)readSize != bitsLength) {
+               delete bitmap;
+               return readSize < 0 ? readSize : B_ERROR;
+       }
+
+       fDataLeft -= readSize;
+       *_bitmap = bitmap;
+       return B_OK;
+}
+
+
+status_t
+CanvasMessage::ReadFontState(BFont& font)
+{
+       uint8 encoding, spacing;
+       uint16 face;
+       uint32 flags, familyAndStyle;
+       font_direction direction;
+       float falseBoldWidth, rotation, shear, size;
+
+       Read(direction);
+       Read(encoding);
+       Read(flags);
+       Read(spacing);
+       Read(shear);
+       Read(rotation);
+       Read(falseBoldWidth);
+       Read(size);
+       Read(face);
+       status_t result = Read(familyAndStyle);
+       if (result != B_OK)
+               return result;
+
+       font.SetFamilyAndStyle(familyAndStyle);
+       font.SetEncoding(encoding);
+       font.SetFlags(flags);
+       font.SetSpacing(spacing);
+       font.SetShear(shear);
+       font.SetRotation(rotation);
+       font.SetFalseBoldWidth(falseBoldWidth);
+       font.SetSize(size);
+       font.SetFace(face);
+       return B_OK;
+}
+
+
+status_t
+CanvasMessage::ReadViewState(BView& view, ::pattern& pattern)
+{
+       bool subPixelPrecise;
+       float penSize, miterLimit;
+       drawing_mode drawingMode;
+       source_alpha sourceAlpha;
+       alpha_function alphaFunction;
+       cap_mode capMode;
+       join_mode joinMode;
+       rgb_color highColor, lowColor;
+
+       Read(penSize);
+       Read(subPixelPrecise);
+       Read(drawingMode);
+       Read(sourceAlpha);
+       Read(alphaFunction);
+       Read(pattern);
+       Read(capMode);
+       Read(joinMode);
+       Read(miterLimit);
+       Read(highColor);
+       status_t result = Read(lowColor);
+       if (result != B_OK)
+               return result;
+
+       uint32 flags = view.Flags() & ~B_SUBPIXEL_PRECISE;
+       view.SetFlags(flags | (subPixelPrecise ? B_SUBPIXEL_PRECISE : 0));
+       view.SetPenSize(penSize);
+       view.SetDrawingMode(drawingMode);
+       view.SetBlendingMode(sourceAlpha, alphaFunction);
+       view.SetLineMode(capMode, joinMode, miterLimit);
+       view.SetHighColor(highColor);
+       view.SetLowColor(lowColor);
+       return B_OK;
+}
+
+
+status_t
+CanvasMessage::ReadGradient(BGradient** _gradient)
+{
+       BGradient::Type type;
+       Read(type);
+
+       BGradient *gradient = NULL;
+       switch (type) {
+               case BGradient::TYPE_NONE:
+                       break;
+
+               case BGradient::TYPE_LINEAR:
+               {
+                       BPoint start, end;
+
+                       Read(start);
+                       Read(end);
+
+                       gradient = new(std::nothrow) BGradientLinear(start, 
end);
+                       break;
+               }
+
+               case BGradient::TYPE_RADIAL:
+               {
+                       BPoint center;
+                       float radius;
+
+                       Read(center);
+                       Read(radius);
+
+                       gradient = new(std::nothrow) BGradientRadial(center, 
radius);
+                       break;
+               }
+
+               case BGradient::TYPE_RADIAL_FOCUS:
+               {
+                       BPoint center, focal;
+                       float radius;
+
+                       Read(center);
+                       Read(focal);
+                       Read(radius);
+
+                       gradient = new(std::nothrow) 
BGradientRadialFocus(center, radius,
+                               focal);
+                       break;
+               }
+
+               case BGradient::TYPE_DIAMOND:
+               {
+                       BPoint center;
+
+                       Read(center);
+
+                       gradient = new(std::nothrow) BGradientDiamond(center);
+                       break;
+               }
+
+               case BGradient::TYPE_CONIC:
+               {
+                       BPoint center;
+                       float angle;
+
+                       Read(center);
+                       Read(angle);
+
+                       gradient = new(std::nothrow) BGradientConic(center, 
angle);
+                       break;
+               }
+       }
+
+       if (gradient == NULL)
+               return B_NO_MEMORY;
+
+       int32 stopCount;
+       status_t result = Read(stopCount);
+       if (result != B_OK) {
+               delete gradient;
+               return result;
+       }
+
+       for (int32 i = 0; i < stopCount; i++) {
+               rgb_color color;
+               float offset;
+
+               Read(color);
+               result = Read(offset);
+               if (result != B_OK)
+                       return result;
+
+               gradient->AddColor(color, offset);
+       }
+
+       *_gradient = gradient;
+       return B_OK;
+}
+
+
+status_t
+CanvasMessage::ReadArrayLine(BPoint& startPoint, BPoint& endPoint,
+       rgb_color& color)
+{
+       Read(startPoint);
+       Read(endPoint);
+       return Read(color);
+}
diff --git a/src/servers/app/drawing/html5/CanvasMessage.h 
b/src/servers/app/drawing/html5/CanvasMessage.h
new file mode 100644
index 0000000..ca3648c
--- /dev/null
+++ b/src/servers/app/drawing/html5/CanvasMessage.h
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ *             François Revol <revol@xxxxxxx>
+ */
+#ifndef CANVAS_MESSAGE_H
+#define CANCAS_MESSAGE_H
+
+#include "PatternHandler.h"
+#include <ViewPrivate.h>
+
+#include "StreamingRingBuffer.h"
+#include "base64.h"
+
+#include <GraphicsDefs.h>
+#include <Region.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+class BBitmap;
+class BFont;
+class BGradient;
+class BView;
+class DrawState;
+class Pattern;
+class RemotePainter;
+class ServerBitmap;
+class ServerCursor;
+class ServerFont;
+class ViewLineArrayInfo;
+
+enum {
+       RP_INIT_CONNECTION = 1,
+       RP_UPDATE_DISPLAY_MODE,
+       RP_CLOSE_CONNECTION,
+
+       RP_CREATE_STATE = 20,
+       RP_DELETE_STATE,
+       RP_ENABLE_SYNC_DRAWING,
+       RP_DISABLE_SYNC_DRAWING,
+       RP_INVALIDATE_RECT,
+       RP_INVALIDATE_REGION,
+
+       RP_SET_OFFSETS = 40,
+       RP_SET_HIGH_COLOR,
+       RP_SET_LOW_COLOR,
+       RP_SET_PEN_SIZE,
+       RP_SET_STROKE_MODE,
+       RP_SET_BLENDING_MODE,
+       RP_SET_PATTERN,
+       RP_SET_DRAWING_MODE,
+       RP_SET_FONT,
+
+       RP_CONSTRAIN_CLIPPING_REGION = 60,
+       RP_COPY_RECT_NO_CLIPPING,
+       RP_INVERT_RECT,
+       RP_DRAW_BITMAP,
+       RP_DRAW_BITMAP_RECTS,
+
+       RP_STROKE_ARC = 80,
+       RP_STROKE_BEZIER,
+       RP_STROKE_ELLIPSE,
+       RP_STROKE_POLYGON,
+       RP_STROKE_RECT,
+       RP_STROKE_ROUND_RECT,
+       RP_STROKE_SHAPE,
+       RP_STROKE_TRIANGLE,
+       RP_STROKE_LINE,
+       RP_STROKE_LINE_ARRAY,
+
+       RP_FILL_ARC = 100,
+       RP_FILL_BEZIER,
+       RP_FILL_ELLIPSE,
+       RP_FILL_POLYGON,
+       RP_FILL_RECT,
+       RP_FILL_ROUND_RECT,
+       RP_FILL_SHAPE,
+       RP_FILL_TRIANGLE,
+       RP_FILL_REGION,
+
+       RP_FILL_ARC_GRADIENT = 120,
+       RP_FILL_BEZIER_GRADIENT,
+       RP_FILL_ELLIPSE_GRADIENT,
+       RP_FILL_POLYGON_GRADIENT,
+       RP_FILL_RECT_GRADIENT,
+       RP_FILL_ROUND_RECT_GRADIENT,
+       RP_FILL_SHAPE_GRADIENT,
+       RP_FILL_TRIANGLE_GRADIENT,
+       RP_FILL_REGION_GRADIENT,
+
+       RP_STROKE_POINT_COLOR = 140,
+       RP_STROKE_LINE_1PX_COLOR,
+       RP_STROKE_RECT_1PX_COLOR,
+
+       RP_FILL_RECT_COLOR = 160,
+       RP_FILL_REGION_COLOR_NO_CLIPPING,
+
+       RP_DRAW_STRING = 180,
+       RP_DRAW_STRING_WITH_OFFSETS,
+       RP_DRAW_STRING_RESULT,
+       RP_STRING_WIDTH,
+       RP_STRING_WIDTH_RESULT,
+       RP_READ_BITMAP,
+       RP_READ_BITMAP_RESULT,
+
+       RP_SET_CURSOR = 200,
+       RP_SET_CURSOR_VISIBLE,
+       RP_MOVE_CURSOR_TO,
+
+       RP_MOUSE_MOVED = 220,
+       RP_MOUSE_DOWN,
+       RP_MOUSE_UP,
+       RP_MOUSE_WHEEL_CHANGED,
+
+       RP_KEY_DOWN = 240,
+       RP_KEY_UP,
+       RP_UNMAPPED_KEY_DOWN,
+       RP_UNMAPPED_KEY_UP,
+       RP_MODIFIERS_CHANGED
+};
+
+
+class CanvasMessage {
+public:
+                                                               
CanvasMessage(StreamingRingBuffer* source,
+                                                                       
StreamingRingBuffer *target);
+                                                               
~CanvasMessage();
+
+               void                                    Start(uint16 code);
+               status_t                                Flush();
+               void                                    Cancel();
+
+               status_t                                NextMessage(uint16& 
code);
+               uint16                                  Code() { return fCode; }
+               uint32                                  DataLeft() { return 
fDataLeft; }
+
+               template<typename T>
+               void                                    Add(const T& value);
+
+               void                                    AddString(const char* 
string, size_t length);
+               void                                    AddRegion(const 
BRegion& region);
+               void                                    AddGradient(const 
BGradient& gradient);
+
+               void                                    AddBitmap(const 
ServerBitmap& bitmap,
+                                                                       bool 
minimal = false);
+               void                                    AddFont(const 
ServerFont& font);
+               void                                    AddPattern(const 
Pattern& pattern);
+               void                                    AddDrawState(const 
DrawState& drawState);
+               void                                    AddArrayLine(const 
ViewLineArrayInfo& line);
+               void                                    AddCursor(const 
ServerCursor& cursor);
+
+               template<typename T>
+               void                                    AddList(const T* array, 
int32 count);
+
+               template<typename T>
+               status_t                                Read(T& value);
+
+               status_t                                ReadRegion(BRegion& 
region);
+               status_t                                ReadFontState(BFont& 
font);
+                                                                       // sets 
font state
+               status_t                                ReadViewState(BView& 
view, ::pattern& pattern);
+                                                                       // sets 
viewstate and returns pattern
+
+               status_t                                ReadString(char** 
_string, size_t& length);
+               status_t                                ReadBitmap(BBitmap** 
_bitmap,
+                                                                       bool 
minimal = false,
+                                                                       
color_space colorSpace = B_RGB32,
+                                                                       uint32 
flags = 0);
+               status_t                                
ReadGradient(BGradient** _gradient);
+               status_t                                ReadArrayLine(BPoint& 
startPoint,
+                                                                       BPoint& 
endPoint, rgb_color& color);
+
+               template<typename T>
+               status_t                                ReadList(T* array, 
int32 count);
+
+private:
+               bool                                    _MakeSpace(size_t size);
+
+               StreamingRingBuffer*    fSource;
+               StreamingRingBuffer*    fTarget;
+
+               uint8*                                  fBuffer;
+               size_t                                  fAvailable;
+               size_t                                  fWriteIndex;
+               uint32                                  fDataLeft;
+               uint16                                  fCode;
+};
+
+
+inline
+CanvasMessage::CanvasMessage(StreamingRingBuffer* source,
+       StreamingRingBuffer* target)
+       :
+       fSource(source),
+       fTarget(target),
+       fBuffer(NULL),
+       fAvailable(0),
+       fWriteIndex(0),
+       fDataLeft(0)
+{
+}
+
+
+inline
+CanvasMessage::~CanvasMessage()
+{
+       if (fWriteIndex > 0)
+               Flush();
+       free(fBuffer);
+}
+
+
+inline void
+CanvasMessage::Start(uint16 code)
+{
+       if (fWriteIndex > 0)
+               Flush();
+
+       Add(code);
+
+//     uint32 sizeDummy;
+//     Add(sizeDummy);
+}
+
+
+inline status_t
+CanvasMessage::Flush()
+{
+       if (fWriteIndex == 0)
+               return B_NO_INIT;
+
+       // end by the multipart boundary
+       static const char boundary[] = "--x\r\n\r\n";
+       AddString(boundary, sizeof(boundary) - 1);
+
+       uint32 length = fWriteIndex;
+       fAvailable += fWriteIndex;
+       fWriteIndex = 0;
+
+//     memcpy(fBuffer + sizeof(uint16) * 2, &length, sizeof(uint32));
+       return fTarget->Write(fBuffer, length);
+}
+
+
+template<typename T>
+inline void
+CanvasMessage::Add(const T& value)
+{
+       ssize_t done;
+
+       if (!_MakeSpace(sizeof(T) * 2)) // 4/3 actually
+               return;
+
+       //memcpy(fBuffer + fWriteIndex, &value, sizeof(T));
+       done = encode_base64((char *)fBuffer + fWriteIndex, (const char 
*)(&value),
+               sizeof(T));
+       fWriteIndex += done;
+       fAvailable -= done;
+}
+
+
+inline void
+CanvasMessage::AddString(const char* string, size_t length)
+{
+       Add(length);
+       if (length > fAvailable && !_MakeSpace(length))
+               return;
+
+       memcpy(fBuffer + fWriteIndex, string, length);
+       fWriteIndex += length;
+       fAvailable -= length;
+}
+
+
+inline void
+CanvasMessage::AddRegion(const BRegion& region)
+{
+       int32 rectCount = region.CountRects();
+       Add(rectCount);
+
+       for (int32 i = 0; i < rectCount; i++)
+               Add(region.RectAt(i));
+}
+
+
+template<typename T>
+inline void
+CanvasMessage::AddList(const T* array, int32 count)
+{
+       for (int32 i = 0; i < count; i++)
+               Add(array[i]);
+}
+
+
+template<typename T>
+inline status_t
+CanvasMessage::Read(T& value)
+{
+       //TODO
+       if (fDataLeft < sizeof(T))
+               return B_ERROR;
+
+       int32 readSize = fSource->Read(&value, sizeof(T));
+       if (readSize < 0)
+               return readSize;
+
+       if (readSize != sizeof(T))
+               return B_ERROR;
+
+       fDataLeft -= sizeof(T);
+       return B_OK;
+}
+
+
+inline status_t
+CanvasMessage::ReadRegion(BRegion& region)
+{
+       region.MakeEmpty();
+
+       int32 rectCount;
+       Read(rectCount);
+
+       for (int32 i = 0; i < rectCount; i++) {
+               BRect rect;
+               status_t result = Read(rect);
+               if (result != B_OK)
+                       return result;
+
+               region.Include(rect);
+       }
+
+       return B_OK;
+}
+
+
+template<typename T>
+inline status_t
+CanvasMessage::ReadList(T* array, int32 count)
+{
+       for (int32 i = 0; i < count; i++) {
+               status_t result = Read(array[i]);
+               if (result != B_OK)
+                       return result;
+       }
+
+       return B_OK;
+}
+
+
+inline bool
+CanvasMessage::_MakeSpace(size_t size)
+{
+       if (fAvailable >= size)
+               return true;
+
+       size_t extraSize = size + 20;
+       uint8 *newBuffer = (uint8*)realloc(fBuffer, fWriteIndex + extraSize);
+       if (newBuffer == NULL)
+               return false;
+
+       fAvailable = extraSize;
+       fBuffer = newBuffer;
+       return true;
+}
+
+#endif // CANVAS_MESSAGE_H
diff --git a/src/servers/app/drawing/html5/HTML5DrawingEngine.cpp 
b/src/servers/app/drawing/html5/HTML5DrawingEngine.cpp
new file mode 100644
index 0000000..f1434a3
--- /dev/null
+++ b/src/servers/app/drawing/html5/HTML5DrawingEngine.cpp
@@ -0,0 +1,1117 @@
+/*
+ * Copyright 2009-2010, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ *             François Revol <revol@xxxxxxx>
+ */
+
+#include "HTML5DrawingEngine.h"
+#include "CanvasMessage.h"
+
+#include "BitmapDrawingEngine.h"
+#include "DrawState.h"
+
+#include <Bitmap.h>
+#include <utf8_functions.h>
+
+#include <new>
+
+
+HTML5DrawingEngine::HTML5DrawingEngine(HTML5HWInterface* interface)
+       :
+       DrawingEngine(interface),
+       fHWInterface(interface),
+       fToken((uint32)this), // TODO: need to redo that for 64 bit
+       fExtendWidth(0),
+       fCallbackAdded(false),
+       fResultNotify(-1),
+       fStringWidthResult(0.0f),
+       fReadBitmapResult(NULL),
+       fBitmapDrawingEngine(NULL)
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_CREATE_STATE);
+       message.Add(fToken);
+}
+
+
+HTML5DrawingEngine::~HTML5DrawingEngine()
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_DELETE_STATE);
+       message.Add(fToken);
+       message.Flush();
+
+       delete fBitmapDrawingEngine;
+
+       if (fCallbackAdded)
+               fHWInterface->RemoveCallback(fToken);
+       if (fResultNotify >= 0)
+               delete_sem(fResultNotify);
+}
+
+
+// #pragma mark -
+
+
+void
+HTML5DrawingEngine::FrameBufferChanged()
+{
+       // Not allowed
+}
+
+
+// #pragma mark -
+
+
+void
+HTML5DrawingEngine::SetCopyToFrontEnabled(bool enabled)
+{
+       DrawingEngine::SetCopyToFrontEnabled(enabled);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(enabled ? RP_ENABLE_SYNC_DRAWING : 
RP_DISABLE_SYNC_DRAWING);
+       message.Add(fToken);
+}
+
+
+// #pragma mark -
+
+
+//! the HTML5DrawingEngine needs to be locked!
+void
+HTML5DrawingEngine::ConstrainClippingRegion(const BRegion* region)
+{
+       if (fClippingRegion == *region)
+               return;
+
+       fClippingRegion = *region;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_CONSTRAIN_CLIPPING_REGION);
+       message.Add(fToken);
+       message.AddRegion(*region);
+}
+
+
+void
+HTML5DrawingEngine::SetDrawState(const DrawState* state, int32 xOffset,
+       int32 yOffset)
+{
+       SetPenSize(state->PenSize());
+       SetDrawingMode(state->GetDrawingMode());
+       SetBlendingMode(state->AlphaSrcMode(), state->AlphaFncMode());
+       SetPattern(state->GetPattern().GetPattern());
+       SetStrokeMode(state->LineCapMode(), state->LineJoinMode(),
+               state->MiterLimit());
+       SetHighColor(state->HighColor());
+       SetLowColor(state->LowColor());
+       SetFont(state->Font());
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_OFFSETS);
+       message.Add(fToken);
+       message.Add(xOffset);
+       message.Add(yOffset);
+}
+
+
+void
+HTML5DrawingEngine::SetHighColor(const rgb_color& color)
+{
+       if (fState.HighColor() == color)
+               return;
+
+       fState.SetHighColor(color);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_HIGH_COLOR);
+       message.Add(fToken);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::SetLowColor(const rgb_color& color)
+{
+       if (fState.LowColor() == color)
+               return;
+
+       fState.SetLowColor(color);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_LOW_COLOR);
+       message.Add(fToken);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::SetPenSize(float size)
+{
+       if (fState.PenSize() == size)
+               return;
+
+       fState.SetPenSize(size);
+       fExtendWidth = -(size / 2);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_PEN_SIZE);
+       message.Add(fToken);
+       message.Add(size);
+}
+
+
+void
+HTML5DrawingEngine::SetStrokeMode(cap_mode lineCap, join_mode joinMode,
+       float miterLimit)
+{
+       if (fState.LineCapMode() == lineCap && fState.LineJoinMode() == joinMode
+               && fState.MiterLimit() == miterLimit)
+               return;
+
+       fState.SetLineCapMode(lineCap);
+       fState.SetLineJoinMode(joinMode);
+       fState.SetMiterLimit(miterLimit);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_STROKE_MODE);
+       message.Add(fToken);
+       message.Add(lineCap);
+       message.Add(joinMode);
+       message.Add(miterLimit);
+}
+
+
+void
+HTML5DrawingEngine::SetBlendingMode(source_alpha sourceAlpha,
+       alpha_function alphaFunc)
+{
+       if (fState.AlphaSrcMode() == sourceAlpha
+               && fState.AlphaFncMode() == alphaFunc)
+               return;
+
+       fState.SetBlendingMode(sourceAlpha, alphaFunc);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_BLENDING_MODE);
+       message.Add(fToken);
+       message.Add(sourceAlpha);
+       message.Add(alphaFunc);
+}
+
+
+void
+HTML5DrawingEngine::SetPattern(const struct pattern& pattern)
+{
+       if (fState.GetPattern() == pattern)
+               return;
+
+       fState.SetPattern(pattern);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_PATTERN);
+       message.Add(fToken);
+       message.Add(pattern);
+}
+
+
+void
+HTML5DrawingEngine::SetDrawingMode(drawing_mode mode)
+{
+       if (fState.GetDrawingMode() == mode)
+               return;
+
+       fState.SetDrawingMode(mode);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_DRAWING_MODE);
+       message.Add(fToken);
+       message.Add(mode);
+}
+
+
+void
+HTML5DrawingEngine::SetDrawingMode(drawing_mode mode, drawing_mode& oldMode)
+{
+       oldMode = fState.GetDrawingMode();
+       SetDrawingMode(mode);
+}
+
+
+void
+HTML5DrawingEngine::SetFont(const ServerFont& font)
+{
+       if (fState.Font() == font)
+               return;
+
+       fState.SetFont(font);
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_SET_FONT);
+       message.Add(fToken);
+       message.AddFont(font);
+}
+
+
+void
+HTML5DrawingEngine::SetFont(const DrawState* state)
+{
+       SetFont(state->Font());
+}
+
+
+// #pragma mark -
+
+
+BRect
+HTML5DrawingEngine::CopyRect(BRect rect, int32 xOffset, int32 yOffset) const
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_COPY_RECT_NO_CLIPPING);
+       message.Add(xOffset);
+       message.Add(yOffset);
+       message.Add(rect);
+       return rect.OffsetBySelf(xOffset, yOffset);
+}
+
+
+void
+HTML5DrawingEngine::InvertRect(BRect rect)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_INVERT_RECT);
+       message.Add(fToken);
+       message.Add(rect);
+}
+
+
+void
+HTML5DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& _bitmapRect,
+       const BRect& _viewRect, uint32 options)
+{
+       BRect bitmapRect = _bitmapRect;
+       BRect viewRect = _viewRect;
+       double xScale = (bitmapRect.Width() + 1) / (viewRect.Width() + 1);
+       double yScale = (bitmapRect.Height() + 1) / (viewRect.Height() + 1);
+
+       // constrain rect to passed bitmap bounds
+       // and transfer the changes to the viewRect with the right scale
+       BRect actualBitmapRect = bitmap->Bounds();
+       if (bitmapRect.left < actualBitmapRect.left) {
+               float diff = actualBitmapRect.left - bitmapRect.left;
+               viewRect.left += diff / xScale;
+               bitmapRect.left = actualBitmapRect.left;
+       }
+       if (bitmapRect.top < actualBitmapRect.top) {
+               float diff = actualBitmapRect.top - bitmapRect.top;
+               viewRect.top += diff / yScale;
+               bitmapRect.top = actualBitmapRect.top;
+       }
+       if (bitmapRect.right > actualBitmapRect.right) {
+               float diff = bitmapRect.right - actualBitmapRect.right;
+               viewRect.right -= diff / xScale;
+               bitmapRect.right = actualBitmapRect.right;
+       }
+       if (bitmapRect.bottom > actualBitmapRect.bottom) {
+               float diff = bitmapRect.bottom - actualBitmapRect.bottom;
+               viewRect.bottom -= diff / yScale;
+               bitmapRect.bottom = actualBitmapRect.bottom;
+       }
+
+       BRegion clippedRegion(viewRect);
+       clippedRegion.IntersectWith(&fClippingRegion);
+
+       int32 rectCount = clippedRegion.CountRects();
+       if (rectCount == 0)
+               return;
+
+       if (rectCount > 1 || (rectCount == 1 && clippedRegion.RectAt(0) != 
viewRect)
+               || viewRect.Width() < bitmapRect.Width()
+               || viewRect.Height() < bitmapRect.Height()) {
+               UtilityBitmap** bitmaps;
+               if (_ExtractBitmapRegions(*bitmap, options, bitmapRect, 
viewRect,
+                               xScale, yScale, clippedRegion, bitmaps) != 
B_OK) {
+                       return;
+               }
+
+               CanvasMessage message(NULL, fHWInterface->SendBuffer());
+               message.Start(RP_DRAW_BITMAP_RECTS);
+               message.Add(fToken);
+               message.Add(options);
+               message.Add(bitmap->ColorSpace());
+               message.Add(bitmap->Flags());
+               message.Add(rectCount);
+
+               for (int32 i = 0; i < rectCount; i++) {
+                       message.Add(clippedRegion.RectAt(i));
+                       message.AddBitmap(*bitmaps[i], true);
+                       delete bitmaps[i];
+               }
+
+               free(bitmaps);
+               return;
+       }
+
+       // TODO: we may want to cache/checksum bitmaps
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_DRAW_BITMAP);
+       message.Add(fToken);
+       message.Add(bitmapRect);
+       message.Add(viewRect);
+       message.Add(options);
+       message.AddBitmap(*bitmap);
+}
+
+
+void
+HTML5DrawingEngine::DrawArc(BRect rect, const float& angle, const float& span,
+       bool filled)
+{
+       BRect bounds = rect;
+       if (!filled)
+               bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_ARC : RP_STROKE_ARC);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(angle);
+       message.Add(span);
+}
+
+void
+HTML5DrawingEngine::FillArc(BRect rect, const float& angle, const float& span,
+       const BGradient& gradient)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_ARC_GRADIENT);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(angle);
+       message.Add(span);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::DrawBezier(BPoint* points, bool filled)
+{
+       BRect bounds = _BuildBounds(points, 4);
+       if (!filled)
+               bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_BEZIER : RP_STROKE_BEZIER);
+       message.Add(fToken);
+       message.AddList(points, 4);
+}
+
+
+void
+HTML5DrawingEngine::FillBezier(BPoint* points, const BGradient& gradient)
+{
+       BRect bounds = _BuildBounds(points, 4);
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_BEZIER_GRADIENT);
+       message.Add(fToken);
+       message.AddList(points, 4);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::DrawEllipse(BRect rect, bool filled)
+{
+       BRect bounds = rect;
+       if (!filled)
+               bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_ELLIPSE : RP_STROKE_ELLIPSE);
+       message.Add(fToken);
+       message.Add(rect);
+}
+
+
+void
+HTML5DrawingEngine::FillEllipse(BRect rect, const BGradient& gradient)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_ELLIPSE_GRADIENT);
+       message.Add(fToken);
+       message.Add(rect);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::DrawPolygon(BPoint* pointList, int32 numPoints,
+       BRect bounds, bool filled, bool closed)
+{
+       BRect clipBounds = bounds;
+       if (!filled)
+               clipBounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(clipBounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_POLYGON : RP_STROKE_POLYGON);
+       message.Add(fToken);
+       message.Add(bounds);
+       message.Add(closed);
+       message.Add(numPoints);
+       for (int32 i = 0; i < numPoints; i++)
+               message.Add(pointList[i]);
+}
+
+
+void
+HTML5DrawingEngine::FillPolygon(BPoint* pointList, int32 numPoints,
+       BRect bounds, const BGradient& gradient, bool closed)
+{
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_POLYGON_GRADIENT);
+       message.Add(fToken);
+       message.Add(bounds);
+       message.Add(closed);
+       message.Add(numPoints);
+       for (int32 i = 0; i < numPoints; i++)
+               message.Add(pointList[i]);
+       message.AddGradient(gradient);
+}
+
+
+// #pragma mark - rgb_color versions
+
+
+void
+HTML5DrawingEngine::StrokePoint(const BPoint& point, const rgb_color& color)
+{
+       BRect bounds(point, point);
+       bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_POINT_COLOR);
+       message.Add(fToken);
+       message.Add(point);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end,
+       const rgb_color& color)
+{
+       BPoint points[2] = { start, end };
+       BRect bounds = _BuildBounds(points, 2);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_LINE_1PX_COLOR);
+       message.Add(fToken);
+       message.AddList(points, 2);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::StrokeRect(BRect rect, const rgb_color &color)
+{
+       BRect bounds = rect;
+       bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_RECT_1PX_COLOR);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::FillRect(BRect rect, const rgb_color& color)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_RECT_COLOR);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(color);
+}
+
+
+void
+HTML5DrawingEngine::FillRegion(BRegion& region, const rgb_color& color)
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_REGION_COLOR_NO_CLIPPING);
+       message.AddRegion(region);
+       message.Add(color);
+}
+
+
+// #pragma mark - DrawState versions
+
+
+void
+HTML5DrawingEngine::StrokeRect(BRect rect)
+{
+       BRect bounds = rect;
+       bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_RECT);
+       message.Add(fToken);
+       message.Add(rect);
+}
+
+
+void
+HTML5DrawingEngine::FillRect(BRect rect)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_RECT);
+       message.Add(fToken);
+       message.Add(rect);
+}
+
+
+void
+HTML5DrawingEngine::FillRect(BRect rect, const BGradient& gradient)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_RECT_GRADIENT);
+       message.Add(fToken);
+       message.Add(rect);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::FillRegion(BRegion& region)
+{
+       BRegion clippedRegion = region;
+       clippedRegion.IntersectWith(&fClippingRegion);
+       if (clippedRegion.CountRects() == 0)
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_REGION);
+       message.Add(fToken);
+       message.AddRegion(clippedRegion.CountRects() < region.CountRects()
+               ? clippedRegion : region);
+}
+
+
+void
+HTML5DrawingEngine::FillRegion(BRegion& region, const BGradient& gradient)
+{
+       BRegion clippedRegion = region;
+       clippedRegion.IntersectWith(&fClippingRegion);
+       if (clippedRegion.CountRects() == 0)
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_REGION_GRADIENT);
+       message.Add(fToken);
+       message.AddRegion(clippedRegion.CountRects() < region.CountRects()
+               ? clippedRegion : region);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::DrawRoundRect(BRect rect, float xRadius, float yRadius,
+       bool filled)
+{
+       BRect bounds = rect;
+       if (!filled)
+               bounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_ROUND_RECT : RP_STROKE_ROUND_RECT);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(xRadius);
+       message.Add(yRadius);
+}
+
+
+void
+HTML5DrawingEngine::FillRoundRect(BRect rect, float xRadius, float yRadius,
+       const BGradient& gradient)
+{
+       if (!fClippingRegion.Intersects(rect))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_ROUND_RECT_GRADIENT);
+       message.Add(fToken);
+       message.Add(rect);
+       message.Add(xRadius);
+       message.Add(yRadius);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::DrawShape(const BRect& bounds, int32 opCount,
+       const uint32* opList, int32 pointCount, const BPoint* pointList,
+       bool filled, const BPoint& viewToScreenOffset, float viewScale)
+{
+       BRect clipBounds = bounds;
+       if (!filled)
+               clipBounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(clipBounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_SHAPE : RP_STROKE_SHAPE);
+       message.Add(fToken);
+       message.Add(bounds);
+       message.Add(opCount);
+       message.AddList(opList, opCount);
+       message.Add(pointCount);
+       message.AddList(pointList, pointCount);
+       message.Add(viewToScreenOffset);
+       message.Add(viewScale);
+}
+
+
+void
+HTML5DrawingEngine::FillShape(const BRect& bounds, int32 opCount,
+       const uint32* opList, int32 pointCount, const BPoint* pointList,
+       const BGradient& gradient, const BPoint& viewToScreenOffset,
+       float viewScale)
+{
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_SHAPE_GRADIENT);
+       message.Add(fToken);
+       message.Add(bounds);
+       message.Add(opCount);
+       message.AddList(opList, opCount);
+       message.Add(pointCount);
+       message.AddList(pointList, pointCount);
+       message.AddGradient(gradient);
+       message.Add(viewToScreenOffset);
+       message.Add(viewScale);
+}
+
+
+void
+HTML5DrawingEngine::DrawTriangle(BPoint* points, const BRect& bounds,
+       bool filled)
+{
+       BRect clipBounds = bounds;
+       if (!filled)
+               clipBounds.InsetBy(fExtendWidth, fExtendWidth);
+
+       if (!fClippingRegion.Intersects(clipBounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(filled ? RP_FILL_TRIANGLE : RP_STROKE_TRIANGLE);
+       message.Add(fToken);
+       message.AddList(points, 3);
+       message.Add(bounds);
+}
+
+
+void
+HTML5DrawingEngine::FillTriangle(BPoint* points, const BRect& bounds,
+       const BGradient& gradient)
+{
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_FILL_TRIANGLE_GRADIENT);
+       message.Add(fToken);
+       message.Add(points[0]);
+       message.Add(points[1]);
+       message.Add(points[2]);
+       message.Add(bounds);
+       message.AddGradient(gradient);
+}
+
+
+void
+HTML5DrawingEngine::StrokeLine(const BPoint &start, const BPoint &end)
+{
+       BPoint points[2] = { start, end };
+       BRect bounds = _BuildBounds(points, 2);
+
+       if (!fClippingRegion.Intersects(bounds))
+               return;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_LINE);
+       message.Add(fToken);
+       message.AddList(points, 2);
+}
+
+
+void
+HTML5DrawingEngine::StrokeLineArray(int32 numLines,
+       const ViewLineArrayInfo *lineData)
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+       message.Start(RP_STROKE_LINE_ARRAY);
+       message.Add(fToken);
+       message.Add(numLines);
+       for (int32 i = 0; i < numLines; i++)
+               message.AddArrayLine(lineData[i]);
+}
+
+
+// #pragma mark - string functions
+
+
+BPoint
+HTML5DrawingEngine::DrawString(const char* string, int32 length,
+       const BPoint& point, escapement_delta* delta)
+{
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+
+       message.Start(RP_DRAW_STRING);
+       message.Add(fToken);
+       message.Add(point);
+       message.AddString(string, length);
+       message.Add(delta != NULL);
+       if (delta != NULL)
+               message.AddList(delta, length);
+
+       status_t result = _AddCallback();
+       if (message.Flush() != B_OK)
+               return point;
+
+       if (result != B_OK)
+               return point;
+
+       do {
+               result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
+                       1 * 1000 * 1000);
+       } while (result == B_INTERRUPTED);
+
+       if (result != B_OK)
+               return point;
+
+       return fDrawStringResult;
+}
+
+
+BPoint
+HTML5DrawingEngine::DrawString(const char* string, int32 length,
+       const BPoint* offsets)
+{
+       // Guaranteed to have at least one point.
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+
+       message.Start(RP_DRAW_STRING_WITH_OFFSETS);
+       message.Add(fToken);
+       message.AddString(string, length);
+       message.AddList(offsets, UTF8CountChars(string, length));
+
+       status_t result = _AddCallback();
+       if (message.Flush() != B_OK)
+               return offsets[0];
+
+       if (result != B_OK)
+               return offsets[0];
+
+       do {
+               result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
+                       1 * 1000 * 1000);
+       } while (result == B_INTERRUPTED);
+
+       if (result != B_OK)
+               return offsets[0];
+
+       return fDrawStringResult;
+}
+
+
+float
+HTML5DrawingEngine::StringWidth(const char* string, int32 length,
+       escapement_delta* delta)
+{
+       // TODO: decide if really needed and use callback if so
+       return fState.Font().StringWidth(string, length, delta);
+}
+
+
+// #pragma mark -
+
+
+status_t
+HTML5DrawingEngine::ReadBitmap(ServerBitmap* bitmap, bool drawCursor,
+       BRect bounds)
+{
+       if (_AddCallback() != B_OK)
+               return B_UNSUPPORTED;
+
+       CanvasMessage message(NULL, fHWInterface->SendBuffer());
+
+       message.Start(RP_READ_BITMAP);
+       message.Add(fToken);
+       message.Add(bounds);
+       message.Add(drawCursor);
+       if (message.Flush() != B_OK)
+               return B_UNSUPPORTED;
+
+       status_t result;
+       do {
+               result = acquire_sem_etc(fResultNotify, 1, B_RELATIVE_TIMEOUT,
+                       100 * 1000 * 1000);
+       } while (result == B_INTERRUPTED);
+
+       if (result != B_OK)
+               return result;
+
+       BBitmap* read = fReadBitmapResult;
+       if (read == NULL)
+               return B_UNSUPPORTED;
+
+       result = bitmap->ImportBits(read->Bits(), read->BitsLength(),
+               read->BytesPerRow(), read->ColorSpace());
+       delete read;
+       return result;
+}
+
+
+// #pragma mark -
+
+
+status_t
+HTML5DrawingEngine::_AddCallback()
+{
+       if (fCallbackAdded)
+               return B_OK;
+
+       if (fResultNotify < 0)
+               fResultNotify = create_sem(0, "drawing engine result");
+       if (fResultNotify < 0)
+               return fResultNotify;
+
+       status_t result = fHWInterface->AddCallback(fToken, 
&_DrawingEngineResult,
+               this);
+
+       fCallbackAdded = result == B_OK;
+       return result;
+}
+
+
+bool
+HTML5DrawingEngine::_DrawingEngineResult(void* cookie, CanvasMessage& message)
+{
+       HTML5DrawingEngine* engine = (HTML5DrawingEngine*)cookie;
+
+       switch (message.Code()) {
+               case RP_DRAW_STRING_RESULT:
+                       if (message.Read(engine->fDrawStringResult) != B_OK)
+                               return false;
+                       break;
+
+               case RP_STRING_WIDTH_RESULT:
+                       if (message.Read(engine->fStringWidthResult) != B_OK)
+                               return false;
+                       break;
+
+               case RP_READ_BITMAP_RESULT:
+                       if (message.ReadBitmap(&engine->fReadBitmapResult) != 
B_OK)
+                               return false;
+                       break;
+
+               default:
+                       return false;
+       }
+
+       release_sem(engine->fResultNotify);
+       return true;
+}
+
+
+BRect
+HTML5DrawingEngine::_BuildBounds(BPoint* points, int32 pointCount)
+{
+       BRect bounds(1000000, 1000000, 0, 0);
+       for (int32 i = 0; i < pointCount; i++) {
+               bounds.left = min_c(bounds.left, points[i].x);
+               bounds.top = min_c(bounds.top, points[i].y);
+               bounds.right = max_c(bounds.right, points[i].x);
+               bounds.bottom = max_c(bounds.bottom, points[i].y);
+       }
+
+       return bounds;
+}
+
+
+status_t
+HTML5DrawingEngine::_ExtractBitmapRegions(ServerBitmap& bitmap, uint32 options,
+       const BRect& bitmapRect, const BRect& viewRect, double xScale,
+       double yScale, BRegion& region, UtilityBitmap**& bitmaps)
+{
+       int32 rectCount = region.CountRects();
+       bitmaps = (UtilityBitmap**)malloc(rectCount * sizeof(UtilityBitmap*));
+       if (bitmaps == NULL)
+               return B_NO_MEMORY;
+
+       for (int32 i = 0; i < rectCount; i++) {
+               BRect sourceRect = 
region.RectAt(i).OffsetByCopy(-viewRect.LeftTop());
+               int32 targetWidth = (int32)(sourceRect.Width() + 1.5);
+               int32 targetHeight = (int32)(sourceRect.Height() + 1.5);
+
+               if (xScale != 1.0) {
+                       sourceRect.left = (int32)(sourceRect.left * xScale + 
0.5);
+                       sourceRect.right = (int32)(sourceRect.right * xScale + 
0.5);
+                       if (xScale < 1.0)
+                               targetWidth = (int32)(sourceRect.Width() + 1.5);
+               }
+
+               if (yScale != 1.0) {
+                       sourceRect.top = (int32)(sourceRect.top * yScale + 0.5);
+                       sourceRect.bottom = (int32)(sourceRect.bottom * yScale 
+ 0.5);
+                       if (yScale < 1.0)
+                               targetHeight = (int32)(sourceRect.Height() + 
1.5);
+               }
+
+               sourceRect.OffsetBy(bitmapRect.LeftTop());
+                       // sourceRect is now the part of the bitmap we want 
copied
+
+               status_t result = B_OK;
+               if ((xScale > 1.0 || yScale > 1.0)
+                       && (targetWidth * targetHeight < 
(int32)(sourceRect.Width() + 1.5)
+                               * (int32)(sourceRect.Height() + 1.5))) {
+                       // the target bitmap is smaller than the source, scale 
it locally
+                       // and send over the smaller version to avoid sending 
any extra data
+                       if (fBitmapDrawingEngine == NULL) {
+                               fBitmapDrawingEngine
+                                       = new(std::nothrow) 
BitmapDrawingEngine(B_RGBA32);
+                               if (fBitmapDrawingEngine == NULL)
+                                       result = B_NO_MEMORY;
+                       }
+
+                       if (result == B_OK) {
+                               result = 
fBitmapDrawingEngine->SetSize(targetWidth,
+                                       targetHeight);
+                       }
+
+                       if (result == B_OK) {
+                               fBitmapDrawingEngine->SetDrawingMode(B_OP_COPY);
+
+                               switch (bitmap.ColorSpace()) {
+                                       case B_RGBA32:
+                                       case B_RGBA32_BIG:
+                                       case B_RGBA15:
+                                       case B_RGBA15_BIG:
+                                               break;
+
+                                       default:
+                                       {
+                                               // we need to clear the 
background if there may be
+                                               // transparency through 
transparent magic (we use
+                                               // B_OP_COPY when we draw alpha 
enabled bitmaps, so we
+                                               // don't need to clear there)
+                                               // TODO: this is not actually 
correct, as we're going to
+                                               // loose the transparency with 
the conversion to the
+                                               // original non-alpha 
colorspace happening in
+                                               // ExportToBitmap
+                                               rgb_color background = { 0, 0, 
0, 0 };
+                                               fBitmapDrawingEngine->FillRect(
+                                                       BRect(0, 0, targetWidth 
- 1, targetHeight -1),
+                                                       background);
+                                               
fBitmapDrawingEngine->SetDrawingMode(B_OP_OVER);
+                                               break;
+                                       }
+                               }
+
+                               fBitmapDrawingEngine->DrawBitmap(&bitmap, 
sourceRect,
+                                       BRect(0, 0, targetWidth - 1, 
targetHeight - 1), options);
+                               bitmaps[i] = 
fBitmapDrawingEngine->ExportToBitmap(targetWidth,
+                                       targetHeight, bitmap.ColorSpace());
+                               if (bitmaps[i] == NULL)
+                                       result = B_NO_MEMORY;
+                       }
+               } else {
+                       // source is smaller or equal target, extract the 
relevant rects
+                       // directly without any scaling and conversion
+                       targetWidth = (int32)(sourceRect.Width() + 1.5);
+                       targetHeight = (int32)(sourceRect.Height() + 1.5);
+
+                       bitmaps[i] = new(std::nothrow) UtilityBitmap(
+                               BRect(0, 0, targetWidth - 1, targetHeight - 1),
+                               bitmap.ColorSpace(), 0);
+                       if (bitmaps[i] == NULL)
+                               result = B_NO_MEMORY;
+
+                       result = bitmaps[i]->ImportBits(bitmap.Bits(), 
bitmap.BitsLength(),
+                               bitmap.BytesPerRow(), bitmap.ColorSpace(), 
sourceRect.LeftTop(),
+                               BPoint(0, 0), targetWidth, targetHeight);
+                       if (result != B_OK)
+                               delete bitmaps[i];
+               }
+
+               if (result != B_OK) {
+                       for (int32 j = 0; j < i; j++)
+                               delete bitmaps[j];
+                       free(bitmaps);
+                       return result;
+               }
+       }
+
+       return B_OK;
+}
diff --git a/src/servers/app/drawing/html5/HTML5DrawingEngine.h 
b/src/servers/app/drawing/html5/HTML5DrawingEngine.h
new file mode 100644
index 0000000..5a2c547
--- /dev/null
+++ b/src/servers/app/drawing/html5/HTML5DrawingEngine.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2009, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Michael Lotz <mmlr@xxxxxxxx>
+ *             François Revol <revol@xxxxxxx>
+ */
+#ifndef HTML5_DRAWING_ENGINE_H
+#define HTML5_DRAWING_ENGINE_H
+
+#include "DrawingEngine.h"
+#include "DrawState.h"
+#include "HTML5HWInterface.h"
+#include "ServerFont.h"
+
+class BPoint;
+class BRect;
+class BRegion;
+
+class BitmapDrawingEngine;
+class ServerBitmap;
+
+class HTML5DrawingEngine : public DrawingEngine {
+public:
+                                                               
HTML5DrawingEngine(
+                                                                       
HTML5HWInterface* interface);
+       virtual                                         ~HTML5DrawingEngine();
+
+       // HWInterfaceListener interface
+       virtual void                            FrameBufferChanged();
+
+       virtual void                            SetCopyToFrontEnabled(bool 
enabled);
+
+       // for screen shots
+       virtual status_t                        ReadBitmap(ServerBitmap* bitmap,
+                                                                       bool 
drawCursor, BRect bounds);
+
+       // clipping for all drawing functions, passing a NULL region
+       // will remove any clipping (drawing allowed everywhere)
+       virtual void                            ConstrainClippingRegion(const 
BRegion* region);
+
+       virtual void                            SetDrawState(const DrawState* 
state,
+                                                                       int32 
xOffset = 0, int32 yOffset = 0);
+
+       virtual void                            SetHighColor(const rgb_color& 
color);
+       virtual void                            SetLowColor(const rgb_color& 
color);
+       virtual void                            SetPenSize(float size);
+       virtual void                            SetStrokeMode(cap_mode lineCap,
+                                                                       
join_mode joinMode, float miterLimit);
+       virtual void                            SetPattern(const struct 
pattern& pattern);
+       virtual void                            SetDrawingMode(drawing_mode 
mode);
+       virtual void                            SetDrawingMode(drawing_mode 
mode,
+                                                                       
drawing_mode& oldMode);
+       virtual void                            SetBlendingMode(source_alpha 
srcAlpha,
+                                                                       
alpha_function alphaFunc);
+       virtual void                            SetFont(const ServerFont& font);
+       virtual void                            SetFont(const DrawState* state);
+
+       // drawing functions
+       virtual void                            InvertRect(BRect rect);
+
+       virtual void                            DrawBitmap(ServerBitmap* bitmap,
+                                                                       const 
BRect& bitmapRect,
+                                                                       const 
BRect& viewRect, uint32 options = 0);
+
+       // drawing primitives
+       virtual void                            DrawArc(BRect rect, const 
float& angle,
+                                                                       const 
float& span, bool filled);
+       virtual void                            FillArc(BRect rect, const 
float& angle,
+                                                                       const 
float& span,
+                                                                       const 
BGradient& gradient);
+
+       virtual void                            DrawBezier(BPoint* points, bool 
filled);
+       virtual void                            FillBezier(BPoint* points,
+                                                                       const 
BGradient& gradient);
+
+       virtual void                            DrawEllipse(BRect rect, bool 
filled);
+       virtual void                            FillEllipse(BRect rect,
+                                                                       const 
BGradient& gradient);
+
+       virtual void                            DrawPolygon(BPoint* pointList, 
int32 numPoints,
+                                                                       BRect 
bounds, bool filled, bool closed);
+       virtual void                            FillPolygon(BPoint* pointList, 
int32 numPoints,
+                                                                       BRect 
bounds, const BGradient& gradient,
+                                                                       bool 
closed);
+
+       // these rgb_color versions are used internally by the server
+       virtual void                            StrokePoint(const BPoint& point,
+                                                                       const 
rgb_color& color);
+       virtual void                            StrokeRect(BRect rect, const 
rgb_color &color);
+       virtual void                            FillRect(BRect rect, const 
rgb_color &color);
+       virtual void                            FillRegion(BRegion& region,
+                                                                       const 
rgb_color& color);
+
+       virtual void                            StrokeRect(BRect rect);
+       virtual void                            FillRect(BRect rect);
+       virtual void                            FillRect(BRect rect, const 
BGradient& gradient);
+
+       virtual void                            FillRegion(BRegion& region);
+       virtual void                            FillRegion(BRegion& region,
+                                                                       const 
BGradient& gradient);
+
+       virtual void                            DrawRoundRect(BRect rect, float 
xRadius,
+                                                                       float 
yRadius, bool filled);
+       virtual void                            FillRoundRect(BRect rect, float 
xRadius,
+                                                                       float 
yRadius, const BGradient& gradient);
+
+       virtual void                            DrawShape(const BRect& bounds,
+                                                                       int32 
opCount, const uint32* opList,
+                                                                       int32 
pointCount, const BPoint* pointList,
+                                                                       bool 
filled,
+                                                                       const 
BPoint& viewToScreenOffset,
+                                                                       float 
viewScale);
+       virtual void                            FillShape(const BRect& bounds,
+                                                                       int32 
opCount, const uint32* opList,
+                                                                       int32 
pointCount, const BPoint* pointList,
+                                                                       const 
BGradient& gradient,
+                                                                       const 
BPoint& viewToScreenOffset,
+                                                                       float 
viewScale);
+
+       virtual void                            DrawTriangle(BPoint* points,
+                                                                       const 
BRect& bounds, bool filled);
+       virtual void                            FillTriangle(BPoint* points,
+                                                                       const 
BRect& bounds,
+                                                                       const 
BGradient& gradient);
+
+       // these versions are used by the Decorator
+       virtual void                            StrokeLine(const BPoint& start,
+                                                                       const 
BPoint& end, const rgb_color& color);
+       virtual void                            StrokeLine(const BPoint& start,
+                                                                       const 
BPoint& end);
+       virtual void                            StrokeLineArray(int32 numlines,
+                                                                       const 
ViewLineArrayInfo* data);
+
+       // returns the pen position behind the (virtually) drawn string
+       virtual BPoint                          DrawString(const char* string, 
int32 length,
+                                                                       const 
BPoint& point,
+                                                                       
escapement_delta* delta = NULL);
+virtual        BPoint                                  DrawString(const char* 
string, int32 length,
+                                                                       const 
BPoint* offsets);
+
+       virtual float                           StringWidth(const char* string, 
int32 length,
+                                                                       
escapement_delta* delta = NULL);
+
+       // software rendering backend invoked by CopyRegion() for the sorted
+       // individual rects
+       virtual BRect                           CopyRect(BRect rect, int32 
xOffset,
+                                                                       int32 
yOffset) const;
+
+private:
+                       status_t                        _AddCallback();
+
+       static  bool                            _DrawingEngineResult(void* 
cookie,
+                                                                       
CanvasMessage& message);
+
+                       BRect                           _BuildBounds(BPoint* 
points, int32 pointCount);
+               status_t                                
_ExtractBitmapRegions(ServerBitmap& bitmap,
+                                                                       uint32 
options, const BRect& bitmapRect,
+                                                                       const 
BRect& viewRect, double xScale,
+                                                                       double 
yScale, BRegion& region,

[ *** diff truncated: 2166 lines dropped *** ]



Other related posts: