home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / writeflash / !MakeFlash / c / fonttext < prev    next >
Text File  |  2000-04-23  |  13KB  |  487 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. //
  5. #include "proto.h"
  6. #include "bucket.h"
  7. #include "bitcount.h"
  8. #include "matrix.h"
  9. #include "rectangle.h"
  10. #include "main.h"
  11. #include "bbox.h"
  12. #include "flash.h"
  13. #include "fonttext.h"
  14. #include "preprocess.h"
  15.  
  16. #define MAXFONTS              64
  17.  
  18.  
  19. static int fontcount = 0;
  20. static FONT *fontlist[MAXFONTS+1];
  21.  
  22. static int glyph_index(FONT *font, U8 letter, int *write);
  23. static int is_glyph_used(FONT *font, U8 glyph);
  24.  
  25.  
  26. int add_glyph_shape(GLYPH *glyph, GLYPHSHAPE *shape) {
  27.  
  28.   if (!glyph->shapes) {
  29.     glyph->shapes = malloc(sizeof(GLYPHSHAPE));
  30.     if (!glyph->shapes) {
  31.       fprintf(stderr, "No room\n");
  32.       return 1;
  33.     }
  34.     glyph->shapecount = 0;
  35.  
  36.   } else {
  37.     GLYPHSHAPE *newshapes;
  38.     newshapes = realloc(glyph->shapes, (glyph->shapecount+1)*sizeof(GLYPHSHAPE));
  39.     if (!newshapes) {
  40.       fprintf(stderr, "No room\n");
  41.       return 1;
  42.     }
  43.     glyph->shapes = newshapes;
  44.   }
  45.  
  46.   memcpy(glyph->shapes + glyph->shapecount, shape, sizeof(GLYPHSHAPE));
  47.   glyph->shapecount++;
  48.  
  49.   return 0;
  50. }
  51.  
  52.  
  53. int add_glyph(FONT *font, GLYPH *glyph) {
  54.  
  55.   if (font->glyphcount == 255) {
  56.     fprintf(stderr, "Too many glyphs\n");
  57.     return 1;
  58.   }
  59.  
  60.   if (!font->glyphs) {
  61.     font->glyphs = malloc(sizeof(GLYPH));
  62.     if (!font->glyphs) {
  63.       fprintf(stderr, "No room\n");
  64.       return 1;
  65.     }
  66.     font->glyphcount = 0;
  67.  
  68.   } else {
  69.     GLYPH *newglyphs;
  70.     newglyphs = realloc(font->glyphs, (font->glyphcount+1)*sizeof(GLYPH));
  71.     if (!newglyphs) {
  72.       fprintf(stderr, "No room\n");
  73.       return 1;
  74.     }
  75.     font->glyphs = newglyphs;
  76.   }
  77.  
  78.   memcpy(font->glyphs + font->glyphcount, glyph, sizeof(GLYPH));
  79.   font->glyphcount++;
  80.  
  81.   return 0;
  82. }
  83.  
  84.  
  85. int add_text_record(TEXT *text, TEXTREC *rec) {
  86.  
  87.   if (!text->records) {
  88.     text->records = malloc(sizeof(TEXTREC));
  89.     if (!text->records) {
  90.       fprintf(stderr, "No room\n");
  91.       return 1;
  92.     }
  93.     text->recordcount = 0;
  94.  
  95.   } else {
  96.     TEXTREC *newrecords;
  97.     newrecords = realloc(text->records, (text->recordcount+1)*sizeof(TEXTREC));
  98.     if (!newrecords) {
  99.       fprintf(stderr, "No room\n");
  100.       return 1;
  101.     }
  102.     text->records = newrecords;
  103.   }
  104.  
  105.   memcpy(text->records + text->recordcount, rec, sizeof(TEXTREC));
  106.   text->recordcount++;
  107.  
  108.   return 0;
  109. }
  110.  
  111.  
  112. int fonttext_read_font() {
  113.  
  114.   return 0;
  115. }
  116.  
  117.  
  118. int fonttext_write_font(FONT *font) {
  119.  
  120.   U32 ptr, i, glyphoffsets, usedglyphs, gi;
  121.   U8 *buffer;
  122.   U16 *offsets;
  123.   int allglyphs;
  124.  
  125.   if (font->glyphcount == 0) {
  126.     fprintf(stderr, "Empty font\n");
  127.     return 1;
  128.   }
  129.  
  130.   if (find_macro("INCLUDE_ALL_GLYPHS") >= 0)
  131.     allglyphs = 1;
  132.   else
  133.     allglyphs = 0;
  134.  
  135.   // count no. of glyphs to write (== no. of used glyphs)
  136.   if (allglyphs)
  137.     usedglyphs = font->glyphcount;
  138.   else {
  139.     usedglyphs = 0;
  140.     for (gi = 0; gi < font->glyphcount; gi++)
  141.       if (is_glyph_used(font, gi))  usedglyphs++;
  142.     if (usedglyphs == 0)                          return 0;
  143.   }
  144.  
  145.  
  146.   if (flush_bucket())                             return 1;
  147.   ptr = read_position(NULL);
  148.   if (write_ushort(0))                            return 1;
  149.  
  150.   if (write_ushort(font->id))                     return 1;
  151.  
  152.   if (flush_bucket())                             return 1;
  153.  
  154.   // write empty glyph-offset-table
  155.   glyphoffsets = read_position(&buffer);
  156.   for (i = 0; i < usedglyphs; i++)
  157.     if (write_ushort(0))                          return 1;
  158.  
  159.   offsets = (U16 *)(buffer+glyphoffsets);
  160.  
  161.   for (gi = 0; gi < font->glyphcount; gi++) {
  162.     GLYPH *glyph;
  163.     GLYPHSHAPE *shapes;
  164.     U32 n;
  165.  
  166.     if ((is_glyph_used(font, gi)) || (allglyphs)) {
  167.       glyph = font->glyphs + gi;
  168.       shapes = glyph->shapes;
  169.  
  170.       if (flush_bucket())                         return 1;
  171.       *offsets++ = read_position(NULL) - glyphoffsets;
  172.       // bits used for fill and linestyles
  173.       if (write_ubits(4, 1))                      return 1;
  174.       if (write_ubits(4, 1))                      return 1;
  175.       // select fillstyle1 = 1
  176.       if (write_ubits(1, 0))                      return 1;
  177.       if (write_ubits(5, SHAPERECORD_STYLE_FILL1)) return 1;
  178.       if (write_ubits(1, 1))                      return 1; // fillstyle1
  179.  
  180.       for (n = 0; n < glyph->shapecount; n++) {
  181.         int bits;
  182.         GLYPHSHAPE *rec;
  183.  
  184.         rec = shapes+n;
  185.         switch (rec->type) {
  186.         case GLYPHSHAPE_MOVE:
  187.           if ((rec->x) || (rec->y)) {
  188.             if (write_ubits(1, 0))                return 1;
  189.             if (write_ubits(5, SHAPERECORD_STYLE_MOVE))  return 1;
  190.             bits = bitcount_signed(rec->x, rec->y, 0, 0);
  191.             if (write_ubits(5, bits))             return 1;
  192.             if (write_bits(bits, rec->x))         return 1;
  193.             if (write_bits(bits, rec->y))         return 1;
  194.           }
  195.           break;
  196.         case GLYPHSHAPE_LINE:
  197.           if ((rec->x) || (rec->y)) {
  198.             if (write_ubits(1, 1))                return 1;
  199.             if (write_ubits(1, 1))                return 1;
  200.             bits = bitcount_signed(rec->x, rec->y, 0, 0);
  201.             if (bits < 2)   bits = 2;
  202.             if (write_ubits(4, bits-2))           return 1;
  203.             if ((rec->x == 0) || (rec->y == 0)) {
  204.               if (write_ubits(1, 0))              return 1;
  205.               if (rec->y == 0) {
  206.                 if (write_ubits(1, 0))            return 1;
  207.                 if (write_bits(bits, rec->x))     return 1;
  208.               } else {
  209.                 if (write_ubits(1, 1))            return 1;
  210.                 if (write_bits(bits, rec->y))     return 1;
  211.               }
  212.             } else {
  213.               if (write_ubits(1, 1))              return 1;
  214.               if (write_bits(bits, rec->x))       return 1;
  215.               if (write_bits(bits, rec->y))       return 1;
  216.             }
  217.           }
  218.           break;
  219.         case GLYPHSHAPE_CURVE:
  220.           if (write_ubits(1, 1))                  return 1;
  221.           if (write_ubits(1, 0))                  return 1;
  222.           bits = bitcount_signed(rec->x, rec->y, rec->ctrlx, rec->ctrly);
  223.           if (bits < 2)   bits = 2;
  224.           if (write_ubits(4, bits-2))             return 1;
  225.           if (write_bits(bits, rec->ctrlx))       return 1;
  226.           if (write_bits(bits, rec->ctrly))       return 1;
  227.           if (write_bits(bits, rec->x))           return 1;
  228.           if (write_bits(bits, rec->y))           return 1;
  229.           break;
  230.         }
  231.       }
  232.  
  233.       if (write_ubits(1, 0))                      return 1;
  234.       if (write_ubits(5, 0))                      return 1;
  235.     }
  236.   }
  237.  
  238.   return update_record_header(stagDefineFont, ptr);
  239. }
  240.  
  241.  
  242. int fonttext_write_text(TEXT *text) {
  243.  
  244.   U32 ptr, gbits, abits, i, allglyphs, maxglyphs;
  245.   S32 maxadv;
  246.   FONT *font;
  247.   U16 fontsize;
  248.   RECT bbox;
  249.  
  250.   font = NULL;
  251.   fontsize = 0;
  252.  
  253.   if (find_macro("INCLUDE_ALL_GLYPHS") >= 0)
  254.     allglyphs = 1;
  255.   else
  256.     allglyphs = 0;
  257.  
  258.   if (flush_bucket())                             return 1;
  259.   ptr = read_position(NULL);
  260.   if (write_ushort(0))                            return 1;
  261.  
  262.   if (write_ushort(text->id))                     return 1;
  263.  
  264.   // text bbox
  265.   if (string_bbox(text, &bbox, &maxadv))          return 1;
  266.   if (rect_write(&bbox))                          return 1;
  267.  
  268.   if (matrix_write(&text->matrix))                return 1;
  269.  
  270. //  gbits = 8;
  271. //  abits = 16;
  272.   maxglyphs = 0;
  273.   i = 0;
  274.   do {
  275.     if (fontlist[i]) {
  276.       if (fontlist[i]->glyphcount > maxglyphs)
  277.         maxglyphs = fontlist[i]->glyphcount;
  278.       i++;
  279.     }
  280.   } while (fontlist[i]);
  281.   gbits = bitcount(maxglyphs, 0, 0, 0);
  282.   abits = 1 + bitcount(maxadv, 0, 0, 0);
  283.   if (write_ubyte(gbits))                         return 1;
  284.   if (write_ubyte(abits))                         return 1;
  285.  
  286.   for (i = 0; i < text->recordcount; i++) {
  287.     TEXTREC *rec;
  288.     rec = text->records + i;
  289.     if (rec->flags == TEXTREC_STRING) {
  290.       int g;
  291.       if ((font == NULL) || (fontsize == 0)) {
  292.         fprintf(stderr, "No font has been selected, or illegal fontsize\n");
  293.         return 1;
  294.       }
  295.       if (write_ubyte(rec->data.text.length))    return 1;
  296.       for (g = 0; g < rec->data.text.length; g++) {
  297.         int gi, adv, write;
  298.         GLYPH *glyph;
  299.  
  300.         gi = glyph_index(font, rec->data.text.text[g], &write);
  301.         // gi is the glyph index in the font in memory
  302.         // write is the glyph index in the font when written to the file
  303.         if (gi < 0)                               return 1;
  304.         if (allglyphs)  write = gi;
  305.         if (write_ubits(gbits, write))            return 1;
  306.         glyph = font->glyphs + gi;
  307.         adv = ((font->spacing + glyph->bbox.maxx - glyph->bbox.minx) * fontsize )/1024;
  308.         if (write_bits(abits, adv))               return 1;
  309.       }
  310.     } else {
  311.       U8 flags;
  312.       flags = 128;
  313.       if (rec->flags & TEXTREC_MOVE) {
  314.         if (rec->data.style.x)  flags |= 1;
  315.         if (rec->data.style.y)  flags |= 2;
  316.       }
  317.       if (rec->flags & TEXTREC_COLOUR)  flags |= 4;
  318.       if (rec->flags & TEXTREC_SIZE) {
  319.         flags |= 8;
  320.         fontsize = rec->data.style.size;
  321.       }
  322.       if (rec->flags & TEXTREC_FONT) {
  323.         int i;
  324.  
  325.         flags |= 8;
  326.         font = NULL;
  327.         i = find_font(rec->data.style.font);
  328.         if (i == -1) {
  329.           fprintf(stderr, "Font id %d not found\n", rec->data.style.font);
  330.           return 1;
  331.         }
  332.         font = fontlist[i];
  333.       }
  334.       if (write_ubyte(flags))                     return 1;
  335.       if (flags & 8)
  336.         if (write_ushort(font->id))               return 1;
  337.       if (flags & 4)
  338.         if (write_uint(rec->data.style.colour))   return 1;
  339.       if (flags & 1)
  340.         if (write_short(rec->data.style.x))       return 1;
  341.       if (flags & 2)
  342.         if (write_short(rec->data.style.y))       return 1;
  343.       if (flags & 8)
  344.         if (write_ushort(fontsize))               return 1;
  345.     }
  346.   }
  347.  
  348.   if (write_ubyte(0))                             return 1;
  349.  
  350.   return update_record_header(stagDefineText2, ptr);
  351. }
  352.  
  353.  
  354. int string_bbox(TEXT *text, RECT *bbox, S32 *advance) {
  355.  
  356.   int i, fontsize, context;
  357.   FONT *font;
  358.   S32 plotx, ploty;
  359.  
  360.   font = NULL;
  361.   fontsize = 0;
  362.  
  363.   *advance = 0;
  364.  
  365.   bbox_init(bbox, &context);
  366.   plotx = ploty = 0;
  367.  
  368.   for (i = 0; i < text->recordcount; i++) {
  369.     TEXTREC *rec;
  370.  
  371.     rec = text->records + i;
  372.     if (rec->flags == TEXTREC_STRING) {
  373.       int g;
  374.       for (g = 0; g < rec->data.text.length; g++) {
  375.         int gi, adv, write;
  376.         GLYPH *glyph;
  377.         RECT gb;
  378.  
  379.         gi = glyph_index(font, rec->data.text.text[g], &write);
  380.         if (gi < 0)                               return 1;
  381.         glyph = font->glyphs + gi;
  382.         gb.minx = plotx+glyph->bbox.minx*fontsize/1024;
  383.         gb.miny = ploty+glyph->bbox.miny*fontsize/1024;
  384.         gb.maxx = plotx+glyph->bbox.maxx*fontsize/1024;
  385.         gb.maxy = ploty+glyph->bbox.maxy*fontsize/1024;
  386.         bbox_add_bbox(bbox, &context, &gb);
  387.         // calculate advance value
  388.         adv = ((font->spacing + glyph->bbox.maxx - glyph->bbox.minx) * fontsize )/1024;
  389.         if (adv  > *advance)  *advance = adv;
  390.         if (-adv > *advance)  *advance = -adv;
  391.         plotx += adv;
  392.       }
  393.  
  394.     } else {
  395.       if (rec->flags & TEXTREC_MOVE) {
  396.         plotx += rec->data.style.x;
  397.         ploty += rec->data.style.y;
  398.       }
  399.       if (rec->flags & TEXTREC_SIZE)   fontsize = rec->data.style.size;
  400.       if (rec->flags & TEXTREC_FONT) {
  401.         U16 id;
  402.         unsigned int i;
  403.         id = rec->data.style.font;
  404.         i = 0;
  405.         font = NULL;
  406.         do {
  407.           if (!fontlist[i])   return 1;
  408.           if (fontlist[i]->id == id)  font = fontlist[i];
  409.           i++;
  410.         } while (!font);
  411.       }
  412.     }
  413.   }
  414.  
  415.   return 0;
  416. }
  417.  
  418.  
  419. int mark_glyphs_as_used(int fontindex, U8 *string, int n) {
  420.  
  421.   int i, gi;
  422.   FONT *font;
  423.  
  424.   font = fontlist[fontindex];
  425.  
  426.   for (i = 0; i < n; i++) {
  427.     gi = glyph_index(font, string[i], NULL);
  428.     if (gi == -1)
  429.       return 1;
  430.     else
  431.       font->usedglyphs[gi>>5] |= 1<<(gi &31);
  432.   }
  433.  
  434.   return 0;
  435. }
  436.  
  437.  
  438. int find_font(U16 id) {
  439.  
  440.   int i;
  441.  
  442.   for (i = 0; i < fontcount; i++)
  443.     if (fontlist[i]->id == id)  return i;
  444.  
  445.   return -1;
  446. }
  447.  
  448.  
  449. int add_font(FONT *font) {
  450.  
  451.   if (fontcount == MAXFONTS) {
  452.     fprintf(stderr, "Too many fonts\n");
  453.     return 1;
  454.   }
  455.   fontlist[fontcount++] = font;
  456.   fontlist[fontcount] = NULL;
  457.  
  458.   return 0;
  459. }
  460.  
  461. // ----------------------------------------------------------
  462.  
  463. int glyph_index(FONT *font, U8 letter, int *write) {
  464.  
  465.   U32 n;
  466.  
  467.   if (!font)                  return -1;
  468.   if (write)  *write = 0;
  469.  
  470.   for (n = 0; n < font->glyphcount; n++) {
  471.     if (font->glyphs[n].letter == letter)   return n;
  472.     if (write)
  473.       if (is_glyph_used(font, n))  *write += 1;
  474.   }
  475.  
  476.   fprintf(stderr, "Letter '%c' not defined in the selected font\n", letter);
  477.   return -1;
  478. }
  479.  
  480.  
  481. int is_glyph_used(FONT *font, U8 glyph) {
  482.  
  483.   if (font->usedglyphs[glyph>>5] & (1<<(glyph &31)))  return 1;
  484.  
  485.   return 0;
  486. }
  487.