home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xibm.zip / apa16 / apa16Font.c < prev    next >
C/C++ Source or Header  |  1992-03-23  |  13KB  |  486 lines

  1. /***********************************************************
  2. Copyright 1991 by the Massachusetts Institute of Technology
  3.  
  4.                      All rights reserved.
  5.  
  6. Permission to use, copy, modify, and distribute this software and its
  7. documentation for any purpose and without fee is hereby granted,
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in
  10. supporting documentation, and that the name of the Massachusetts
  11. Institute of Technology (M.I.T.) not be used in advertising or publicity
  12. pertaining to distribution of the software without specific, written
  13. prior permission.
  14.  
  15. M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. #include "X.h"
  26. #include "Xproto.h"
  27. #include "region.h"
  28. #include "misc.h"
  29. #include "screenint.h"
  30. #include "dixfontstr.h"
  31.  
  32. #include "OScompiler.h"
  33.  
  34. #include "apa16Decls.h"
  35. #include "apa16Hdwr.h"
  36. #include "apa16Font.h"
  37.  
  38. #include "ibmTrace.h"
  39.  
  40. /* apa16 font cache:
  41.  
  42.    There are 4 areas of off-screen memory available for use as a font cache.
  43.    When a font is allocated, memory is allocated to hold the cache descriptor
  44.    but no off-screen memory is allocated.  The first call to apa16ValidateGC
  45.    causes apa16CacheFont to be called.  This allocates memory for the character
  46.    bitmap and metric pointers and calls get_glyphs to initialize them.
  47.  
  48.    The first time the font is used, apa16CacheFontRow is called to allocate
  49.    offscreen memory.  This may displace other fonts (there is a counter in
  50.    each font structure used for an LRU replacement).  Individual characters
  51.    are copied in as needed.
  52.  
  53.    There remains one problem: what to do if a the widths of the characters of
  54.    a font add to more than 1024.  Currently the remaining characters are not
  55.    cached.
  56.  
  57.    */
  58.  
  59. #ifndef NO_FUNCTION_PROTOTYPES
  60. static void apa16UncacheFontRow(apa16FontPtr, int);
  61. #else
  62. static void apa16UncacheFontRow();
  63. #endif
  64.  
  65. /* This variable is used to determine the least recently used cached font.
  66.    Each user of a cached font should assign
  67.      font->afCache[row]->referenced = ++apa16_fontcache_counter;
  68.  
  69.    */
  70.  
  71. int apa16_fontcache_counter;
  72.  
  73. static struct apa16FontCache *cache_head[4], font_regions[4];
  74.  
  75. void apa16InitFontCache()
  76. {
  77.  
  78.   TRACE(("apa16InitFontCache"));
  79.  
  80.   /* The code below never frees a font cache entry with a zero prev field;
  81.      it is easier to use the address of a static variable than to call
  82.      malloc and be prepared to handle failure.  */
  83.  
  84.   cache_head[0] = &font_regions[0];
  85.   cache_head[1] = &font_regions[1];
  86.   cache_head[2] = &font_regions[2];
  87.   cache_head[3] = &font_regions[3];
  88.  
  89.   font_regions[0].xorg = 0;
  90.   font_regions[1].xorg = 0;
  91.   font_regions[2].xorg = 0;
  92.   font_regions[3].xorg = MAXCURSORS * 2 * CURSOR_WIDTH;
  93.  
  94.   font_regions[0].yorg = 1009;
  95.   font_regions[1].yorg = 768;
  96.   font_regions[2].yorg = FONT_TOP;
  97.   font_regions[3].yorg = CURSOR_AREA_TOP;
  98.  
  99.   font_regions[0].w = 1023;
  100.   font_regions[1].w = 1023;
  101.   font_regions[2].w = 1023;
  102.   font_regions[3].w = STAGE_X_OFFSET - MAXCURSORS * 2 * CURSOR_WIDTH;
  103.  
  104.   font_regions[0].h = 15;
  105.   font_regions[1].h = 16;
  106.   font_regions[2].h = FONT_BOTTOM - FONT_TOP + 1;    /* 48 */
  107.   font_regions[3].h = 64;
  108.  
  109.   font_regions[0].prev = 0;
  110.   font_regions[1].prev = 0;
  111.   font_regions[2].prev = 0;
  112.   font_regions[3].prev = 0;
  113.  
  114.   font_regions[0].next = 0;
  115.   font_regions[1].next = 0;
  116.   font_regions[2].next = 0;
  117.   font_regions[3].next = 0;
  118.  
  119.   font_regions[0].used = 0;
  120.   font_regions[1].used = 0;
  121.   font_regions[2].used = 0;
  122.   font_regions[3].used = 0;
  123. }
  124.  
  125. Bool
  126. apa16RealizeFont(pScr, pFont)
  127. ScreenPtr pScr;
  128. register FontPtr pFont;
  129. {
  130.   apa16FontPtr pAF;
  131.  
  132.   TRACE(("apa16RealizeFont(%#x)", pFont));
  133.  
  134.   if (pFont->info.maxbounds.characterWidth > 32 ||
  135.       FONTMAXBOUNDS(pFont,ascent) + FONTMAXBOUNDS(pFont,descent) + 1 > 24 ||
  136.       pFont->info.minbounds.characterWidth < 0 ||
  137.       pFont->info.drawDirection != FontLeftToRight ||
  138. #ifndef ALLOW_16BIT
  139.       FONTLASTROW(pFont) > 1 || /* temporary restriction */
  140. #endif
  141.       (pAF = (apa16FontPtr)Xalloc(sizeof(apa16Font))) == NULL)
  142.     {
  143.       return mfbRealizeFont(pScr, pFont);
  144.     }
  145.   if (!FontSetPrivate(pFont, apa16FontPrivateIndex, (pointer)pAF))
  146.     {
  147.       Xfree(pAF);
  148.       return mfbRealizeFont(pScr, pFont);
  149.     }
  150.   TRACE(("\tcached\n"));
  151.   pAF->afFont   = pFont;
  152. #if 1
  153.   pAF->afHeight = FONTMAXBOUNDS(pFont,ascent) + FONTMAXBOUNDS(pFont,descent);
  154. #else
  155.   pAF->afHeight = FONTASCENT(pFont) + FONTDESCENT(pFont);
  156. #endif
  157.   pAF->afNChars = FONTLASTCOL(pFont) - FONTFIRSTCOL(pFont) + 1;
  158.   pAF->afNrows  = FONTLASTROW(pFont) + 1;
  159. #ifdef ALLOW_16BIT
  160.   if (pAF->afNrows > 1)
  161.     pAF->afNChars *= ((pFont->info.lastRow - pFont->info.firstRow)+1);
  162. #endif
  163.   pAF->afCache = NULL;
  164.   pAF->afDefChar = pFont->info.defaultCh + FONTFIRSTCOL(pFont);
  165.   if (pFont->info.constantWidth)
  166.     {
  167.       pAF->afDefWidth = pAF->afWidth = pFont->info.maxbounds.characterWidth;
  168.     }
  169.   else
  170.     {
  171.       pAF->afWidth = -1;
  172.       pAF->afDefWidth = -1;    /* CacheFont will set this */
  173.     }
  174.   return TRUE;
  175. }
  176.  
  177. Bool
  178. apa16UnrealizeFont(pScr, pFont)
  179. ScreenPtr pScr;
  180. FontPtr pFont;
  181. {
  182.   apa16FontPtr pAF = (apa16FontPtr)FontGetPrivate(pFont,apa16FontPrivateIndex);
  183.  
  184.   TRACE(("apa16UnrealizeFont(%#x) cache %#x rows %d\n", pFont, pAF,
  185.      pAF ? pAF->afNrows : 0));
  186.  
  187.   if (!pAF)
  188.     return mfbUnrealizeFont(pScr, pFont);
  189.   if (pAF->afCache)
  190.     {
  191.       int i;
  192.       for (i = pAF->afNrows - 1; i >= 0; i--)
  193.     apa16UncacheFontRow(pAF, i);
  194.       Xfree(pAF->afCache);
  195.     }
  196.   Xfree(pAF);
  197.   FontSetPrivate(pFont,apa16FontPrivateIndex,0);
  198.   return TRUE;
  199. }
  200.  
  201. /* There is a design flaw in the font library: it is not possible
  202.    to find out where the holes in a font are except by querying each
  203.    individual character.  */
  204. static void apa16SlowGetGlyphs(xfont, nchars, chars, cip)
  205. FontPtr xfont;
  206. int nchars;
  207. unsigned char *chars;
  208. CharInfoPtr *cip;
  209. {
  210.   int i;
  211.   for (i = 0; i < nchars; i++)
  212.     {
  213.       int n;
  214.       (*xfont->get_glyphs)(xfont, 1, chars++, Linear8Bit, &n, cip);
  215.       if (n != 1)
  216.     *cip = 0;
  217.       cip++;
  218.     }
  219. }
  220.  
  221. Bool
  222. apa16CacheFont(font)
  223. apa16FontPtr font;
  224. {
  225.   unsigned char allchars[256];
  226.   int i;
  227.   register apa16FontCache **fc;
  228.   register apa16FCCharInfo *ci;
  229.   FontPtr xfont = font->afFont;
  230.   int fontmin = FONTFIRSTCOL(xfont);
  231.   int fontmax = FONTLASTCOL(xfont);
  232.   int n;
  233.  
  234. #ifndef ALLOW_16BIT
  235.   if (font->afNrows > 1)
  236.     return FALSE;
  237. #endif
  238.  
  239.   /* If 16 bit fonts are allowed, multiply the malloc arg by the
  240.      number of rows. */
  241.   if ((fc = (apa16FontCache **)Xalloc(sizeof (apa16FontCache *))) == NULL)
  242.     return FALSE;
  243.   if ((ci = (apa16FCCharInfo *)Xalloc(sizeof (apa16FCCharInfo))) == NULL)
  244.     {
  245.       Xfree(fc);
  246.       return FALSE;
  247.     }
  248.   bzero(ci, sizeof(apa16FCCharInfo));
  249.   *fc = 0;
  250.   font->afCache = fc;
  251.   font->afChars = ci;
  252.   /* For now, assume 1 row (8 bit font). */
  253.   ci->cmin = fontmin;
  254.   ci->cmax = fontmax;
  255.   for (i = fontmin; i <= fontmax; i++)
  256.     allchars[i] = i;
  257.   (*xfont->get_glyphs)(xfont, fontmax - fontmin + 1,
  258.                allchars + fontmin, Linear8Bit,
  259.                &n, font->afChars[0].chars + fontmin);
  260.   if (n != fontmax - fontmin + 1)
  261.     apa16SlowGetGlyphs(xfont, fontmax - fontmin + 1, allchars + fontmin,
  262.                font->afChars[0].chars + fontmin);
  263.  
  264.   font->afDefWidth = font->afChars[0].chars[font->afDefChar]->metrics.characterWidth;
  265.   TRACE(("apa16CacheFont(%x), default width = %d\n", font, font->afDefWidth));
  266.   return TRUE;
  267. }
  268.  
  269. static apa16FontCache *
  270. apa16FreeFontRow(h)
  271. unsigned short h;
  272. {
  273.   register apa16FontCache *fc;
  274.   unsigned int age = -1;
  275.   apa16FontCache *oldest = 0;
  276.   int i;
  277.  
  278.   TRACE(("apa16FreeFontRow(%d)\n", h));
  279.  
  280.   for (i = 0; i < 4; i++)
  281.     {
  282.       fc = cache_head[i];
  283.       do
  284.     if (fc->used && fc->h >= h && fc->referenced < age)
  285.       {
  286.         oldest = fc;
  287.         age = fc->referenced;
  288.       }
  289.       while (fc = fc->next);
  290.     }
  291.   if (oldest == 0)
  292.     return 0;
  293.   /* free oldest */
  294.   oldest->owner->afCache[oldest->row] = 0;
  295.   oldest->owner->afChars[oldest->row].cached = 0;
  296.   oldest->used = 0;
  297.   /* debug */
  298.   oldest->owner = 0;
  299.   fc = oldest->next;
  300.   if (fc && fc->used == 0 && fc->xorg == oldest->xorg && fc->w == oldest->w)
  301.     {
  302.       /* note: the permanent struct is always first on the chain,
  303.      therefore fc is not permanent */
  304.       oldest->h += fc->h;
  305.       oldest->next = fc->next;
  306.       if (fc->next)
  307.     fc->next->prev = oldest;
  308.       Xfree(fc);
  309.     }
  310.   return oldest;
  311. }
  312.  
  313. static void
  314. apa16UncacheFontRow(font, row)
  315. apa16FontPtr font;
  316. int row;
  317. {
  318.   register apa16FontCache *fc = font->afCache[row], *tmpfc;
  319.  
  320.   TRACE(("apa16UncacheFontRow(%x, %d) fc = %x\n", font, row, fc));
  321.  
  322.   /* Even if a font is cached, a row of it may not be.
  323.      Check here to simplify callers.  */
  324.   if (fc == 0)
  325.     return;
  326.  
  327.   tmpfc = fc->next;
  328.  
  329.   /* Because the first font cache in each region can't be freed (it
  330.      is staticly allocated), when there are two adjacent free regions
  331.      join them by freeing the second one.  */
  332.  
  333.   if (tmpfc && tmpfc->used == 0 &&
  334.       tmpfc->xorg == fc->xorg && tmpfc->w == fc->w)
  335.     {
  336.       fc->h += tmpfc->h;
  337.       fc->next = tmpfc->next;
  338.       if (fc->next)
  339.     fc->next->prev = fc;
  340.       Xfree(tmpfc);
  341.     }
  342.  
  343.   tmpfc = fc->prev;
  344.  
  345.   if (tmpfc && tmpfc->used == 0 &&
  346.       tmpfc->xorg == fc->xorg && tmpfc->w == fc->w)
  347.     {
  348.       tmpfc->h += fc->h;
  349.       tmpfc->next = fc->next;
  350.       if (tmpfc->next)
  351.     tmpfc->next->prev = tmpfc;
  352.       Xfree(fc);
  353.       fc = tmpfc;
  354.     }
  355.   fc->used = 0;
  356.   fc->row = 0;
  357.   fc->owner = 0;
  358.  
  359.   font->afCache[row] = 0;
  360.   font->afChars[row].cached = 0;
  361.   return;
  362. }
  363.  
  364. /* Allocate a band of offscreen memory for a font. */
  365. Bool
  366. apa16CacheFontRow(font, row)
  367. apa16FontPtr font;
  368. int row;
  369. {
  370.   register apa16FontCache *fc;
  371.   apa16FontCache *tmp;
  372.   int i;
  373.   unsigned short cmd;
  374.   unsigned short h = font->afHeight;
  375.  
  376.   TRACE(("apa16CacheFontRow(%x,%d)\n",font,row))
  377.  
  378.   for (i = 0; i < 4; i++)
  379.     {
  380.       for (fc = cache_head[i]; fc; fc = fc->next)
  381.     if (!fc->used && fc->h >= h)
  382.       goto found;
  383.     }
  384.   /* Didn't find a free band.  Free the least recently used font row.  */
  385.   fc = apa16FreeFontRow(h);
  386.  
  387.  found:
  388.   if (fc == 0)
  389.     return 0;
  390.  
  391.   /* if band is more than 8 pixels larger than needed, split it */
  392.   if (fc->h > h + 8 &&
  393.       (tmp = (apa16FontCache *)Xalloc(sizeof(apa16FontCache))))
  394.     {
  395.       tmp->xorg = fc->xorg;
  396.       tmp->yorg = fc->yorg + h;
  397.       tmp->w = fc->w;
  398.       tmp->h = fc->h - h;
  399.       fc->h = h;
  400.       tmp->next = fc->next;
  401.       if (tmp->next)
  402.     tmp->next->prev = tmp;
  403.       fc->next = tmp;
  404.       tmp->prev = fc;
  405.       tmp->used = 0;
  406.     }
  407.  
  408.   fc->row = row;
  409.   fc->used = 1;
  410.   fc->referenced = 0;
  411.   fc->owner = font;
  412.  
  413.   font->afCache[row] = fc;
  414.   font->afChars[row].cached = 1;
  415.   font->afChars[row].x = fc->xorg;
  416.   font->afChars[row].xmax = fc->xorg + fc->w;
  417.   font->afChars[row].yorg = fc->yorg + h;
  418.   APA16_GET_CMD_FILL(RROP_BLACK,cmd);
  419.   FILL_RECT(cmd,fc->xorg + fc->w, fc->yorg + h, fc->w, h);
  420.   bzero(font->afChars[row].char_cached,
  421.     sizeof(font->afChars[row].char_cached));
  422.   return TRUE;
  423. }
  424.  
  425. /* Given a list of characters, copy them to the cache.
  426.  
  427.    Warning: this code only works for 8 bit fonts. */
  428.  
  429. Bool
  430. apa16CacheChars(font, str, len)
  431. apa16FontPtr font;
  432. unsigned char *str;
  433. unsigned int len;
  434. {
  435.  
  436.   TRACE(("apa16CacheChars(%x,%x,%d) %d x %d/%d range (%d,%d)\n",
  437.      font,str,len,*str,font->afChars->x, font->afChars->xmax,
  438.      font->afChars->cmin,font->afChars->cmax));
  439.   QUEUE_WAIT();
  440.   apa16Qmerge_mode_old = MERGE_WHITE;
  441.   MR = (MODE_SHADOW & MERGE_MODE_MASK) | MERGE_WHITE;
  442.  
  443.   while(len-- > 0)
  444.     {
  445.       unsigned int ndx = *str;
  446.       apa16FCCharInfo *fci;
  447.       unsigned short w;
  448.  
  449.       fci = font->afChars;    /* change this for 16 bit fonts */
  450.       str++;
  451.  
  452.       if (fci->chars[ndx] == 0)
  453.     fci->char_cached[ndx] = 1;
  454.  
  455.       if (fci->char_cached[ndx])
  456.     continue;
  457.  
  458.       w = GLYPHWIDTHPIXELS(fci->chars[ndx]);
  459.  
  460.       if (fci->x + w > fci->xmax)
  461.     {
  462.       ErrorF("apa16CacheChars: out of space\n");
  463.       return FALSE;
  464.     }
  465.       fci->x += w;
  466.       fci->xorg[ndx] = fci->x;
  467.       fci->char_cached[ndx] = 1;
  468.       apa16PutGlyph(fci->xorg[ndx], fci->yorg, fci->chars[ndx],
  469.             FONTMAXBOUNDS(font->afFont,descent));
  470.     }
  471.   apa16Qmerge_mode_old = MERGE_COPY;
  472.   MR = MR_DEFAULT;
  473.   return TRUE;
  474. }
  475.  
  476. #ifdef DEBUG
  477. copy_font_area()
  478. {
  479.     unsigned cmd;
  480.  
  481.     APA16_GET_CMD(ROP_RECT_COPY,GXcopy,cmd);
  482.     COPY_RECT(cmd,1023,750,
  483.               1023,1023,1023,1023-768);
  484. }
  485. #endif
  486.