dmose%mozilla.org 0efb7c174c updated xPL license boilerplate to v1.1, a=chofmann@netscape.com,r=endico@mozilla.org
git-svn-id: svn://10.0.0.236/trunk@52910 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 03:43:54 +00:00

435 lines
9.6 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* f.cpp (FontObject.cpp)
*
* C++ implementation of the (f) FontObject
*
* dp Suresh <dp@netscape.com>
*/
#include "f.h"
#include "nf.h"
FontObject::
FontObject(struct nff *f, struct nfrc *irc, const char *url)
: self(f), inGC(0), wfList(free_fh_store), iswebfont(0), state(NF_FONT_COMPLETE), shared(1)
{
m_rcMajorType = nfrc_GetMajorType(irc, NULL);
m_rcMinorType = nfrc_GetMinorType(irc, NULL);
urlOfFont = CopyString(url);
if (urlOfFont && *urlOfFont)
{
// Webfont
iswebfont = 1;
state = NF_FONT_INCOMPLETE;
}
}
FontObject::
~FontObject()
{
if (urlOfFont) delete (char *)urlOfFont;
}
jdouble * FontObject::
EnumerateSizes(struct nfrc *rc)
{
wfListElement *tmp = head;
jdouble *ret = NULL;
int max_ret_len = 0;
for (; tmp; tmp = tmp->next)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
computeSizes(rc, ele);
jdouble *sizes = ele->sizesList.getSizes();
if (sizes)
{
MergeSizes(ret, max_ret_len, sizes);
}
}
return (ret);
}
/*ARGSUSED*/
struct nfrf * FontObject::
GetRenderableFont(struct nfrc *rc, jdouble pointsize)
{
struct nfrf * rf = NULL;
wfListElement *tmp = head;
int onlyOne = (head == tail);
if (!onlyOne)
{
WF_TRACEMSG(("NF: More than one displayer handling font 0x%x.", self));
}
// Sanity check to make sure that the rc is of the same type
if (!nfrc_IsEquivalent(rc, m_rcMajorType, m_rcMinorType, NULL))
{
// Invalid rc.
return NULL;
}
for (; tmp; tmp = tmp->next)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
// Get any cached rf.
rf = ele->sizesList.getRf(pointsize);
if (rf)
{
// Increment the refcount of the cached rf.
WF_TRACEMSG(("NF: Found rf %x (f = 0x%x, pointsize = %6.2f) in cache.",
rf, self, pointsize));
nfrf_addRef(rf, NULL);
break;
}
// Try to get a new rf.
// The right way to do this is to check with the list of enumerated
// sizes to see if the displayer does support this size. We will
// however, ask the displayer anyway if there was only one
// displayer that handled this font.
if (!onlyOne)
{
computeSizes(rc, ele);
if (!ele->sizesList.supportsSize(pointsize))
{
// point size not supported by this displayer. Try next....
continue;
}
}
rf = ele->fppeer->CreateRenderableFont(rc, ele->fh, pointsize);
if (!rf)
{
// That displayer lied about the sizes it can handle.
// Remove the size from the sizes list.
ele->sizesList.removeSize(pointsize);
}
else
{
WF_TRACEMSG(("NF: Created new rf %x (f = 0x%x, pointsize = %6.2f) from displayer %s.",
rf, self, pointsize, ele->fppeer->name()));
// Cache this rf.
int ret = ele->sizesList.addRf(rf);
//
// if ret < 0, then we ran out of memory
// This is very bad because we are now having the
// fh refcount the nff. And the fh would need to know
// exactly how many rf's were created with it. If an
// rf was created but not added to the sizesList, then
// the fh will be deleted one too soon causing access of
// deleted object when the final RfDone() happens.
break;
}
}
return(rf);
}
struct nffmi *
FontObject::GetMatchInfo(struct nfrc *rc, jdouble pointsize)
{
struct nffmi *fmi = NULL;
wfListElement *tmp = head;
for (; tmp; tmp = tmp->next)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
computeSizes(rc, ele);
if (ele->sizesList.supportsSize(pointsize))
{
// Get the fh corresponding to this fontdisplayer
fmi = ele->fppeer->GetMatchInfo(ele->fh);
if (!fmi)
{
// That displayer lied about the sizes it can handle.
// Remove the size from the sizes list.
ele->sizesList.removeSize(pointsize);
}
else
{
break;
}
}
}
return (fmi);
}
jint
FontObject::GetRcMajorType()
{
return (m_rcMajorType);
}
jint
FontObject::GetRcMinorType()
{
return (m_rcMinorType);
}
int
FontObject::isShared(void)
{
return (shared);
}
int
FontObject::setShared(int sharedState)
{
shared = sharedState;
return (0);
}
//
// FontBroker specific
//
int FontObject::
addFontHandle(FontDisplayerPeerObject *fppeer, void *fh)
{
struct fh_store *ele = new fh_store;
if (!ele) {
// No memory.
return (-1);
}
ele->fppeer = fppeer;
ele->fh = fh;
add((void *)ele);
// Tell wffpPeer that we created a fh
fppeer->FontHandleCreated(fh);
//
// We will have the fonthandle refcount the Font too.
// A font should not be deleted until all its fonthandles
// are deleted.
//
nff_addRef(self, NULL);
// If the displayer is a non-native displayer
// (The correct condition is if this is webfont)
// then disable shared
if (!fppeer->isNative())
{
setShared(0);
}
return (0);
}
int FontObject::
isRfExist(struct nfrf *rf)
{
wfListElement *tmp = head;
int nrf;
for (; tmp; tmp = tmp->next)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
nrf = ele->sizesList.isRfExist(rf);
if (nrf > 0)
{
break;
}
}
return (nrf);
}
int
FontObject::releaseRf(struct nfrf *rf)
{
wfListElement *tmp = head;
int ret = 0;
for (; tmp; tmp = tmp->next)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
ret += ele->sizesList.removeRf(rf);
}
return (ret);
}
int
FontObject::isWebFont()
{
return (iswebfont);
}
const char *
FontObject::url()
{
return (urlOfFont);
}
int
FontObject::GetState()
{
return (state);
}
int
FontObject::setState(int completion_state)
{
int old_state = state;
state = completion_state;
return (old_state);
}
#include "Pcf.h"
//
// The Font garbage Collector.
//
// A FontHandle can be released when there are no consumers using this
// FontObject and there are no rf's active. This is given by the expression
// [referenceCount(FONT) - fonthandleCount(FONT)]
// + rfcount(FONT.sizesList) == 0
// referenceCount(FONT) is got from looking into the nff* jmc object
// fonthandleCount(FONT) is got by count()
//
// A FontObject can be destroyed only when there are no fonthandles
// in the FontObject. This is given by the expression:
// fonthandleCount(FONT) == 0
//
// This will return ZERO, if the Font can be deleted. If not, it
// will return NONZERO.
//
int FontObject::
GC()
{
// Prevent the GC from calling itself. This will happen when fonthandles
// are removed. Since each of the list element refcounts the Font, everytime
// an element it removed, its freeItem() will Font::release().
// The below will prevent the GC from stepping over itself.
if (inGC)
{
return(-1);
}
inGC++;
wfListElement *tmp = head;
cfImplHeader* impl = (cfImplHeader*)cf2cfImpl(self);
int nconsumers = impl->refcount - count();
// At this point, we will increment the refcount by 1. This is because
// removing an fh could cause the refcount to goto zero and that would
// cause the FontObject that we are working with to be deleted from
// underneath us. To prevent this, **AFTER COMPUTING nconsumers** we
// increment the refcount.
impl->refcount++;
while(tmp)
{
struct fh_store *ele = (struct fh_store *)tmp->item;
//
// WARNING: we could be possibly removing this element.
// Store the next element we should visit ahead of time.
//
tmp = tmp->next;
if (nconsumers + ele->sizesList.getRfCount() == 0)
{
// This fonthandle is a candidate for deletion.
remove(ele);
}
}
// Undo the dummy incrementing of refcount we did to protect ourself.
// NOTE: we cannot use nff_release() as that would go and delete the
// object. Callers of the GC are smart enough to check the return value
// of GC or look at the refcount and delete the object.
impl->refcount--;
inGC --;
return (impl->refcount);
}
//
// Private method implementations.
//
void FontObject::
computeSizes(struct nfrc *rc, struct fh_store *ele)
{
#if defined(XP_WIN) && !defined(WIN32) && !defined(XP_OS2)
/* Win 16 core dumps on enumerating. HACK HACK HACK */
return;
#else
if (!ele->sizesList.initialized())
{
// Sizes was never computed for this
WF_TRACEMSG(("NF: Computing sizes supported by font 0x%x by displayer %s.\n",
self, ele->fppeer->name()));
jdouble *sizes = ele->fppeer->EnumerateSizes(rc, ele->fh);
ele->sizesList.addSizes(sizes);
}
#endif
}
//
// Other functions
//
void
free_fh_store(wfList *object, void *item)
{
// We know that the wfList is actually a FontObject
// because FontObject is the superclass and wfList is the
// base class.
//
// Hence this is ok.
FontObject *fob = (FontObject *)object;
struct fh_store *ele = (struct fh_store *)item;
// Tell the wffpPeer that we are done with the the fonthandle
// The wffpPeer will take decisions of unloading the displayer
// DLM on this call.
ele->fppeer->FontHandleDone(ele->fh);
delete(ele);
//
// We will have the fonthandle refcount the Font too. So
// deletion of a fontHandle will decrement the refcount of Font.
// A font should not be deleted until all its fonthandles
// are deleted.
//
nff_release(fob->self, NULL);
}