int
wfFontObjectCache::releaseRf(struct nfrf *rf)
{
#ifdef DEBUG
	WF_TRACEMSG( ("NF: Deleting rf (0x%x).", rf) );
#endif /* DEBUG */

	struct wfListElement *tmp = head;
	int nrelease = 0;
    while(tmp)
	{
		struct font_store *ele = (struct font_store *) tmp->item;

		// We know that this Font object was created by us. So we can
		// snoop into its implementation to call implementation specific
		// methods.
		cfImpl *oimpl = cf2cfImpl(ele->f);
		FontObject *fob = (FontObject *)oimpl->object;

		//
		// WARNING: Before calling FontObject::releaseRf we need to get the
		// next item in the list. This is because the FontObject could turn
		// around and decide to remove itself from our list.
		//
		tmp = tmp->next;
		int n = fob->releaseRf(rf);
		if (n)
		{
			// Run the garbage collector since some rf was released. This
			// could even cause the font object to be deleted.
			if (!fob->GC())
			{
				struct nff *f_to_delete = (struct nff *) ele->f;

				// Delete the FontObject. Deleting the FontObject will turn
				// around and delete the element in the fontObjectCache list
				// by calling FontObjectCache::releaseFont().
				//
				// So DONT REMOVE THE ELEMENT. It will be removed.
				// wfList::remove(ele);

				nff_addRef(f_to_delete, NULL);
				nff_release(f_to_delete, NULL);
			}
		}
		nrelease += n;
	}

	if (nrelease)
	{
		// Some font had this rf. It is not possbile then for the same rf
		// exist with webfonts. Skip looking into the webfonts.
		return(nrelease);
	}
	return (nrelease);
}
// this function allocate space, the destructor for m_pRenderableFont,
// need to free the space.
int	CyaFont::CreateNetscapeFontWithFMI(
	MWContext *pContext,
	HDC hDC, struct nffmi *pWantedFmi, double fontHeight )
{
	struct nff      *genericFontHandle;

	if( m_pRenderableFont != NULL )
        nfrf_release( m_pRenderableFont, NULL);
    m_pRenderableFont = NULL;
	
	if( UpdateDisplayRC( hDC ) ) 
		return(1);			// error

  	// Create a FMI for the font of interest 
    // Not really used by Displayer, because it has hardcoded the font and don't do any matching.
	
	if (pWantedFmi == NULL)
		return( FONTERR_CreateFontMatchInfoFailed );
	
	/* Find the url that is loading this font */
    const char *accessing_url_str = NULL;
	if( pContext ) {
		History_entry *he = SHIST_GetCurrent(&(pContext->hist));
		if( he )
			accessing_url_str = he->address;
	}

	// Look for a font 
	genericFontHandle = nffbc_LookupFont(
		   theGlobalNSFont.getFontBrokerConsumerInterface(), 
		   m_displayRC,
		   pWantedFmi,
		   accessing_url_str, /* XXX GetContext()->url */
		   NULL /* exception */);

	if (genericFontHandle == NULL) {
		// failed
		theGlobalNSFont.LookupFailed( pContext, m_displayRC, pWantedFmi);
		return( FONTERR_nffbc_LookupFontFailed );

	}

	if( fontHeight < 0 )
		fontHeight = - fontHeight;		// webfont use positive size, see winfp.cpp

	/* Create a rendering font */
	m_pRenderableFont = nff_GetRenderableFont( genericFontHandle, m_displayRC, fontHeight, NULL /* exception */);
	
    // clean up 
    nff_release( genericFontHandle , NULL );


    return( FONTERR_OK );
}   // int	CyaFont::CreateNetscapeFontWithFMI( HDC hDC )
static void
wf_ReleaseStreamData(struct stream_data *data)
{
	nffbc_release(data->fbc, NULL);

	// Release stream and tell the wffpPeer about it
	data->fpPeer->StreamDone(data->fpStream);
	nfstrm_release(data->fpStream, NULL);

	nfdoer_release(data->observer, NULL);
	nff_release(data->f, NULL);

	delete data;
	return;
}
//
// Font stream handler.
// This will be called by netlib to when a stream of type FO_FONT
// is available.
//
extern "C" NET_StreamClass*
/*ARGSUSED*/
wfNewStream(FO_Present_Types format_out, void* client_data,
			URL_Struct* urls, MWContext* cx)
{
	struct nffbc *fbc = (struct nffbc *) client_data;
	struct wf_new_stream_data *inData =
		(struct wf_new_stream_data *) urls->fe_data;
	cfbImpl *oimpl = cfb2cfbImpl(fbc);
	FontBrokerObject *fbobj = (FontBrokerObject *)oimpl->object;
	
	const char *mimetype = fbobj->GetMimetype(urls->content_type, urls->address);

	if (!mimetype || !*mimetype)
	{
		return (NULL);
	}

	WF_TRACEMSG(("NF: Looking for mimetype: %s.", mimetype));

	NET_StreamClass *netStream = NULL;
	
	// Find which font Displayer implements the mimetype
	struct wfListElement *tmp = fbobj->fpPeers.head;
	for(; tmp; tmp = tmp->next)
	{
		FontDisplayerPeerObject *fpp = (FontDisplayerPeerObject *) tmp->item;
		if (fpp->isMimetypeEnabled(mimetype) > 0)
		{
			// Get the font Displayer stream handle
			WF_TRACEMSG(("NF: fppeer %s supports mimetype %s.", fpp->name(),
				mimetype));
			struct nfstrm *fpStream = fpp->CreateFontStreamHandler(inData->rc, inData->url_of_page);
			if (!fpStream)
			{
				// Error. Cannot create stream from Font Displayer.
				// We will cycle through other Displayers to see if we can
				// find any other font Displayer who can service us.
				WF_TRACEMSG(("NF: fppeer %s cannot create fpStream. "
					"Continuing...", fpp->name()));
				fpp = NULL;
				continue;
			}

			// Create a libnet stream
			netStream = (NET_StreamClass *) WF_ALLOC(sizeof(NET_StreamClass));
			if (!netStream)
			{
				// Error. No point continuing.
				WF_TRACEMSG(("NF: Error: Cannot create net stream. No memory."));
				nfstrm_release(fpStream, NULL);
				break;
			}

			// Create our stream data object
			struct stream_data *wfStream = new stream_data;
			if (!wfStream)
			{
				WF_TRACEMSG(("NF: Error: No memory to allocate stream_data."));
				nfstrm_release(fpStream, NULL);
				delete netStream;
				netStream = NULL;
				break;
			}

			// Fill our stream data
			wfStream->urls = urls;

			nffbc_addRef(fbc, NULL);
			wfStream->fbc = fbc;

			// fpstream was created here. So no need to addref it as
			// the creation process would already have incremented the
			// refcount.
			//nfstrm_addRef(fpStream, NULL);
			wfStream->fpStream = fpStream;

			// Tell the wffpPeer about this new stream
			fpp->StreamCreated(fpStream);

			nfdoer_addRef(inData->observer, NULL);
			wfStream->observer = inData->observer;

			nff_addRef(inData->f, NULL);
			wfStream->f = inData->f;

			wfStream->fpPeer = fpp;

			// Fill libnet stream
			netStream->name = "Font Broker";
			netStream->abort = wfAbort;
			netStream->complete = wfComplete;
			netStream->put_block = (MKStreamWriteFunc)wfWrite;
			netStream->is_write_ready = wfWriteReady;
			netStream->data_object = (void *)wfStream;
			netStream->window_id = cx;
			break;
		}
	}

	// Cleanup our wf_new_stream_data that was passed in
	nfdoer_release(inData->observer, NULL);
	nff_release(inData->f, NULL);
	nfrc_release(inData->rc, NULL);
	if (inData->url_of_page)
	{
		delete inData->url_of_page;
		inData->url_of_page = NULL;
	}
	delete inData;

	return (netStream);
}