1
votes

I researched for fonts that used in HTML5 & CSS3. I know web-fonts (like ttf/otf, eot, woff,woff2) will support in Web pages. But, I need to use *.fon fonts (font that used in native application) in canvas.

I refered the link that bitmaptext can be used with extending fabric.image. But, i need to use bitmaptext like normal text object of fabricjs. eg. font-style, wrapping, line spacing, font change, etc.

Is it possible to do with bitmaptext or is there any other way to render text from *.fon files?

.fon file converted to bitmap

1
Can't you convert this .fon in a web compatible font? looks like the best solution.AndreaBogazzi
Can. But, i want to change the character fontsize(width and height will not be proportionate) not like normal text fontsize. eg. if i use 6x9 font which character width is 6px and height is 9px, then my fontsize may be 12x9 or 6x18. thats not possible in normal web font.VijayaDinagar
So your best bet is to subclass iText instead of text, and override the rendering method, at that point you have an editable bitmap textAndreaBogazzi
Currently, i created a character set with *.fon as image and extended the fabric.image class as reference from link. is your opinion is to extend IText instead of Image?VijayaDinagar
What do you think to make a tutorial from this use case? I can add the tutorial to fabricjs.com an then post it here as a link, or copy the full code in the answer. I Think is nice use case for a subclass tutorialAndreaBogazzi

1 Answers

1
votes

Here you can see a basic override of the Textbox class.

I added all the properties i needed to handle the basic functionality, i stubbed the measureChar function to return the fixed width of the bitmap font, 6px.

At initialize time i create a map that tells me the position of the most common chars in the bitmap font, and finally i wrote a simple render method that retrieve the part of the canvas it needs in order to draw that character.

You still need to figure out fontColor, fontSize, doubleWidth and doubleHeight, but should be straight forward now that you have this example

(function() {
  fabric.BitmapText = fabric.util.createClass(fabric.Textbox, {
    type: 'bitmapText',
    bitmap: 'https://i.stack.imgur.com/ITDgw.png',
    readyToRender: false,
    charWidth: 6,
    charHeight: 9,
    fontSize: 9,

    charMap: ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}'
      .split('').reduce(function(acc, char, index) {
        acc[char] = index + 31;
        return acc;
      }, {}),
    initialize: function(text, options) {
      this.callSuper('initialize', text, options);
      var image = fabric.document.createElement('img');
      image.onload = (function() {
        var canvas = fabric.document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;
        console.log(canvas.width)
        canvas.getContext('2d').drawImage(image, 0, 0);
        this.bitmapResource = canvas;
        this.readyToRender = true;
        this.dirty = true;
        if (this.canvas) this.canvas.requestRenderAll();
      }).bind(this);
      image.src = this.bitmap;
    },

    // override: make it return a fixed box 6x9
    _measureChar: function(_char, charStyle, previousChar, prevCharStyle) {
      return { width: 6, kernedWidth: 6 };
    },

    _renderChar: function(method, ctx, lineIndex, charIndex, _char, left, top) {
      if (!this.readyToRender) return;
      var charMap = this.charMap, res = this.bitmapResource;
      _char.split('').forEach(function(singleChar) {
        ctx.drawImage(res, charMap[singleChar] * 6, 0, 5, 9, left, top - 6, 5, 9);
        ctx.translate(6, 0);
      });
    },
  });


  var canvas = new fabric.Canvas('c');
  var text = new fabric.BitmapText('Hello i am a bitmap text');

  canvas.add(text);
  canvas.setActiveObject(text);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.1.0/fabric.min.js"></script>
<canvas id="c" width="350" height="400" />