• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.tests.extensions;
18 
19 import com.badlogic.gdx.Gdx;
20 import com.badlogic.gdx.graphics.GL20;
21 import com.badlogic.gdx.graphics.OrthographicCamera;
22 import com.badlogic.gdx.graphics.Pixmap.Format;
23 import com.badlogic.gdx.graphics.Texture;
24 import com.badlogic.gdx.graphics.g2d.BitmapFont;
25 import com.badlogic.gdx.graphics.g2d.PixmapPacker;
26 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
27 import com.badlogic.gdx.graphics.g2d.TextureAtlas;
28 import com.badlogic.gdx.graphics.g2d.TextureRegion;
29 import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
30 import com.badlogic.gdx.tests.utils.GdxTest;
31 import com.badlogic.gdx.utils.Array;
32 
33 import java.util.EnumMap;
34 
35 /**
36  * An example of packing many glyphs into a single texture atlas, using FreeTypeFontGenerator.
37  * <p/>
38  * This example uses enum ordinals for fast access to a two-dimensional array, which stores BitmapFonts by size and style. A more
39  * flexible solution might be to use an ObjectMap and and IntMap instead.
40  * <p/>
41  * This test uses a less efficient but more convenient way to pack multiple generated fonts into a single texture atlas
42  * compared with FreeTypePackTest - each texture page will be generated and refreshed once.  Refreshing textures is slow
43  * on mobile devices.
44  */
45 public class FreeTypeAtlasTest extends GdxTest {
46 
47 	// Define font sizes here...
48 	static enum FontSize {
49 		Tiny(10), Small(12), Medium(16), Large(20), Huge(24), ReallyHuge(28), JustTooBig(64);
50 
51 		public final int size;
52 
FontSize(int size)53 		FontSize(int size) {
54 			this.size = size;
55 		}
56 	}
57 
58 	// Define font styles here...
59 	static enum FontStyle {
60 		Regular("data/arial.ttf"), Italic("data/arial-italic.ttf");
61 
62 		public final String path;
63 
FontStyle(String path)64 		FontStyle(String path) {
65 			this.path = path;
66 		}
67 	}
68 
69 	OrthographicCamera camera;
70 	SpriteBatch batch;
71 	String text;
72 	PixmapPacker packer;
73 	FontMap<BitmapFont> fontMap;
74 
75 	public static final int FONT_ATLAS_WIDTH = 1024;
76 	public static final int FONT_ATLAS_HEIGHT = 512;
77 
78 	// whether to use integer coords for BitmapFont...
79 	private static final boolean INTEGER = false;
80 
81 	// Our demo doesn't need any fancy characters.
82 	// Note: the set in FreeTypeFontGenerator.DEFAULT_CHARS is more extensive
83 	// Also note that this string must be contained of unique characters; no duplicates!
84 	public static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz\n1234567890"
85 			+ "\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*";
86 
87 	@Override
create()88 	public void create() {
89 		camera = new OrthographicCamera();
90 		batch = new SpriteBatch();
91 
92 		long start = System.currentTimeMillis();
93 		int glyphCount = createFonts();
94 		long time = System.currentTimeMillis() - start;
95 		text = glyphCount + " glyphs packed in " + packer.getPages().size + " page(s) in " + time + " ms";
96 
97 	}
98 
99 	@Override
render()100 	public void render() {
101 		Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
102 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
103 
104 		camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
105 		batch.setProjectionMatrix(camera.combined);
106 		batch.begin();
107 
108 		float x = 10;
109 		float y = Gdx.graphics.getHeight() - 10;
110 
111 		int renderCalls = 0;
112 
113 		// NOTE: Before production release on mobile, you should cache the array from values()
114 		// inside the Enum in order to reduce allocations in the render loop.
115 		for (FontStyle style : FontStyle.values()) {
116 			for (FontSize size : FontSize.values()) {
117 				BitmapFont fnt = getFont(style, size);
118 
119 				fnt.draw(batch, style.name() + " " + size.size + "pt: The quick brown fox jumps over the lazy dog", x, y);
120 				y -= fnt.getLineHeight() + 10;
121 			}
122 			y -= 20;
123 		}
124 
125 		BitmapFont font = getFont(FontStyle.Regular, FontSize.Medium);
126 		font.draw(batch, text, 10, font.getCapHeight() + 10);
127 
128 		// draw all glyphs in background
129 		batch.setColor(1f, 1f, 1f, 0.15f);
130 		batch.draw(packer.getPages().first().getTexture(), 0, 0);
131 		batch.setColor(1f, 1f, 1f, 1f);
132 		batch.end();
133 	}
134 
135 	@Override
dispose()136 	public void dispose() {
137 		super.dispose();
138 		packer.dispose();
139 		batch.dispose();
140 	}
141 
142 	// Utility method to grab a font by style/size pair
getFont(FontStyle style, FontSize size)143 	public BitmapFont getFont(FontStyle style, FontSize size) {
144 		return fontMap.get(style).get(size);
145 	}
146 
createFonts()147 	protected int createFonts() {
148 		// This test uses a less efficient but more convenient way to pack multiple generated fonts into a single
149 		// texture atlas.
150 		//
151 		// 1. Create a new PixmapPacker big enough to fit all your desired glyphs
152 		// 2. Create a new FreeTypeFontGenerator for each TTF file (i.e. font styles/families)
153 		// 3. For each size and style, call generator.generateFont() with the packer set on the parameter
154 		// 4. Generate the texture atlas using packer.generateTextureAtlas or packer.updateTextureAtlas.
155 		// 5. Dispose of the atlas upon application exit or when you are done using the fonts
156 		// //////////////////////////////////////////////////////////////////////////////////////////////////////
157 
158 		// create the pixmap packer
159 		packer = new PixmapPacker(FONT_ATLAS_WIDTH, FONT_ATLAS_HEIGHT, Format.RGBA8888, 2, false);
160 
161 		fontMap = new FontMap<BitmapFont>();
162 		int fontCount = 0;
163 
164 		// for each style...
165 		for (FontStyle style : FontStyle.values()) {
166 			// get the file for this style
167 			FreeTypeFontGenerator gen = new FreeTypeFontGenerator(Gdx.files.internal(style.path));
168 
169 			// For each size...
170 			for (FontSize size : FontSize.values()) {
171 				// pack the glyphs into the atlas using the default chars
172 				FreeTypeFontGenerator.FreeTypeFontParameter fontParameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
173 				fontParameter.size = size.size;
174 				fontParameter.packer = packer;
175 				fontParameter.characters = CHARACTERS;
176 				BitmapFont bmFont = gen.generateFont(fontParameter);
177 
178 				fontMap.get(style).put(size, bmFont);
179 				fontCount++;
180 			}
181 
182 			// dispose of the generator once we're finished with this family
183 			gen.dispose();
184 		}
185 
186 		// for the demo, show how many glyphs we loaded
187 		return fontCount * CHARACTERS.length();
188 	}
189 
190 	// We use a nested EnumMap for fast access
191 	class FontMap<T> extends EnumMap<FontStyle, EnumMap<FontSize, T>> {
192 
FontMap()193 		public FontMap() {
194 			super(FontStyle.class);
195 
196 			// create the enum map for each FontSize
197 			for (FontStyle style : FontStyle.values()) {
198 				put(style, new EnumMap<FontSize, T>(FontSize.class));
199 			}
200 		}
201 	}
202 }
203