--- /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);
+}