home *** CD-ROM | disk | FTP | other *** search
- /* -*- 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.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
- /*
- * 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);
- }
-
-