canvas

Using bitmap fonts

With this example we are going to demonstrate how to use bitmap fonts in an Android Application. Android is running on a wide variety of devices with lots of different screen sizes and resolutions.

So bitmap fonts can help you address the problem of using a consistent font face across different devices. For this tutorial we are going to use a monospaced font alphabet which means that all the characters have the same width and height.
 
 
 
 

In short, to create and use bitmap fonts you should:

  • create an image containing all the characters of the alphabet you want, with transparent background and copy it to a drawable Android resource foulders
  • measure the height and the width of a sample character on your image, in pixels
  • create a bitmap containing the character map
  • assosiate all the characters and numbers of the alphabet with a substet bitmap, derived from the main bitmap
  • use Glyphs an canvans to draw the sting you want on the screen

as shown in the code snippets below:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package net.obviam.fonts;
 
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
 
public class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
 
    private static final String TAG = DrawingPanel.class.getSimpleName();
 
    private Canvas canvas;      // the canvas to draw on
    private Glyphs glyphs;      // the glyphs
 
    public DrawingPanel(Context context) {
        super(context);
        // adding the panel to handle events
        getHolder().addCallback(this);
 
        // initialise resources
        loadResources();
 
        // making the Panel focusable so it can handle events
        setFocusable(true);
    }
 
    /**
     * Loads the images
     */
    private void loadResources() {
        this.glyphs = new Glyphs(BitmapFactory.decodeResource(getResources(), R.drawable.glyphs_green));
        Log.d(TAG, "Green glyphs loaded");
    }
 
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }
 
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }
 
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // draw text at touch
        try {
            canvas = getHolder().lockCanvas();
            synchronized (getHolder()) {
                if (event.getAction() == MotionEvent.ACTION_DOWN
                        || event.getAction() == MotionEvent.ACTION_MOVE) {
                    // clear the screen
                    canvas.drawColor(Color.BLACK);
                    // draw glyphs
                    glyphs.drawString(canvas, "Drawing string at "
                            + (int) event.getX() + " " + (int) event.getY(),
                            (int) event.getX(), (int) event.getY());
                }
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    canvas.drawColor(Color.BLACK);
                    glyphs.drawString(canvas, "Drawn string at "
                            + (int) event.getX() + " " + (int) event.getY(),
                            (int) event.getX(), (int) event.getY());
                }
            }
        } finally {
            if (canvas != null) {
                getHolder().unlockCanvasAndPost(canvas);
            }
        }
        // event was handled
        return true;
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
    }
 
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package net.obviam.fonts;
 
import java.util.HashMap;
import java.util.Map;
 
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
 
public class Glyphs {
 
    private static final String TAG = Glyphs.class.getSimpleName();
    private Bitmap bitmap;  // bitmap containing the character map/sheet
 
    // Map to associate a bitmap to each character
    private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);
 
    private int width;  // width in pixels of one character
    private int height; // height in pixels of one character
 
    // the characters in the English alphabet
    private char[] charactersL = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z' };
    private char[] charactersU = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
            'U', 'V', 'W', 'X', 'Y', 'Z' };
    private char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7',
            '8', '9', '0' };
 
    public Glyphs(Bitmap bitmap) {
        super();
        this.bitmap = bitmap;
        this.width = 8;
        this.height = 12;
        // Cutting up the glyphs
        // Starting with the first row - lower cases
        for (int i = 0; i < 26; i++) {
            glyphs.put(charactersL[i], Bitmap.createBitmap(bitmap,
                    0 + (i * width), 0, width, height));
        }
        Log.d(TAG, "Lowercases initialised");
 
        // Continuing with the second row - upper cases
        // Note that the row starts at 15px - hardcoded
        for (int i = 0; i < 26; i++) {
            glyphs.put(charactersU[i], Bitmap.createBitmap(bitmap,
                    0 + (i * width), 15, width, height));
        }
        // row 3 for numbers
        Log.d(TAG, "Uppercases initialised");
        for (int i = 0; i < 10; i++) {
            glyphs.put(numbers[i], Bitmap.createBitmap(bitmap,
                    0 + (i * width), 30, width, height));
        }
        Log.d(TAG, "Numbers initialised");
 
        // TODO - 4th row for punctuation
    }
 
    public Bitmap getBitmap() {
        return bitmap;
    }
 
    /**
     * Draws the string onto the canvas at <code>x</code> and <code>y</code>
     * @param text
     */
    public void drawString(Canvas canvas, String text, int x, int y) {
        if (canvas == null) {
            Log.d(TAG, "Canvas is null");
        }
        for (int i = 0; i < text.length(); i++) {
            Character ch = text.charAt(i);
            if (glyphs.get(ch) != null) {
                canvas.drawBitmap(glyphs.get(ch), x + (i * width), y, null);
            }
        }
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package net.obviam.fonts;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
 
public class PrintingActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
 
  super.onCreate(savedInstanceState);
 
  // turn off title
 
  requestWindowFeature(Window.FEATURE_NO_TITLE);
 
  setContentView(new DrawingPanel(this));
    }
}

 
This was an example of how to Use Bitmap Fonts in Android.

Related Article:

Reference: Using Bitmap Fonts in Android from our JCG partner Tamas Jano at the “Against The Grain” blog.

Ilias Tsagklis

Ilias is a software developer turned online entrepreneur. He is co-founder and Executive Editor at Java Code Geeks.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button