• 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;
18 
19 import com.badlogic.gdx.Gdx;
20 import com.badlogic.gdx.graphics.Color;
21 import com.badlogic.gdx.graphics.GL20;
22 import com.badlogic.gdx.graphics.OrthographicCamera;
23 import com.badlogic.gdx.graphics.Texture;
24 import com.badlogic.gdx.graphics.Texture.TextureFilter;
25 import com.badlogic.gdx.graphics.g2d.BitmapFont;
26 import com.badlogic.gdx.graphics.g2d.GlyphLayout;
27 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
28 import com.badlogic.gdx.graphics.g2d.TextureRegion;
29 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
30 import com.badlogic.gdx.math.MathUtils;
31 import com.badlogic.gdx.tests.utils.GdxTest;
32 import com.badlogic.gdx.utils.Align;
33 
34 public class BitmapFontDistanceFieldTest extends GdxTest {
35 
36 	private static final String TEXT = "Ta";
37 	private static final Color COLOR = Color.BLACK;
38 	private static final float[] SCALES = {0.25f, 0.5f, 1, 2, 4};
39 
40 	private static class DistanceFieldShader extends ShaderProgram {
DistanceFieldShader()41 		public DistanceFieldShader () {
42 			super(Gdx.files.internal("data/shaders/distancefield.vert"), Gdx.files.internal("data/shaders/distancefield.frag"));
43 			if (!isCompiled()) {
44 				throw new RuntimeException("Shader compilation failed:\n" + getLog());
45 			}
46 		}
47 
48 		/** @param smoothing a value between 0 and 1 */
setSmoothing(float smoothing)49 		public void setSmoothing (float smoothing) {
50 			float delta = 0.5f * MathUtils.clamp(smoothing, 0, 1);
51 			setUniformf("u_lower", 0.5f - delta);
52 			setUniformf("u_upper", 0.5f + delta);
53 		}
54 	}
55 
56 	private OrthographicCamera camera;
57 	private SpriteBatch spriteBatch;
58 
59 	private Texture regularTexture;
60 	private Texture distanceFieldTexture;
61 	private BitmapFont descriptionFont;
62 	private BitmapFont regularFont;
63 	private BitmapFont distanceFieldFont;
64 	private DistanceFieldShader distanceFieldShader;
65 	private GlyphLayout layout = new GlyphLayout();
66 
67 	@Override
create()68 	public void create () {
69 		camera = new OrthographicCamera();
70 		spriteBatch = new SpriteBatch();
71 
72 		descriptionFont = new BitmapFont(Gdx.files.internal("data/arial-15.fnt"), true);
73 		descriptionFont.setColor(Color.RED);
74 
75 		regularTexture = new Texture(Gdx.files.internal("data/verdana39.png"), true);
76 		regularFont = new BitmapFont(Gdx.files.internal("data/verdana39.fnt"), new TextureRegion(regularTexture), true);
77 		regularFont.setColor(COLOR);
78 
79 		distanceFieldTexture = new Texture(Gdx.files.internal("data/verdana39distancefield.png"), true);
80 		distanceFieldFont = new BitmapFont(Gdx.files.internal("data/verdana39distancefield.fnt"), new TextureRegion(
81 			distanceFieldTexture), true);
82 		distanceFieldFont.setColor(COLOR);
83 
84 		distanceFieldShader = new DistanceFieldShader();
85 		ShaderProgram.pedantic = false; // Useful when debugging this test
86 	}
87 
88 	@Override
render()89 	public void render () {
90 		Gdx.gl.glClearColor(1, 1, 1, 1);
91 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
92 
93 		spriteBatch.begin();
94 
95 		int x = 10;
96 		x += drawFont(regularFont, "Regular font\nNearest filter", false, false, 0, x);
97 		x += drawFont(regularFont, "Regular font\nLinear filter", true, false, 0, x);
98 		x += drawFont(regularFont, "Regular font\nCustom shader", true, true, 1.0f, x);
99 		x += drawFont(distanceFieldFont, "Distance field\nCustom shader", true, true, 1 / 8f, x);
100 		x += drawFont(distanceFieldFont, "Distance field\nShowing distance field", false, false, 0, x);
101 
102 		spriteBatch.end();
103 	}
104 
drawFont(BitmapFont font, String description, boolean linearFiltering, boolean useShader, float smoothing, int x)105 	private int drawFont (BitmapFont font, String description, boolean linearFiltering, boolean useShader, float smoothing, int x) {
106 		int y = 10;
107 		float maxWidth = 0;
108 
109 		spriteBatch.setShader(null);
110 		descriptionFont.draw(spriteBatch, description, x, y);
111 		spriteBatch.flush();
112 		y += 10 + 2 * descriptionFont.getLineHeight();
113 
114 		// set filters for each page
115 		TextureFilter minFilter = linearFiltering ? TextureFilter.MipMapLinearNearest : TextureFilter.Nearest;
116 		TextureFilter magFilter = linearFiltering ? TextureFilter.Linear : TextureFilter.Nearest;
117 		for (int i = 0; i < font.getRegions().size; i++) {
118 			font.getRegion(i).getTexture().setFilter(minFilter, magFilter);
119 		}
120 
121 		if (useShader) {
122 			spriteBatch.setShader(distanceFieldShader);
123 		} else {
124 			spriteBatch.setShader(null);
125 		}
126 
127 		for (float scale : SCALES) {
128 			font.getData().setScale(scale);
129 			layout.setText(font, TEXT);
130 			maxWidth = Math.max(maxWidth, layout.width);
131 			if (useShader) {
132 				distanceFieldShader.setSmoothing(smoothing / scale);
133 			}
134 			font.draw(spriteBatch, layout, x, y);
135 			y += font.getLineHeight();
136 			spriteBatch.flush();
137 		}
138 		return (int)Math.ceil(maxWidth);
139 	}
140 
getBaselineShift(float shift)141 	private float getBaselineShift (float shift) {
142 		return shift;
143 	}
144 
145 	@Override
resize(int width, int height)146 	public void resize (int width, int height) {
147 		super.resize(width, height);
148 		camera.setToOrtho(true, width, height);
149 		spriteBatch.setTransformMatrix(camera.view);
150 		spriteBatch.setProjectionMatrix(camera.projection);
151 	}
152 
153 	@Override
dispose()154 	public void dispose () {
155 		spriteBatch.dispose();
156 		regularTexture.dispose();
157 		distanceFieldTexture.dispose();
158 		descriptionFont.dispose();
159 		regularFont.dispose();
160 		distanceFieldFont.dispose();
161 		distanceFieldShader.dispose();
162 	}
163 }
164