home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / libfont / src / f.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.9 KB  |  431 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.  * f.cpp (FontObject.cpp)
  20.  *
  21.  * C++ implementation of the (f) FontObject
  22.  *
  23.  * dp Suresh <dp@netscape.com>
  24.  */
  25.  
  26.  
  27. #include "f.h"
  28. #include "nf.h"
  29.  
  30.  
  31. FontObject::
  32. FontObject(struct nff *f, struct nfrc *irc, const char *url)
  33.            : self(f), inGC(0), wfList(free_fh_store), iswebfont(0), state(NF_FONT_COMPLETE), shared(1)
  34. {
  35.     m_rcMajorType = nfrc_GetMajorType(irc, NULL);
  36.     m_rcMinorType = nfrc_GetMinorType(irc, NULL);
  37.     urlOfFont = CopyString(url);
  38.     if (urlOfFont && *urlOfFont)
  39.     {
  40.         // Webfont
  41.         iswebfont = 1;
  42.         state = NF_FONT_INCOMPLETE;
  43.     }
  44. }
  45.  
  46. FontObject::
  47. ~FontObject()
  48. {
  49.     if (urlOfFont) delete (char *)urlOfFont;
  50. }
  51.  
  52.  
  53. jdouble * FontObject::
  54. EnumerateSizes(struct nfrc *rc)
  55. {
  56.     wfListElement *tmp = head;
  57.     jdouble *ret = NULL;
  58.     int max_ret_len = 0;
  59.  
  60.     for (; tmp; tmp = tmp->next)
  61.       {
  62.         struct fh_store *ele = (struct fh_store *)tmp->item;
  63.         
  64.         computeSizes(rc, ele);
  65.         jdouble *sizes = ele->sizesList.getSizes();
  66.         if (sizes)
  67.         {
  68.             MergeSizes(ret, max_ret_len, sizes);
  69.         }
  70.     }
  71.     return (ret);
  72. }
  73.  
  74. /*ARGSUSED*/
  75. struct nfrf * FontObject::
  76. GetRenderableFont(struct nfrc *rc, jdouble pointsize)
  77. {
  78.     struct nfrf * rf = NULL;
  79.     wfListElement *tmp = head;
  80.     int onlyOne = (head == tail);
  81.  
  82.     if (!onlyOne)
  83.     {
  84.         WF_TRACEMSG(("NF: More than one displayer handling font 0x%x.", self));
  85.     }
  86.  
  87.     // Sanity check to make sure that the rc is of the same type
  88.     if (!nfrc_IsEquivalent(rc, m_rcMajorType, m_rcMinorType, NULL))
  89.     {
  90.         // Invalid rc.
  91.         return NULL;
  92.     }
  93.  
  94.     for (; tmp; tmp = tmp->next)
  95.     {
  96.         struct fh_store *ele = (struct fh_store *)tmp->item;
  97.  
  98.         // Get any cached rf.
  99.         rf = ele->sizesList.getRf(pointsize);
  100.         if (rf)
  101.         {
  102.             // Increment the refcount of the cached rf.
  103.             WF_TRACEMSG(("NF: Found rf %x (f = 0x%x, pointsize = %6.2f) in cache.",
  104.                 rf, self, pointsize));
  105.             nfrf_addRef(rf, NULL);
  106.             break;
  107.         }
  108.  
  109.         // Try to get a new rf.
  110.         // The right way to do this is to check with the list of enumerated
  111.         // sizes to see if the displayer does support this size. We will
  112.         // however, ask the displayer anyway if there was only one
  113.         // displayer that handled this font.
  114.         if (!onlyOne)
  115.         {
  116.             computeSizes(rc, ele);
  117.             if (!ele->sizesList.supportsSize(pointsize))
  118.             {
  119.                 // point size not supported by this displayer. Try next....
  120.                 continue;
  121.             }
  122.         }
  123.         rf = ele->fppeer->CreateRenderableFont(rc, ele->fh, pointsize);
  124.         if (!rf)
  125.         {
  126.             // That displayer lied about the sizes it can handle.
  127.             // Remove the size from the sizes list.
  128.             ele->sizesList.removeSize(pointsize);
  129.         }
  130.         else
  131.         {
  132.             WF_TRACEMSG(("NF: Created new rf %x (f = 0x%x, pointsize = %6.2f) from displayer %s.",
  133.                 rf, self, pointsize, ele->fppeer->name()));
  134.             
  135.             // Cache this rf.
  136.             int ret = ele->sizesList.addRf(rf);
  137.             //
  138.             // if ret < 0, then we ran out of memory
  139.             // This is very bad because we are now having the
  140.             // fh refcount the nff. And the fh would need to know
  141.             // exactly how many rf's were created with it. If an
  142.             // rf was created but not added to the sizesList, then
  143.             // the fh will be deleted one too soon causing access of
  144.             // deleted object when the final RfDone() happens.
  145.             break;
  146.         }
  147.     }
  148.     return(rf);
  149. }
  150. struct nffmi *
  151. FontObject::GetMatchInfo(struct nfrc *rc, jdouble pointsize)
  152. {
  153.     struct nffmi *fmi = NULL;
  154.     wfListElement *tmp = head;
  155.  
  156.     for (; tmp; tmp = tmp->next)
  157.       {
  158.         struct fh_store *ele = (struct fh_store *)tmp->item;
  159.         computeSizes(rc, ele);
  160.  
  161.         if (ele->sizesList.supportsSize(pointsize))
  162.           {
  163.             // Get the fh corresponding to this fontdisplayer
  164.             fmi = ele->fppeer->GetMatchInfo(ele->fh);
  165.  
  166.             if (!fmi)
  167.               {
  168.                 // That displayer lied about the sizes it can handle.
  169.                 // Remove the size from the sizes list.
  170.                 ele->sizesList.removeSize(pointsize);
  171.               }
  172.             else
  173.               {
  174.                 break;
  175.               }
  176.           }
  177.       }
  178.     return (fmi);
  179. }
  180.  
  181. jint
  182. FontObject::GetRcMajorType()
  183. {
  184.     return (m_rcMajorType);
  185. }
  186.  
  187. jint
  188. FontObject::GetRcMinorType()
  189. {
  190.     return (m_rcMinorType);
  191. }
  192.  
  193.  
  194. int
  195. FontObject::isShared(void)
  196. {
  197.     return (shared);
  198. }
  199.  
  200. int
  201. FontObject::setShared(int sharedState)
  202. {
  203.     shared = sharedState;
  204.     return (0);
  205. }
  206.  
  207.  
  208. //
  209. // FontBroker specific
  210. //
  211.  
  212. int FontObject::
  213. addFontHandle(FontDisplayerPeerObject *fppeer, void *fh)
  214. {
  215.     struct fh_store *ele = new fh_store;
  216.     if (!ele) {
  217.         // No memory.
  218.         return (-1);
  219.     }
  220.     ele->fppeer = fppeer;
  221.     ele->fh = fh;
  222.     add((void *)ele);
  223.  
  224.     // Tell wffpPeer that we created a fh
  225.     fppeer->FontHandleCreated(fh);
  226.  
  227.     //
  228.     // We will have the fonthandle refcount the Font too.
  229.     // A font should not be deleted until all its fonthandles
  230.     // are deleted.
  231.     //
  232.     nff_addRef(self, NULL);
  233.  
  234.     // If the displayer is a non-native displayer
  235.     // (The correct condition is if this is webfont)
  236.     // then disable shared
  237.     if (!fppeer->isNative())
  238.     {
  239.         setShared(0);
  240.     }
  241.     
  242.     return (0);
  243. }
  244.  
  245.  
  246. int FontObject::
  247. isRfExist(struct nfrf *rf)
  248. {
  249.     wfListElement *tmp = head;
  250.     int nrf;
  251.  
  252.     for (; tmp; tmp = tmp->next)
  253.       {
  254.         struct fh_store *ele = (struct fh_store *)tmp->item;
  255.         nrf = ele->sizesList.isRfExist(rf);
  256.         if (nrf > 0)
  257.           {
  258.             break;
  259.           }
  260.       }
  261.     return (nrf);
  262. }
  263.  
  264. int
  265. FontObject::releaseRf(struct nfrf *rf)
  266. {
  267.     wfListElement *tmp = head;
  268.     int ret = 0;
  269.  
  270.     for (; tmp; tmp = tmp->next)
  271.       {
  272.         struct fh_store *ele = (struct fh_store *)tmp->item;
  273.         ret += ele->sizesList.removeRf(rf);
  274.       }
  275.  
  276.     return (ret);
  277. }
  278.  
  279. int
  280. FontObject::isWebFont()
  281. {
  282.     return (iswebfont);
  283. }
  284.  
  285. const char *
  286. FontObject::url()
  287. {
  288.     return (urlOfFont);
  289. }
  290.  
  291.  
  292. int
  293. FontObject::GetState()
  294. {
  295.     return (state);
  296. }
  297.  
  298.  
  299. int
  300. FontObject::setState(int completion_state)
  301. {
  302.     int old_state = state;
  303.     state = completion_state;
  304.     return (old_state);
  305. }
  306.  
  307.  
  308.  
  309. #include "Pcf.h"
  310. //
  311. // The Font garbage Collector.
  312. //
  313. // A FontHandle can be released when there are no consumers using this
  314. // FontObject and there are no rf's active. This is given by the expression
  315. //        [referenceCount(FONT) - fonthandleCount(FONT)]
  316. //                + rfcount(FONT.sizesList)                == 0
  317. // referenceCount(FONT) is got from looking into the nff* jmc object
  318. // fonthandleCount(FONT) is got by count()
  319. //
  320. // A FontObject can be destroyed only when there are no fonthandles
  321. // in the FontObject. This is given by the expression:
  322. //        fonthandleCount(FONT) == 0
  323. //
  324. // This will return ZERO, if the Font can be deleted. If not, it
  325. // will return NONZERO.
  326. //
  327. int FontObject::
  328. GC()
  329. {
  330.     // Prevent the GC from calling itself. This will happen when fonthandles
  331.     // are removed. Since each of the list element refcounts the Font, everytime
  332.     // an element it removed, its freeItem() will Font::release().
  333.     // The below will prevent the GC from stepping over itself.
  334.     if (inGC)
  335.     {
  336.         return(-1);
  337.     }
  338.     inGC++;
  339.  
  340.     wfListElement *tmp = head;
  341.  
  342.     cfImplHeader* impl = (cfImplHeader*)cf2cfImpl(self);
  343.     int nconsumers = impl->refcount - count();
  344.  
  345.     // At this point, we will increment the refcount by 1. This is because
  346.     // removing an fh could cause the refcount to goto zero and that would
  347.     // cause the FontObject that we are working with to be deleted from
  348.     // underneath us. To prevent this, **AFTER COMPUTING nconsumers** we
  349.     // increment the refcount.
  350.     impl->refcount++;
  351.  
  352.     while(tmp)
  353.     {
  354.         struct fh_store *ele = (struct fh_store *)tmp->item;
  355.         //
  356.         // WARNING: we could be possibly removing this element.
  357.         // Store the next element we should visit ahead of time.
  358.         //
  359.         tmp = tmp->next;
  360.  
  361.         if (nconsumers + ele->sizesList.getRfCount() == 0)
  362.         {
  363.             // This fonthandle is a candidate for deletion.
  364.             remove(ele);
  365.         }
  366.     }
  367.  
  368.     // Undo the dummy incrementing of refcount we did to protect ourself.
  369.     // NOTE: we cannot use nff_release() as that would go and delete the
  370.     // object. Callers of the GC are smart enough to check the return value
  371.     // of GC or look at the refcount and delete the object.
  372.     impl->refcount--;
  373.  
  374.     inGC --;
  375.     return (impl->refcount);
  376. }
  377.  
  378. //
  379. // Private method implementations.
  380. //
  381.  
  382. void FontObject::
  383. computeSizes(struct nfrc *rc, struct fh_store *ele)
  384. {
  385. #if defined(XP_WIN) && !defined(WIN32) && !defined(XP_OS2)
  386.     /* Win 16 core dumps on  enumerating. HACK HACK HACK */
  387.     return;
  388. #else
  389.     if (!ele->sizesList.initialized())
  390.       {
  391.         // Sizes was never computed for this
  392.         WF_TRACEMSG(("NF: Computing sizes supported by font 0x%x by displayer %s.\n",
  393.             self, ele->fppeer->name()));
  394.         jdouble *sizes = ele->fppeer->EnumerateSizes(rc, ele->fh);
  395.         ele->sizesList.addSizes(sizes);
  396.       }
  397. #endif
  398. }
  399.  
  400. //
  401. // Other functions
  402. //
  403. void
  404. free_fh_store(wfList *object, void *item)
  405. {
  406.     // We know that the wfList is actually a FontObject
  407.     // because FontObject is the superclass and wfList is the
  408.     // base class.
  409.     //
  410.     // Hence this is ok.
  411.     FontObject *fob = (FontObject *)object;
  412.     struct fh_store *ele = (struct fh_store *)item;
  413.  
  414.     // Tell the wffpPeer that we are done with the the fonthandle
  415.     // The wffpPeer will take decisions of unloading the displayer
  416.     // DLM on this call.
  417.     ele->fppeer->FontHandleDone(ele->fh);
  418.  
  419.  
  420.     delete(ele);
  421.  
  422.     //
  423.     // We will have the fonthandle refcount the Font too. So
  424.     // deletion of a fontHandle will decrement the refcount of Font.
  425.     // A font should not be deleted until all its fonthandles
  426.     // are deleted.
  427.     //
  428.     nff_release(fob->self, NULL);
  429. }
  430.  
  431.