webengine/wmlengine/src/ImageCH/src/Epoc32ImageContentHandler.cpp
changeset 0 dd21522fd290
child 37 cb62a4f66ebe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/wmlengine/src/ImageCH/src/Epoc32ImageContentHandler.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1128 @@
+/*
+* Copyright (c) 2000 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <e32def.h>  // First to avoid NULL redefine warning (no #ifndef NULL).
+#include <e32std.h>
+
+#include "nw_lmgr_slavepropertylist.h"
+#include "nw_fbox_imagebuttonbox.h"
+#include "nw_lmgr_imgcontainerbox.h"
+#include "nw_wml1x_wml1xcontenthandler.h"
+#include "nw_wml1x_wml1xdefaultstylesheet.h"
+#include "GDIDeviceContext.h"
+#include "nw_imagech_epoc32contenthandleri.h"
+#include "nwx_http_defs.h"
+#include "nw_lmgr_animatedimagebox.h"
+#include "nw_image_virtualimage.h"
+#include "nw_system_optionlist.h"
+#include "HEDDocumentListener.h"
+#include "nw_lmgr_rootbox.h"
+#include "nw_image_epoc32simpleimage.h"
+#include "epoc32imagedecoder.h"
+#include "nw_lmgr_statictablecellbox.h"
+#include "nwx_logger.h"
+#include "nwx_settings.h"
+#include "MemoryManager.h"
+
+
+/*required for animations*/
+
+/* ------------------------------------------------------------------------- */
+
+/* find context box to be deleted */
+/* ------------------------------------------------------------------------- */
+static
+NW_LMgr_Box_t*
+NW_LMgr_ImageCH_Epoc32ContentHandler_FindContextBox( NW_HED_DocumentNode_t* documentNode,
+                                                    void* context )
+  {
+  NW_LMgr_Box_t* box = NULL;
+  NW_LMgr_Box_t* contextBox = NULL;
+  NW_LMgr_BoxVisitor_t boxVisitor;
+
+  box = NW_HED_ContentHandlerOf( documentNode )->boxTree;
+  if(NW_LMgr_BoxVisitor_Initialize( &boxVisitor, box ) != KBrsrSuccess )
+    {
+    return NULL;
+    }
+  while( ( box = NW_LMgr_BoxVisitor_NextBox( &boxVisitor, 0 ) ) != NULL )
+    {
+    if( ( NW_Object_IsInstanceOf( box, &NW_LMgr_ContainerBox_Class ) &&
+         !NW_Object_IsInstanceOf( box->propList, &NW_LMgr_SlavePropertyList_Class ) )
+         || NW_Object_IsClass( box, &NW_FBox_ImageButtonBox_Class )
+         || NW_Object_IsDerivedFrom( box, &NW_LMgr_ImgContainerBox_Class ) )
+      {
+      NW_LMgr_PropertyValueType_t type = NW_CSS_ValueType_Object;
+      NW_LMgr_PropertyValue_t value;
+
+      // "wml image" (wbmp) element Id is integer type while "html image" Id is object type
+      if( NW_Object_IsInstanceOf( documentNode, &NW_Wml1x_ContentHandler_Class) )
+        {
+        type = NW_CSS_ValueType_Integer;
+        }
+      if( NW_LMgr_Box_GetPropertyValue( box, NW_CSS_Prop_elementId, type, &value ) == KBrsrSuccess )
+        {
+        if( type == NW_CSS_ValueType_Object && value.object == context ||
+            type == NW_CSS_ValueType_Integer && value.integer == NW_INT32_CAST(context) )
+          {
+          // We found a box that has element Id same as context
+          contextBox = box;
+          break;
+          }
+        }
+      }
+    }
+  return contextBox;
+  }
+
+/* ------------------------------------------------------------------------- */
+static
+TBrowserStatusCode
+NW_LMgr_ImageCH_Epoc32ContentHandler_HandleValidImageBox( NW_ImageCH_Epoc32ContentHandler_t* thisObj )
+  {
+  NW_ASSERT( thisObj );
+
+  NW_TRY( status )
+    {
+    NW_HED_DocumentNode_t* documentNode = NW_HED_DocumentNodeOf( thisObj )->parent;
+    NW_LMgr_Box_t* cannedImageBox;
+
+    // The box tree hasn't been created yet; there is no need to replace the
+    // missing image icon.
+    if( NW_HED_ContentHandlerOf( documentNode )->boxTree == NULL )
+      {
+      NW_THROW_STATUS( status, KBrsrFailure );
+      }
+
+    // find the context box (placeholder with the canned image)
+    cannedImageBox = NW_LMgr_ImageCH_Epoc32ContentHandler_FindContextBox( documentNode, thisObj->context );
+
+    // The "cannedImageBox" is a placeholder for the real image. If it doesn't
+    // exist, then the image was loaded before we had time to create it so 
+    // there is nothing to replace
+    if( cannedImageBox != NULL )
+      {
+      // When the cannedImageBox is imagebuttonbox we know we are dealing
+      // input type=image tag
+      if( NW_Object_IsClass( cannedImageBox, &NW_FBox_ImageButtonBox_Class ) )
+        {
+        NW_FBox_ImageButtonBox_t* imageButtonBox = NW_FBox_ImageButtonBoxOf( cannedImageBox );
+        imageButtonBox->image = thisObj->image;
+        // set boxtree
+        NW_HED_ContentHandler_t* contentHandler = NW_HED_ContentHandlerOf( thisObj );
+        contentHandler->boxTree = NW_LMgr_BoxOf( imageButtonBox );
+        }
+      else
+        {
+        // set boxtree
+        NW_HED_ContentHandler_t* contentHandler = NW_HED_ContentHandlerOf( thisObj );
+        contentHandler->boxTree = NW_LMgr_BoxOf( cannedImageBox );  
+        }
+      if( NW_Object_IsInstanceOf( documentNode, &NW_Wml1x_ContentHandler_Class) )
+        {
+        // here comes some WML specific calls
+        NW_LMgr_Property_t    prop;
+        NW_LMgr_PropertyValue_t id;
+        id.integer = NW_INT32_CAST( thisObj->context );
+
+        AddImageProperties( NW_Wml1x_ContentHandlerOf( documentNode ), cannedImageBox, id );
+        NW_Wml1x_ImageWithinAnchorDefaultStyle( &prop, cannedImageBox );
+        }
+      }
+    }
+  NW_CATCH(status)
+    {
+    }
+  NW_FINALLY
+    {
+    return status;
+    }
+  NW_END_TRY
+  }
+
+/* ------------------------------------------------------------------------- *
+   class definition
+ * ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+const
+NW_ImageCH_Epoc32ContentHandler_Class_t NW_ImageCH_Epoc32ContentHandler_Class = {
+  { /* NW_Object_Core                */
+    /* super                         */ &NW_HED_ContentHandler_Class,
+    /* queryInterface                */ _NW_Object_Base_QueryInterface
+  },
+  { /* NW_Object_Base                */
+    /* interfaceList                 */ _NW_ImageCH_Epoc32ContentHandler_InterfaceList
+  },
+  { /* NW_Object_Dynamic             */
+    /* instanceSize                  */ sizeof (NW_ImageCH_Epoc32ContentHandler_t),
+    /* construct                     */ _NW_ImageCH_Epoc32ContentHandler_Construct,
+    /* destruct                      */ _NW_ImageCH_Epoc32ContentHandler_Destruct
+  },
+  { /* NW_HED_DocumentNode           */
+    /* cancel                        */ _NW_HED_DocumentNode_Cancel,
+    /* partialLoadCallback	     */ NULL,
+    /* initialize                    */ _NW_ImageCH_Epoc32ContentHandler_Initialize,
+    /* nodeChanged                   */ _NW_HED_DocumentNode_NodeChanged,
+    /* getBoxTree                    */ _NW_ImageCH_Epoc32ContentHandler_GetBoxTree,
+    /* processEvent                  */ _NW_HED_DocumentNode_ProcessEvent,
+    /* handleError                   */ _NW_HED_DocumentNode_HandleError,
+    /* suspend                       */ _NW_HED_ContentHandler_Suspend,
+    /* resume                        */ _NW_HED_DocumentNode_Resume,
+    /* allLoadsCompleted             */ _NW_HED_ContentHandler_AllLoadsCompleted,
+    /* intraPageNavigationCompleted  */ _NW_HED_DocumentNode_IntraPageNavigationCompleted,
+    /* loseFocus                     */ _NW_HED_ContentHandler_LoseFocus,
+    /* gainFocus                     */ _NW_HED_ContentHandler_GainFocus,
+    /* handleLoadComplete           */ _NW_HED_DocumentNode_HandleLoadComplete,
+  },
+  { /* NW_HED_ContentHandler         */
+    /* partialNextChunk              */ _NW_ImageCH_Epoc32ContentHandler_PartialNextChunk,
+    /* getTitle                      */ _NW_ImageCH_Epoc32ContentHandler_GetTitle,
+    /* getUrl                        */ _NW_HED_ContentHandler_GetURL,
+    /* resolveUrl                    */ _NW_HED_ContentHandler_ResolveURL,
+    /* createHistoryEntry            */ _NW_HED_ContentHandler_CreateHistoryEntry,
+    /* createIntraHistoryEntry       */ _NW_HED_ContentHandler_CreateIntraDocumentHistoryEntry,
+    /* newUrlResponse                */ _NW_HED_ContentHandler_NewUrlResponse,
+    /* createBoxTree                 */ _NW_ImageCH_Epoc32ContentHandler_CreateBoxTree,
+    /* handleRequest                 */ _NW_HED_ContentHandler_HandleRequest,
+    /* featureQuery                  */ _NW_HED_ContentHandler_FeatureQuery,
+    /* responseComplete              */ _NW_HED_ContentHandler_ResponseComplete
+  },
+  { /* NW_ImageCH_Epoc32ContentHandler */
+   /* unused                         */ NW_Object_Unused
+  }
+};
+
+/* ------------------------------------------------------------------------- */
+const
+NW_Object_Class_t* const _NW_ImageCH_Epoc32ContentHandler_InterfaceList[] = {
+  &_NW_ImageCH_Epoc32_ImageObserver_Class,
+  NULL
+};
+
+/* ------------------------------------------------------------------------- */
+const
+NW_Image_IImageObserver_Class_t _NW_ImageCH_Epoc32_ImageObserver_Class = {
+  { /* NW_Object_Core       */
+    /* super                */ &NW_Image_IImageObserver_Class,
+    /* queryInterface       */ _NW_Object_Interface_QueryInterface
+  },
+  { /* NW_Object_Interface  */
+    /* offset               */ offsetof( NW_ImageCH_Epoc32ContentHandler_t, NW_Image_IImageObserver )
+  },
+  { /* NW_Image_IImageObserver */
+    /* imageOpened          */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpened,
+    /* sizeChanged          */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_SizeChanged,
+    /* imageOpeningStarted  */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpeningStarted,
+    /* imageDecoded         */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDecoded,
+    /* imageDestroyed       */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDestroyed,
+    /* isVisible            */ _NW_ImageCH_Epoc32ContentHandler_IImageObserver_IsVisible
+  }
+};
+
+/* ------------------------------------------------------------------------- *
+   virtual methods
+ * ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+TBrowserStatusCode
+_NW_ImageCH_Epoc32ContentHandler_Construct( NW_Object_Dynamic_t* dynamicObject,
+                                            va_list* argList )
+{
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+  NW_HED_UrlRequest_t* urlRequest;
+  TBrowserStatusCode status = KBrsrSuccess;
+
+  /* for convenience */
+  thisObj = NW_ImageCH_Epoc32ContentHandlerOf (dynamicObject);
+
+  /* invoke our superclass constructor */
+  status = _NW_HED_ContentHandler_Construct (dynamicObject, argList);
+  if (status != KBrsrSuccess) 
+    {
+    return status;
+    }
+
+  NW_HED_ContentHandler_SetIsEmbeddable (thisObj, NW_TRUE);
+
+  /* get the loadMode */
+  urlRequest = va_arg (*argList, NW_HED_UrlRequest_t*);
+  NW_ASSERT (urlRequest);
+  NW_ASSERT (NW_Object_IsInstanceOf (urlRequest, &NW_HED_UrlRequest_Class));
+
+  thisObj->noStore = (NW_Bool)va_arg (*argList, NW_Uint32);
+
+  thisObj->loadMode = urlRequest->loadMode;
+
+  /* copy the request url */
+  const NW_Ucs2* rawUrl = NW_HED_UrlRequest_GetRawUrl(urlRequest);
+  if (rawUrl != NULL)
+    {
+    thisObj->requestUrl = NW_Str_Newcpy(rawUrl);
+    if (thisObj->requestUrl == NULL)
+       {
+       status = KBrsrOutOfMemory;
+       }
+    }
+
+  thisObj->altText = NULL;
+
+  /*
+  ** TODO this is the error passed in NW_HED_Image_ContentHandler_NewBrokenImage
+  ** in the future this may be useful information.  It isn't right now...
+
+  thisObj->brokenImageError = va_arg (*argList, TBrowserStatusCode);
+  */
+
+  return status;
+}
+
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_Destruct( NW_Object_Dynamic_t* dynamicObject )
+  {
+
+  /* parameter assertion block */
+  NW_ASSERT(NW_Object_IsInstanceOf (dynamicObject,
+                                     &NW_ImageCH_Epoc32ContentHandler_Class));
+
+  /* for convenience */
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj = NW_ImageCH_Epoc32ContentHandlerOf( dynamicObject );
+
+  // removed observer
+  if( thisObj->image )
+    {
+    (void) NW_Image_AbstractImage_RemoveImageObserver( thisObj->image,
+      &thisObj->NW_Image_IImageObserver );
+    }
+
+   /* deallocate the buffer */
+  NW_Object_Delete( thisObj->image );
+  thisObj->image = NULL;
+
+  /* free the title */
+  NW_Object_Delete( thisObj->title );
+
+   /* deallocate the request url */
+  NW_Mem_Free( thisObj->requestUrl );
+
+  /* deallocate the alt text */
+  NW_Mem_Free( thisObj->altText );
+  }
+
+/* ------------------------------------------------------------------------- */
+TBrowserStatusCode
+_NW_ImageCH_Epoc32ContentHandler_Initialize( NW_HED_DocumentNode_t* documentNode,
+  TBrowserStatusCode aInitStatus )
+  {
+  TBrowserStatusCode status = KBrsrSuccess;
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+  NW_REQUIRED_PARAM( aInitStatus );
+
+  // parameter assertion block 
+  NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
+                                     &NW_ImageCH_Epoc32ContentHandler_Class));
+
+  // for convenience 
+  thisObj = NW_ImageCH_Epoc32ContentHandlerOf (documentNode);
+
+  // let the image decoder know that no more data comes in.
+  // no need to inform virtual images as they share the same
+  // decoder
+  if( thisObj->image && NW_Object_IsClass( thisObj->image, &NW_Image_Epoc32Simple_Class ) == NW_TRUE )
+    {
+    NW_Image_Epoc32Simple_t* simpleImage = NW_Image_Epoc32SimpleOf( thisObj->image );
+
+    status = NW_Image_Epoc32Simple_Initialize( simpleImage );
+    }
+  return status;
+  }
+
+/* ------------------------------------------------------------------------- */
+TBrowserStatusCode
+_NW_ImageCH_Epoc32ContentHandler_GetBoxTree( NW_HED_DocumentNode_t* documentNode,
+                                             NW_LMgr_Box_t** boxTree )
+  {
+  // parameter assertion block 
+  NW_ASSERT (NW_Object_IsInstanceOf (documentNode,
+                                     &NW_ImageCH_Epoc32ContentHandler_Class));
+
+  NW_HED_ContentHandler_t* contentHandler = NW_HED_ContentHandlerOf( documentNode );
+  if( contentHandler->boxTree )
+    {
+	  *boxTree = contentHandler->boxTree;
+	  return KBrsrSuccess;
+    }
+  return _NW_HED_ContentHandler_GetBoxTree( documentNode, boxTree );
+  }
+
+
+/* ------------------------------------------------------------------------- */
+TBrowserStatusCode
+_NW_ImageCH_Epoc32ContentHandler_PartialNextChunk(NW_HED_ContentHandler_t* contentHandler,
+                                                  NW_Int32 chunkIndex,
+                                                  NW_Url_Resp_t* response,
+                                                  void* context)
+    {
+    NW_TRY(status) 
+        {
+        NW_ASSERT(contentHandler != NULL);
+        NW_ASSERT(response != NULL);
+        
+        NW_Image_Epoc32Simple_t* simpleImage;
+        NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+        
+        // for convenience 
+        thisObj = NW_ImageCH_Epoc32ContentHandlerOf(contentHandler);
+        // make sure we have a valid response
+        NW_THROW_ON_NULL(response, status, KBrsrUnexpectedError);
+        
+        // first chunk
+        if (chunkIndex == 0)
+            {
+            // invoke superclass
+            status = NW_HED_ContentHandler_Class.NW_HED_ContentHandler.partialNextChunk( 
+                                           contentHandler, chunkIndex, response, context);
+            // response has been released by the base class call.
+            response = NULL;
+            _NW_THROW_ON_ERROR(status);
+            
+            // Do we have an image content-type that Symbian won't recognize,
+            // but the browser supports.
+            TImageType imageType = GetRecognizedImageType((const char*)
+                                        contentHandler->response->contentTypeString);
+                
+            NW_GDI_Dimension3D_t size = {0, 0, 0};
+            // create bitmap
+            simpleImage = NW_Image_Epoc32Simple_New(size, NULL, NULL, NW_FALSE, NW_FALSE,
+                                                    imageType,
+                                                    contentHandler->response->body->data, 
+                                                    contentHandler->response->body->length,
+                                                    NW_HED_DocumentNodeOf(thisObj));
+            NW_THROW_OOM_ON_NULL(simpleImage, status);
+            
+            // The image now has ownership of the raw data.
+            contentHandler->response->body->length = 0;
+            contentHandler->response->body->allocatedLength = 0;
+            delete contentHandler->response->body;   
+            contentHandler->response->body = NULL;
+            
+            thisObj->image = NW_Image_AbstractImageOf(simpleImage);
+            // set observer
+            status = NW_Image_AbstractImage_SetImageObserver(thisObj->image,
+                                                             &thisObj->NW_Image_IImageObserver);
+            NW_THROW_ON(KBrsrOutOfMemory, status);
+            // ignore observer errors -except OOM
+            status = KBrsrSuccess;
+            }
+        // do not take last chunk as it has no data
+        else if (chunkIndex != -1)
+            {
+            // make sure that the image has been created when the first 
+            // chunk came in
+            NW_THROW_ON_NULL(thisObj->image, status, KBrsrUnexpectedError);
+            
+            NW_ASSERT(NW_Object_IsInstanceOf(thisObj->image,
+                                             &NW_Image_Epoc32Simple_Class));    
+            simpleImage = NW_Image_Epoc32SimpleOf(thisObj->image);
+            // pass chunk to the decoded
+            status = NW_Image_Epoc32Simple_PartialNextChunk(NW_Image_AbstractImageOf(simpleImage),
+                                                            response->body);
+            // NW_Image_Epoc32Simple_PartialNextChunk takes body ownership
+            response->body = NULL;
+            
+            _NW_THROW_ON_ERROR(status);      
+            }
+        else
+            {
+            // this function musn't be called with the last partial response that has no body.
+            // Initialize must be called instead
+            NW_ASSERT(NW_TRUE);
+            }
+        }
+    NW_CATCH(status) 
+        {
+        }
+    NW_FINALLY 
+        {
+        // free response
+        UrlLoader_UrlResponseDelete(response);
+        return status;
+        } 
+    NW_END_TRY
+    }
+
+
+/* ------------------------------------------------------------------------- */
+const NW_Text_t*
+_NW_ImageCH_Epoc32ContentHandler_GetTitle( NW_HED_ContentHandler_t* contentHandler )
+{
+  static const NW_Ucs2 storage[] = { 'I', 'm', 'a', 'g', 'e', '\0' };
+
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+  /* for convenience */
+  thisObj = NW_ImageCH_Epoc32ContentHandlerOf( contentHandler );
+
+  /* we create the title just-in-time */
+  if( thisObj->title == NULL )
+    {
+    thisObj->title = (NW_Text_t*) NW_Text_UCS2_New ((NW_Ucs2*) storage, 0, 0);
+    }
+  return thisObj->title;
+  }
+
+
+/* ------------------------------------------------------------------------- */
+TBrowserStatusCode
+_NW_ImageCH_Epoc32ContentHandler_CreateBoxTree( NW_HED_ContentHandler_t* contentHandler,
+                                                NW_LMgr_Box_t** boxTree )
+{
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+  NW_Image_AbstractImage_t* image = NULL;
+  NW_LMgr_Box_t* box = NULL;
+  NW_Bool brokenImage = NW_FALSE;
+
+  /* parameter assertion block */
+  NW_ASSERT( NW_Object_IsInstanceOf (contentHandler,
+                                     &NW_HED_ContentHandler_Class ) );
+
+  /* for convenience */
+  thisObj = NW_ImageCH_Epoc32ContentHandlerOf( contentHandler );
+
+  /* create the image alias from our image data*/
+  if( thisObj->image != NULL )
+  {
+  /* This case arises when this Image Content Handler contains the Virtual
+     Image */
+    if( NW_Object_IsInstanceOf( thisObj->image, &NW_Image_Virtual_Class ) )
+      {
+      NW_Image_Virtual_t* virtualImage = NW_Image_VirtualOf( thisObj->image );
+      image = (NW_Image_AbstractImage_t*) NW_Image_Virtual_New( virtualImage->image );
+      }
+    else
+      {
+      image = (NW_Image_AbstractImage_t*)NW_Image_Virtual_New( thisObj->image );
+      }
+    }
+  /* for some reason the above failed so create a broken image instead */
+  if( image == NULL )
+    {
+    NW_HED_DocumentRoot_t         *documentRoot;
+    NW_LMgr_RootBox_t             *rootBox;
+    NW_Image_CannedImages_t* cannedImages;
+
+    /* get the RootBox from through IDocumentListener interface */
+    documentRoot =
+      (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode (contentHandler);
+    NW_ASSERT(documentRoot != NULL);
+
+    /* extract the image from our canned images */
+    rootBox = NW_HED_DocumentRoot_GetRootBox(documentRoot);
+    NW_ASSERT(rootBox);
+
+    cannedImages = rootBox->cannedImages;
+    NW_ASSERT(cannedImages!=NULL);
+
+    image = (NW_Image_AbstractImage_t*)
+                       NW_Image_CannedImages_GetImage( cannedImages,
+                                                      NW_Image_Broken );
+    brokenImage = NW_TRUE;
+    }
+  /* create the image box */
+  if( image != NULL )
+    {
+    box = (NW_LMgr_Box_t*) NW_LMgr_AnimatedImageBox_New(0, image, NULL, brokenImage );
+    }
+
+  if( box == NULL )
+    {
+    NW_Object_Delete( image );
+    }
+
+  /* return the box (which may be NULL )*/
+  *boxTree = box;
+  return KBrsrSuccess;
+  }
+
+/* ------------------------------------------------------------------------- */
+NW_HED_UrlRequest_LoadMode_t
+NW_ImageCH_Epoc32ContentHandler_GetLoadMode( NW_ImageCH_Epoc32ContentHandler_t* thisObj )
+  {
+  /* parameter assertion block */
+  NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+
+  return thisObj->loadMode;
+  }
+
+
+/* ------------------------------------------------------------------------- *
+   NW_ImageCH_Epoc32_ImageObserver implementation
+ * ------------------------------------------------------------------------- */
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpened( NW_Image_IImageObserver_t* imageObserver,
+                                                             NW_Image_AbstractImage_t* abstractImage,
+                                                             NW_Bool failed,
+                                                             NW_Int16 suppressDupReformats )
+  {
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj = NULL;
+  NW_HED_DocumentRoot_t* docRoot = NULL;
+  NW_LMgr_RootBox_t* rootBox = NULL;
+  NW_Bool forceReformat = NW_FALSE;
+  NW_Bool relayoutNeeded = NW_FALSE;
+  NW_Bool smallScreenOn;
+
+  //lint -e{550} Symbol not accessed
+  NW_TRY( status )
+    {
+    // parameter assertion block
+    NW_ASSERT( imageObserver != NULL );
+    NW_ASSERT( abstractImage != NULL );
+    NW_ASSERT( NW_Object_IsInstanceOf( imageObserver,
+                                      &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+    NW_LOG0(NW_LOG_LEVEL5, "_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpened START");
+    // obtain the implementer
+    thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( imageObserver );
+    NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+    // get rootbox 
+    docRoot = (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode( thisObj );
+    NW_THROW_ON_NULL( docRoot, status, KBrsrFailure );
+
+    rootBox = NW_HED_DocumentRoot_GetRootBox( docRoot );
+    NW_THROW_ON_NULL( rootBox, status, KBrsrFailure );
+
+    smallScreenOn = NW_LMgr_RootBox_GetSmallScreenOn( rootBox );
+
+    if( failed == NW_FALSE )
+      {
+      relayoutNeeded = NW_TRUE;
+
+      if( thisObj->context )
+        {
+        status =  NW_LMgr_ImageCH_Epoc32ContentHandler_HandleValidImageBox( thisObj );
+        // When status is KBrsrFailure, box tree has not been completely created;
+        // calling MVCView::ReformatBox in the later code will have problems
+        // and program will revisit here because decoder is SetActive again;
+        // so no need to execute code following.
+        // Only set context to NULL when the status is KBrsrSuccess
+        if (status == KBrsrSuccess)
+          {
+          thisObj->context = NULL;
+          }
+        else
+          {
+          NW_THROW( KBrsrSuccess );
+          }
+        }
+
+      /*
+      ** See the comment about "iSuppressDupReformats" in NW_MVC_View_ReformatBox.
+      **
+      ** This helps speed up the special case when an image is duplicated many times
+      ** within the same document.
+      */
+      if( smallScreenOn )
+        {
+        // Start suppressing reformats.
+        if (suppressDupReformats != NW_Image_AbstractImage_SuppressDupReformats_Stop)
+          {
+          rootBox->boxTreeListener->EnableSuppressDupReformats (suppressDupReformats);
+          }
+
+        // Stop suppressing reformats.
+        else 
+          {
+          // This is the last observer.  If any of the image observers needed a 
+          // reformat then force the reformat (below) even if this box doesn't require one
+          forceReformat = rootBox->boxTreeListener->IsForcedReformatNeeded ();
+
+          rootBox->boxTreeListener->EnableSuppressDupReformats (suppressDupReformats);
+          }
+        }
+
+      // get the image box
+      NW_LMgr_Box_t* imageBox = NW_HED_ContentHandlerOf( thisObj )->boxTree;
+
+      if( imageBox )
+        {
+        // first get the visible part of the imagebox and then we can check if the visible 
+        // part is in the view
+        NW_GDI_Rectangle_t imageRect;
+
+        if( NW_LMgr_Box_GetVisibleBounds( imageBox, &imageRect ) == NW_TRUE )
+          {
+          // we need the rootbox to get the device context which then gives us the
+          // current view coordinates
+          CGDIDeviceContext* deviceContext = NW_LMgr_RootBox_GetDeviceContext( rootBox );
+          NW_THROW_ON_NULL( deviceContext, status, KBrsrFailure );
+
+          NW_GDI_Rectangle_t viewRect = deviceContext->ClipRect();
+
+          // check if the image box is in the view
+          if( NW_GDI_Rectangle_Cross( &imageRect, &viewRect, NULL ) )
+            {
+            // force decode
+            status = NW_Image_AbstractImage_ForceImageDecode( abstractImage );
+            NW_THROW_ON_ERROR( status );
+            }
+          }
+
+        NW_LMgr_Property_t hProp;
+        NW_LMgr_Property_t wProp;
+        // check if the replaced image needs relayout.
+        // call relayout, unless both height and width attributes are set.
+        if( ( NW_LMgr_Box_GetProperty( imageBox, NW_CSS_Prop_height, &hProp ) == KBrsrSuccess ) &&
+            ( NW_LMgr_Box_GetProperty( imageBox, NW_CSS_Prop_width, &wProp ) == KBrsrSuccess ) )
+          {
+                    NW_GDI_Rectangle_t bounds;
+                    // inner rectangle's width, height corresponds to css properties
+                    (void) NW_LMgr_Box_GetInnerRectangle(imageBox, &bounds);
+
+          if( (hProp.value.integer != bounds.dimension.height) || 
+              (wProp.value.integer != bounds.dimension.width) )
+            {
+            relayoutNeeded = NW_TRUE;
+            }
+          else
+            {
+            relayoutNeeded = NW_FALSE;
+            }
+          }
+          // when image is ready to be displayed we need to
+          // 1. create a virtual image in order that we could replace the canned -broken- image 
+          // in the image container box
+          // 2. replace the canned image
+          NW_Image_AbstractImage_t* image = NULL;
+
+          if( NW_Object_IsInstanceOf( abstractImage, &NW_Image_Virtual_Class ) )
+            {
+            NW_Image_Virtual_t* virtualImage = NW_Image_VirtualOf( abstractImage );
+            image = (NW_Image_AbstractImage_t*)NW_Image_Virtual_New( virtualImage->image );
+            }
+          else
+            {
+            image = (NW_Image_AbstractImage_t*)NW_Image_Virtual_New( abstractImage );
+            }
+          NW_THROW_OOM_ON_NULL( image, status );
+
+          // replace image
+          if( NW_Object_IsInstanceOf( imageBox, &NW_LMgr_ImgContainerBox_Class ) == NW_TRUE )
+            {
+            NW_LMgr_ImgContainerBox_ReplaceBrokenImage( imageBox, image );
+            }
+          else if( NW_Object_IsInstanceOf( imageBox, &NW_FBox_ImageButtonBox_Class ) == NW_TRUE )
+            {
+            NW_LMgr_ImageButtonBox_ReplaceBrokenImage( imageBox, image );
+            }
+          else
+            {
+            NW_THROW_UNEXPECTED( status );
+            }
+
+        // handle relayout needs
+        if( ( relayoutNeeded == NW_TRUE ) || ( forceReformat == NW_TRUE ) )
+          {
+          if( smallScreenOn )
+            {
+            // in vertical layout mode we just want to format the flow 
+            // containing the image
+            (void) rootBox->boxTreeListener->ReformatBox(imageBox);
+
+            if ((suppressDupReformats == NW_Image_AbstractImage_SuppressDupReformats_Start) ||
+                (suppressDupReformats == NW_Image_AbstractImage_SuppressDupReformats_Continue))
+              {
+              rootBox->boxTreeListener->ForcedReformatNeeded ();
+              }
+            }
+          else
+            {
+            NW_Image_IImageObserver_SizeChanged( imageObserver, abstractImage );
+            }
+          }
+        }
+      }
+    }
+  NW_CATCH( status )
+    {
+    }
+  NW_FINALLY
+    {
+    // open ends. remove it from the queue
+    NW_LMgr_RootBox_ImageOpened( rootBox );
+
+    // Now that the image is opened and its box has the updated size info
+    // recalculate the RootBox's extents, this also causes the scrollbar values
+    // to be updated.
+    if( ( relayoutNeeded == NW_TRUE ) || ( forceReformat == NW_TRUE ) )
+      {
+      NW_LMgr_RootBox_ExtendsCalculationNeeded ( rootBox );
+      }
+
+    NW_LOG0(NW_LOG_LEVEL5, "_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpened ENDS");
+    return;
+    }
+  NW_END_TRY
+  }
+
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_SizeChanged( NW_Image_IImageObserver_t* imageObserver,
+                                                             NW_Image_AbstractImage_t* abstractImage )
+  {
+  NW_REQUIRED_PARAM( abstractImage );
+
+  NW_TRY( status )
+    {
+    NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+    // parameter assertion block
+    NW_ASSERT( imageObserver != NULL );
+    NW_ASSERT( abstractImage != NULL );
+    NW_ASSERT(NW_Object_IsInstanceOf( imageObserver,
+                                      &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+    // obtain the implementer
+    thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( imageObserver );
+    NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+
+    // relayout on the entire tree
+    // first get rootBox and then we can initialize the
+    // relayout event on that.
+    NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode( thisObj );
+    NW_THROW_ON_NULL( docRoot, status, KBrsrFailure );
+
+    NW_LMgr_RootBox_t* rootBox = NW_HED_DocumentRoot_GetRootBox( docRoot );
+    NW_THROW_ON_NULL( rootBox, status, KBrsrFailure );
+
+    // update image container size
+    NW_LMgr_Box_t* box;
+
+    status = NW_HED_DocumentNode_GetBoxTree( NW_HED_DocumentNodeOf( thisObj ), &box );
+    NW_THROW_ON_ERROR( status );
+  
+    // table performance: to prevent additional relayouts on the entire page (max pass of the automatic 
+    // table algorithm), images update parent table size by setting a flag on the table. the actual resize 
+    // happens when a relayout event is generated.
+    while( box->parent != NULL )
+      {
+      // find the parent table.
+      if( NW_Object_IsInstanceOf( box->parent, &NW_LMgr_StaticTableBox_Class ) == NW_TRUE )
+        {
+        NW_LMgr_StaticTableBox_TableSizeChanged( NW_LMgr_StaticTableBoxOf( box->parent ) );
+        break;
+        }
+      box = NW_LMgr_BoxOf( box->parent );
+      }
+    // and send layout event
+    NW_LMgr_RootBox_SetNeedsRelayout( rootBox );
+    }
+  NW_CATCH( status )
+    {
+    }
+  NW_FINALLY
+    {
+    return;
+    }
+  NW_END_TRY
+  }
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageOpeningStarted( NW_Image_IImageObserver_t* imageObserver,
+                                                                     NW_Image_AbstractImage_t* abstractImage )
+  {
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+  NW_HED_DocumentRoot_t*             documentRoot;
+  NW_LMgr_RootBox_t*                 rootBox;
+
+  NW_REQUIRED_PARAM( abstractImage );
+
+  /* parameter assertion block */
+  NW_ASSERT( imageObserver != NULL );
+  NW_ASSERT( abstractImage != NULL );
+  NW_ASSERT(NW_Object_IsInstanceOf( imageObserver,
+                                    &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+    {
+    /* obtain the implementer */
+    thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( imageObserver );
+    NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+
+    // get the RootBox through IDocumentListener interface 
+    documentRoot = (NW_HED_DocumentRoot_t*) NW_HED_DocumentNode_GetRootNode( thisObj );
+    NW_ASSERT( documentRoot != NULL );
+
+    rootBox = NW_HED_DocumentRoot_GetRootBox( documentRoot );
+    NW_ASSERT( rootBox != NULL );
+
+    NW_LMgr_RootBox_ImageOpeningStarted( rootBox );
+    }
+  }
+
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDecoded( NW_Image_IImageObserver_t* imageObserver,
+                                                              NW_Image_AbstractImage_t* abstractImage,
+                                                              NW_Bool failed)
+  {
+  NW_REQUIRED_PARAM( abstractImage );
+  
+  //lint -e{550} Symbol not accessed
+  NW_TRY( status )
+    {
+    NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+    // parameter assertion block 
+    NW_ASSERT( imageObserver != NULL );
+    NW_ASSERT( abstractImage != NULL );
+    NW_ASSERT(NW_Object_IsInstanceOf( imageObserver,
+                                      &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+    NW_LOG0(NW_LOG_LEVEL5, "_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDecoded START");
+    // obtain the implementer 
+    thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( imageObserver );
+    NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+   
+    NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode( thisObj );
+    NW_THROW_ON_NULL( docRoot, status, KBrsrFailure );
+
+    NW_LMgr_RootBox_t* rootBox = NW_HED_DocumentRoot_GetRootBox( docRoot );
+    NW_THROW_ON_NULL( rootBox, status, KBrsrFailure );
+
+    NW_LMgr_Box_t* box = NW_HED_ContentHandlerOf( thisObj )->boxTree;
+    NW_THROW_ON_NULL( box, status, KBrsrFailure );
+   
+    // if the decode failed, we want to replace the unencoded image with the broken image
+    if (failed)
+      {    
+      NW_Image_AbstractImage_t* cannedImage = NULL;
+      NW_Image_AbstractImage_t* image = NULL;
+
+      NW_ASSERT( rootBox->cannedImages != NULL );
+
+      cannedImage = (NW_Image_AbstractImage_t*)
+          NW_Image_CannedImages_GetImage( rootBox->cannedImages, NW_Image_Missing );
+      NW_THROW_OOM_ON_NULL( cannedImage, status );
+     
+      image = (NW_Image_AbstractImage_t*)NW_Image_Virtual_New( cannedImage );
+      NW_THROW_OOM_ON_NULL( image, status );
+
+      // replace image
+      if( NW_Object_IsInstanceOf( box, &NW_LMgr_ImgContainerBox_Class ) == NW_TRUE )
+        {
+        NW_LMgr_ImgContainerBox_ReplaceBrokenImage( box, image );
+        NW_LMgr_ImgContainerBox_t* imageBox = NW_LMgr_ImgContainerBoxOf(box);
+        imageBox->isBroken = NW_TRUE;
+        }
+      else if( NW_Object_IsInstanceOf( box, &NW_FBox_ImageButtonBox_Class ) == NW_TRUE )
+        {
+        NW_LMgr_ImageButtonBox_ReplaceBrokenImage( box, image);
+        }
+      else
+        {
+        NW_THROW_UNEXPECTED( status );
+        }
+      }
+      if( NW_Object_IsInstanceOf( box, &NW_LMgr_AnimatedImageBox_Class ) == NW_TRUE ||
+        NW_Object_IsInstanceOf( box, &NW_FBox_ImageButtonBox_Class ) == NW_TRUE )
+        {
+  	    NW_LMgr_AnimatedImageAggregate_t* AnimatedImageAggregate = (NW_LMgr_AnimatedImageAggregate_t*)
+            NW_Object_QuerySecondary (box, &NW_LMgr_AnimatedImageAggregate_Class);
+  	    status = NW_LMgr_AnimatedImageAggregate_StartTimer (AnimatedImageAggregate); 
+        }
+      else
+        {
+        NW_THROW_UNEXPECTED( status );
+        }
+    // refresh the image box
+    NW_LMgr_Box_Refresh( box );
+    }
+  NW_CATCH( status )
+    {
+    }
+  NW_FINALLY
+    {
+    NW_LOG0(NW_LOG_LEVEL5, "_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDecoded END");
+    return;
+    }
+  NW_END_TRY
+  }
+
+
+/* ------------------------------------------------------------------------- */
+void
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_ImageDestroyed( NW_Image_IImageObserver_t* imageObserver,
+                                                                NW_Image_AbstractImage_t* abstractImage )
+  {
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+  NW_REQUIRED_PARAM( abstractImage );
+
+  /* parameter assertion block */
+  NW_ASSERT( imageObserver != NULL );
+  NW_ASSERT( abstractImage != NULL );
+  NW_ASSERT(NW_Object_IsInstanceOf( imageObserver,
+                                    &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+  /* obtain the implementer */
+  thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( imageObserver );
+  NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+
+  thisObj->image = NULL;
+}
+
+/* ------------------------------------------------------------------------- */
+NW_Bool
+_NW_ImageCH_Epoc32ContentHandler_IImageObserver_IsVisible( NW_Image_IImageObserver_t* aImageObserver)
+  {
+  NW_ImageCH_Epoc32ContentHandler_t* thisObj;
+
+  NW_ASSERT( aImageObserver != NULL );
+  NW_ASSERT(NW_Object_IsInstanceOf( aImageObserver,
+                                    &_NW_ImageCH_Epoc32_ImageObserver_Class ));
+
+  thisObj = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_Interface_GetImplementer( aImageObserver );
+  NW_ASSERT (NW_Object_IsInstanceOf( thisObj, &NW_ImageCH_Epoc32ContentHandler_Class ) );
+
+  NW_HED_DocumentRoot_t* docRoot = (NW_HED_DocumentRoot_t*)
+      NW_HED_DocumentNode_GetRootNode(NW_HED_DocumentNodeOf(thisObj));
+  NW_LMgr_RootBox_t* rootBox = NW_HED_DocumentRoot_GetRootBox(docRoot);
+
+  CGDIDeviceContext* deviceContext = NW_LMgr_RootBox_GetDeviceContext (rootBox);
+  const NW_GDI_Point2D_t* origin = deviceContext->Origin();
+  const NW_GDI_Dimension2D_t* displaySize = &(deviceContext->DisplayBounds()->dimension);
+
+  NW_HED_ContentHandler_t* contentHandler = NW_HED_ContentHandlerOf(thisObj);
+  NW_GDI_Rectangle_t bounds = NW_LMgr_Box_GetDisplayBounds( contentHandler->boxTree );
+  
+  NW_Bool isVisible = NW_TRUE;
+
+  // checking out of view only along the y direction
+  if ( ((origin->y + displaySize->height) < bounds.point.y) ||
+     (origin->y > (bounds.point.y + bounds.dimension.height)) )
+      {
+      isVisible = NW_FALSE;
+      }
+  return isVisible;
+}
+
+/* ------------------------------------------------------------------------- *
+   convenience functions
+ * ------------------------------------------------------------------------- */
+
+/************************************************************************
+
+  Function: NW_ImageCH_Epoc32ContentHandler_GetVirtualHandler
+
+  Description:  This method creates a new ImageContentHandler which is basically
+               a clone of the origins (imageCH) ImageContentHandler. So it makes
+               a virtual copy of the actual Image and sets it on the new ImageCH
+
+  Parameters: parent - The parent ContentHandler (XHTML/WML) of the new ImageCH,
+              urlRequest
+              imageCH - the Image Content Handler to be cloned
+
+  Return Value: The Content Handler containing the virtual image
+
+**************************************************************************/
+
+/* -------------------------------------------------------------------------*/
+TBrowserStatusCode
+NW_ImageCH_Epoc32ContentHandler_GetVirtualHandler( NW_HED_DocumentNode_t* parent,
+                                                   NW_HED_UrlRequest_t* urlRequest,
+                                                   NW_ImageCH_Epoc32ContentHandler_t* imageCH,
+                                                   NW_ImageCH_Epoc32ContentHandler_t** newVirtualImageCH )
+  {
+  NW_ImageCH_Epoc32ContentHandler_t* virtualImageCH = NULL;
+
+  NW_TRY( status ) 
+    {
+    NW_ASSERT( NW_HED_ContentHandlerOf( imageCH )->response != NULL );
+
+    virtualImageCH = (NW_ImageCH_Epoc32ContentHandler_t*)NW_Object_New( 
+      &NW_ImageCH_Epoc32ContentHandler_Class, parent, urlRequest, NW_FALSE, imageCH );
+    // OOM check
+    NW_THROW_OOM_ON_NULL( virtualImageCH, status );
+
+    // if the bitmap exists then take it as a virtual image
+    if( imageCH->image )
+      {
+      virtualImageCH->image = (NW_Image_AbstractImage_t*)NW_Image_Virtual_New( imageCH->image );
+      // OOM check
+      NW_THROW_OOM_ON_NULL( virtualImageCH->image, status );
+    
+      // add it to the top level content handler
+      status = NW_Image_Epoc32Simple_AddDocNode(NW_Image_Epoc32SimpleOf(imageCH->image),
+                                                NW_HED_DocumentNodeOf(virtualImageCH));
+      _NW_THROW_ON_ERROR( status );
+      
+      // observ the virtual image
+      status = NW_Image_AbstractImage_SetImageObserver( NW_Image_AbstractImageOf( virtualImageCH->image ),
+        &NW_ImageCH_Epoc32ContentHandlerOf( virtualImageCH )->NW_Image_IImageObserver );
+      NW_THROW_ON( KBrsrOutOfMemory, status );
+      // ignore observer errors -except OOM
+      status = KBrsrSuccess;
+      }
+    }
+  NW_CATCH( status )
+    {
+    // destroy the newly created virtual image handler
+    NW_Object_Delete( virtualImageCH );
+    virtualImageCH = NULL;
+    }
+  NW_FINALLY
+    {
+    *newVirtualImageCH = virtualImageCH;
+    return status;
+    }
+  NW_END_TRY
+  }
+
+/* -------------------------------------------------------------------------*/
+void
+NW_ImageCH_Epoc32ContentHandler_ForceImageOpen( NW_ImageCH_Epoc32ContentHandler_t* imageCH )
+  {
+  /* parameter assertion block */
+  NW_ASSERT( imageCH != NULL );
+  NW_ASSERT( imageCH->image != NULL );
+  NW_ASSERT(NW_Object_IsInstanceOf( imageCH->image,
+                                    &NW_Image_Epoc32Simple_Class ));
+
+  NW_Image_Epoc32Simple_t* simpleImage = NW_Image_Epoc32SimpleOf( imageCH->image );
+  CEpoc32ImageDecoder* decoder = STATIC_CAST( CEpoc32ImageDecoder*, simpleImage->decoder );
+  
+  TInt error = KErrNone;  
+  TRAP(error, decoder->Open())
+  }
+
+/* -------------------------------------------------------------------------*/
+NW_HED_ContentHandler_t*
+NW_ImageCH_Epoc32ContentHandler_NewBrokenImage (NW_HED_DocumentNode_t* parent,
+                                        NW_HED_UrlRequest_t* urlRequest,
+                                        TBrowserStatusCode error)
+{
+  return (NW_HED_ContentHandler_t*) NW_Object_New (&NW_ImageCH_Epoc32ContentHandler_Class,
+      parent, urlRequest, error);
+}