435 lines
9.6 KiB
C++
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);
|
|
}
|
|
|