001package squidpony.squidgrid.gui.gdx;
002
003import com.badlogic.gdx.Application;
004import com.badlogic.gdx.Gdx;
005import com.badlogic.gdx.LifecycleListener;
006import com.badlogic.gdx.graphics.Texture;
007import com.badlogic.gdx.graphics.g2d.BitmapFont;
008import com.badlogic.gdx.graphics.g2d.TextureAtlas;
009import com.badlogic.gdx.graphics.g2d.TextureRegion;
010import com.badlogic.gdx.graphics.glutils.ShaderProgram;
011import squidpony.squidmath.StatefulRNG;
012
013/**
014 * Default BitmapFonts, a sample image, and a central RNG for use with LibGDX.
015 * The fonts provided are all monospaced, with most looking rather similar (straight orthogonal lines and right-angle
016 * curves), but the one that looks... better than the rest (Inconsolata-LGC, accessible by getSmoothFont(),
017 * getLargeSmoothFont(), or as a distance field font that smoothly scales with getStretchableFont() or a square variant
018 * with getStretchableSquareFont()) also supports Greek and Cyrillic, and is the only one to do so. If you can't decide,
019 * go with getStretchableFont() or getStretchableSquareFont(), which return TextCellFactory objects.
020 *
021 * The most Latin script support is in the font Mandrill, accessible by getDefaultUnicodeFont() and
022 * getLargeUnicodeFont() in two different sizes, and the latter should be suitable for everything from Spanish and
023 * French, to Polish to Vietnamese.
024 * <br>
025 * The sample image is a tentacle taken from a public domain icon collection graciously released by Henrique Lazarini;
026 * it's fitting for SquidLib to have a tentacle as a logo or something, I guess?
027 * <br>
028 * You can get a default RNG with getGuiRandom(); this should probably not be reused for non-GUI-related randomness,
029 * but is meant instead to be used wherever randomized purely-aesthetic effects are needed, such as a jiggling effect.
030 * Created by Tommy Ettinger on 7/11/2015.
031 */
032public class DefaultResources implements LifecycleListener {
033    private BitmapFont narrow1 = null, narrow2 = null, narrow3 = null,
034            smooth1 = null, smooth2 = null, smoothSquare = null, smoothSquareOld = null,
035            square1 = null, square2 = null,
036            unicode1 = null, unicode2 = null;
037    private TextCellFactory distanceNarrow = null, distanceSquare = null, typewriterDistanceNarrow = null,
038            distancePrint = null, distanceClean = null;
039    private TextureAtlas iconAtlas = null;
040    public static final String squareName = "Zodiac-Square-12x12.fnt",
041            narrowName = "Rogue-Zodiac-6x12.fnt",
042            unicodeName = "Mandrill-6x16.fnt",
043            squareNameLarge = "Zodiac-Square-24x24.fnt",
044            narrowNameLarge = "Rogue-Zodiac-12x24.fnt",
045            unicodeNameLarge = "Mandrill-12x32.fnt",
046            narrowNameExtraLarge = "Rogue-Zodiac-18x36.fnt",
047            smoothName = "Inconsolata-LGC-8x18.fnt",
048            smoothNameLarge = "Inconsolata-LGC-12x24.fnt",
049            distanceFieldSquare = "Inconsolata-LGC-Square-distance.fnt",
050            distanceFieldSquareTexture = "Inconsolata-LGC-Square-distance.png",
051            distanceFieldNarrow = "Inconsolata-LGC-Custom-distance.fnt",
052            distanceFieldNarrowTexture = "Inconsolata-LGC-Custom-distance.png",
053            distanceFieldPrint = "Gentium-distance.fnt",
054            distanceFieldPrintTexture = "Gentium-distance.png",
055            distanceFieldClean = "Noto-Sans-distance.fnt",
056            distanceFieldCleanTexture = "Noto-Sans-distance.png",
057            distanceFieldTypewriterNarrow = "CM-Custom-distance.fnt",
058            distanceFieldTypewriterNarrowTexture = "CM-Custom-distance.png";
059    public static String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n"
060            + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n"
061            + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n"
062            + "uniform mat4 u_projTrans;\n"
063            + "varying vec4 v_color;\n"
064            + "varying vec2 v_texCoords;\n"
065            + "\n"
066            + "void main() {\n"
067            + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n"
068            + " v_color.a = v_color.a * (255.0/254.0);\n"
069            + " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n"
070            + " gl_Position =  u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n"
071            + "}\n";
072
073    public static String fragmentShader = "#ifdef GL_ES\n"
074            + " precision mediump float;\n"
075            + " precision mediump int;\n"
076            + "#endif\n"
077            + "\n"
078            + "uniform sampler2D u_texture;\n"
079            + "uniform float u_smoothing;\n"
080            + "varying vec4 v_color;\n"
081            + "varying vec2 v_texCoords;\n"
082            + "\n"
083            + "void main() {\n"
084            + " if (u_smoothing > 0.0) {\n"
085            + "         float smoothing = 0.25 / u_smoothing;\n"
086            + "         float distance = texture2D(u_texture, v_texCoords).a;\n"
087            + "         float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);\n"
088            + "         gl_FragColor = vec4(v_color.rgb, alpha * v_color.a);\n"
089            + " } else {\n"
090            + "         gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n"
091            + " }\n"
092            + "}\n";
093    private SquidColorCenter scc = null;
094    private Texture tentacle = null;
095    private TextureRegion tentacleRegion = null;
096    private StatefulRNG guiRandom;
097
098    private static DefaultResources instance = null;
099
100    private DefaultResources()
101    {
102        if(Gdx.app == null)
103            throw new IllegalStateException("Gdx.app cannot be null; initialize GUI-using objects in create() or later.");
104        Gdx.app.addLifecycleListener(this);
105    }
106
107    private static void initialize()
108    {
109        if(instance == null)
110            instance = new DefaultResources();
111    }
112
113    /**
114     * Returns a 12x12px, stretched but curvaceous font as an embedded resource. Caches it for later calls.
115     * @return the BitmapFont object representing Zodiac-Square.ttf at size 16 pt
116     */
117    public static BitmapFont getDefaultFont()
118    {
119        initialize();
120        if(instance.square1 == null)
121        {
122            try {
123                instance.square1 = new BitmapFont(Gdx.files.internal("Zodiac-Square-12x12.fnt"), Gdx.files.internal("Zodiac-Square-12x12.png"), false);
124                //instance.square1.getData().padBottom = instance.square1.getDescent();
125            } catch (Exception e) {
126            }
127        }
128        return instance.square1;
129    }
130    /**
131     * Returns a 24x24px, stretched but curvaceous font as an embedded resource. Caches it for later calls.
132     * @return the BitmapFont object representing Zodiac-Square.ttf at size 32 pt
133     */
134    public static BitmapFont getLargeFont()
135    {
136        initialize();
137        if(instance.square2 == null)
138        {
139            try {
140                instance.square2 = new BitmapFont(Gdx.files.internal("Zodiac-Square-24x24.fnt"), Gdx.files.internal("Zodiac-Square-24x24.png"), false);
141                //instance.square2.getData().padBottom = instance.square2.getDescent();
142            } catch (Exception e) {
143            }
144        }
145        return instance.square2;
146    }
147    /**
148     * Returns a 6x12px, narrow and curving font as an embedded resource. Caches it for later calls.
149     * @return the BitmapFont object representing Rogue-Zodiac.ttf at size 16 pt
150     */
151    public static BitmapFont getDefaultNarrowFont()
152    {
153        initialize();
154        if(instance.narrow1 == null)
155        {
156            try {
157                instance.narrow1 = new BitmapFont(Gdx.files.internal("Rogue-Zodiac-6x12.fnt"), Gdx.files.internal("Rogue-Zodiac-6x12_0.png"), false);
158                //instance.narrow1.getData().padBottom = instance.narrow1.getDescent();
159            } catch (Exception e) {
160            }
161        }
162        return instance.narrow1;
163    }
164
165    /**
166     * Returns a 12x24px, narrow and curving font as an embedded resource. Caches it for later calls.
167     * @return the BitmapFont object representing Rogue-Zodiac.ttf at size 32 pt
168     */
169    public static BitmapFont getLargeNarrowFont()
170    {
171        initialize();
172        if(instance.narrow2 == null)
173        {
174            try {
175                instance.narrow2 = new BitmapFont(Gdx.files.internal("Rogue-Zodiac-12x24.fnt"), Gdx.files.internal("Rogue-Zodiac-12x24_0.png"), false);
176                //instance.narrow2.getData().padBottom = instance.narrow2.getDescent();
177            } catch (Exception e) {
178            }
179        }
180        return instance.narrow2;
181    }
182    /**
183     * Returns a 12x24px, narrow and curving font as an embedded resource. Caches it for later calls.
184     * @return the BitmapFont object representing Rogue-Zodiac.ttf at size 32 pt
185     */
186    public static BitmapFont getExtraLargeNarrowFont()
187    {
188        initialize();
189        if(instance.narrow3 == null)
190        {
191            try {
192                instance.narrow3 = new BitmapFont(Gdx.files.internal("Rogue-Zodiac-18x36.fnt"), Gdx.files.internal("Rogue-Zodiac-18x36_0.png"), false);
193                //instance.narrow3.getData().padBottom = instance.narrow3.getDescent();
194            } catch (Exception e) {
195            }
196        }
197        return instance.narrow3;
198    }
199
200    /**
201     * Returns a 8x18px, very smooth and generally good-looking font (based on Inconsolata) as an embedded resource.
202     * This font fully supports Latin, Greek, Cyrillic, and of particular interest to SquidLib, Box Drawing characters.
203     * Caches the font for later calls.
204     * @return the BitmapFont object representing Inconsolata-LGC.ttf at size... pretty sure it's 8x18 pixels
205     */
206    public static BitmapFont getSmoothFont()
207    {
208        initialize();
209        if(instance.smooth1 == null)
210        {
211            try {
212                instance.smooth1 = new BitmapFont(Gdx.files.internal("Inconsolata-LGC-8x18.fnt"), Gdx.files.internal("Inconsolata-LGC-8x18.png"), false);
213                //instance.smooth1.getData().padBottom = instance.smooth1.getDescent();
214            } catch (Exception e) {
215            }
216        }
217        return instance.smooth1;
218    }
219    /**
220     * Returns a 12x24px, very smooth and generally good-looking font (based on Inconsolata) as an embedded resource.
221     * This font fully supports Latin, Greek, Cyrillic, and of particular interest to SquidLib, Box Drawing characters.
222     * Caches the font for later calls.
223     * @return the BitmapFont object representing Inconsolata-LGC.ttf at size... not actually sure, 12x24 pixels
224     */
225    public static BitmapFont getLargeSmoothFont()
226    {
227        initialize();
228        if(instance.smooth2 == null)
229        {
230            try {
231                instance.smooth2 = new BitmapFont(Gdx.files.internal("Inconsolata-LGC-12x24.fnt"), Gdx.files.internal("Inconsolata-LGC-12x24.png"), false);
232                //instance.smooth2.getData().padBottom = instance.smooth2.getDescent();
233            } catch (Exception e) {
234            }
235        }
236        return instance.smooth2;
237    }
238    /**
239     * Returns a 6x16px, narrow and curving font with a lot of unicode chars as an embedded resource. Caches it for later calls.
240     * @return the BitmapFont object representing Mandrill.ttf at size 16 pt
241     */
242    public static BitmapFont getDefaultUnicodeFont()
243    {
244        initialize();
245        if(instance.unicode1 == null)
246        {
247            try {
248                instance.unicode1 = new BitmapFont(Gdx.files.internal("Mandrill-6x16.fnt"), Gdx.files.internal("Mandrill-6x16.png"), false);
249                //instance.unicode1.getData().padBottom = instance.unicode1.getDescent();
250            } catch (Exception e) {
251            }
252        }
253        return instance.unicode1;
254    }
255
256    /**
257     * Returns a 12x32px, narrow and curving font with a lot of unicode chars as an embedded resource. Caches it for later calls.
258     * @return the BitmapFont object representing Mandrill.ttf at size 32 pt
259     */
260    public static BitmapFont getLargeUnicodeFont()
261    {
262        initialize();
263        if(instance.unicode2 == null)
264        {
265            try {
266                instance.unicode2 = new BitmapFont(Gdx.files.internal("Mandrill-12x32.fnt"), Gdx.files.internal("Mandrill-12x32.png"), false);
267                //instance.unicode2.getData().padBottom = instance.unicode2.getDescent();
268            } catch (Exception e) {
269            }
270        }
271        return instance.unicode2;
272    }
273    /**
274     * Returns a 25x25px, very smooth and generally good-looking font (based on Inconsolata) as an embedded resource.
275     * This font fully supports Latin, Greek, Cyrillic, and of particular interest to SquidLib, Box Drawing characters.
276     * This variant is (almost) perfectly square, and box drawing characters should line up at size 25x25 px, but other
277     * glyphs will have much more horizontal spacing than in other fonts. Caches the font for later calls.
278     * @return the BitmapFont object representing Inconsolata-LGC-Square at size 25x25 pixels
279     */
280    public static BitmapFont getSquareSmoothFont()
281    {
282        initialize();
283        if(instance.smoothSquare == null)
284        {
285            try {
286                instance.smoothSquare = new BitmapFont(Gdx.files.internal("Inconsolata-LGC-Square-25x25.fnt"), Gdx.files.internal("Inconsolata-LGC-Square-25x25.png"), false);
287                //instance.smoothSquare.getData().padBottom = instance.smoothSquare.getDescent();
288            } catch (Exception e) {
289            }
290        }
291        return instance.smoothSquare;
292    }
293
294    /**
295     * NOTE: May have issues with transparency. Prefer using distance field fonts with getStretchableSquareFont() if
296     * possible, or getSquareSmoothFont() for a larger square BitmapFont. Returns a 20x20px, very smooth and generally
297     * good-looking font (based on Inconsolata) as an embedded resource. This font fully supports Latin, Greek,
298     * Cyrillic, and of particular interest to SquidLib, Box Drawing characters. This variant is (almost) perfectly
299     * square, and box drawing characters should line up at size 20x20 px, but other glyphs will have much more
300     * horizontal spacing than in other fonts. Caches the font for later calls.
301     * @return the BitmapFont object representing Inconsolata-LGC-Square at size 20x20 pixels
302     */
303    public static BitmapFont getSquareSmoothMediumFont()
304    {
305        initialize();
306        if(instance.smoothSquareOld == null)
307        {
308            try {
309                instance.smoothSquareOld = new BitmapFont(Gdx.files.internal("Inconsolata-LGC-Square.fnt"), Gdx.files.internal("Inconsolata-LGC-Square.png"), false);
310                //instance.smoothSquareOld.getData().padBottom = instance.smoothSquareOld.getDescent();
311            } catch (Exception e) {
312            }
313        }
314        return instance.smoothSquareOld;
315    }
316
317    /**
318     * Returns a TextCellFactory already configured to use a square font that should scale cleanly to many sizes. Caches
319     * the result for later calls.
320     * <br>
321     * This creates a TextCellFactory instead of a BitmapFont because it needs to set some extra information so the
322     * distance field font technique this uses can work.
323     * @return the TextCellFactory object that can represent many sizes of the square font Inconsolata-LGC-Square.ttf
324     */
325    public static TextCellFactory getStretchableSquareFont()
326    {
327        initialize();
328        if(instance.distanceSquare == null)
329        {
330            try {
331                instance.distanceSquare = new TextCellFactory().defaultDistanceFieldFont();
332            } catch (Exception e) {
333            }
334        }
335        if(instance.distanceSquare != null)
336            return instance.distanceSquare.copy();
337        return null;
338    }
339    /**
340     * Returns a TextCellFactory already configured to use a narrow font (twice as tall as it is wide) that should scale
341     * cleanly to many sizes. Caches the result for later calls.
342     * <br>
343     * This creates a TextCellFactory instead of a BitmapFont because it needs to set some extra information so the
344     * distance field font technique this uses can work.
345     * @return the TextCellFactory object that can represent many sizes of the font Inconsolata-LGC-Custom.ttf
346     */
347    public static TextCellFactory getStretchableFont()
348    {
349        initialize();
350        if(instance.distanceNarrow == null)
351        {
352            try {
353                instance.distanceNarrow = new TextCellFactory().defaultNarrowDistanceFieldFont();
354            } catch (Exception e) {
355                e.printStackTrace();
356            }
357        }
358        if(instance.distanceNarrow != null)
359            return instance.distanceNarrow.copy();
360        return null;
361
362    }
363
364    /**
365     * Returns a TextCellFactory already configured to use a narrow typewriter-style serif font that should scale
366     * cleanly to many sizes. Caches the result for later calls.
367     * <br>
368     * This creates a TextCellFactory instead of a BitmapFont because it needs to set some extra information so the
369     * distance field font technique this uses can work.
370     * @return the TextCellFactory object that can represent many sizes of the font CM-Custom.ttf
371     */
372    public static TextCellFactory getStretchableTypewriterFont()
373    {
374        initialize();
375        if(instance.typewriterDistanceNarrow == null)
376        {
377            try {
378                instance.typewriterDistanceNarrow = new TextCellFactory()
379                        .fontDistanceField(distanceFieldTypewriterNarrow, distanceFieldTypewriterNarrowTexture);
380            } catch (Exception e) {
381                e.printStackTrace();
382            }
383        }
384        if(instance.typewriterDistanceNarrow != null)
385            return instance.typewriterDistanceNarrow.copy();
386        return null;
387    }
388
389    /**
390     * Returns a TextCellFactory already configured to use a variable-width serif font that should look like the serif
391     * fonts used in many novels' main texts, and that should scale cleanly to many sizes. Meant to be used in variable-
392     * width displays like TextPanel. Caches the result for later calls.
393     * <br>
394     * This creates a TextCellFactory instead of a BitmapFont because it needs to set some extra information so the
395     * distance field font technique this uses can work.
396     * @return the TextCellFactory object that can represent many sizes of the font Gentium, by SIL
397     */
398    public static TextCellFactory getStretchablePrintFont() {
399        initialize();
400        if (instance.distancePrint == null) {
401            try {
402                instance.distancePrint = new TextCellFactory().fontDistanceField(distanceFieldPrint, distanceFieldPrintTexture)
403                        .setSmoothingMultiplier(0.4f).height(30).width(7);
404            } catch (Exception e) {
405                e.printStackTrace();
406            }
407        }
408        if(instance.distancePrint != null)
409            return instance.distancePrint.copy();
410        return null;
411    }
412
413    /**
414     * Returns a TextCellFactory already configured to use a variable-width sans-serif font that currently looks
415     * slightly jumbled without certain layout features. Meant to be used in variable-width displays like TextPanel, but
416     * currently you should prefer getStretchablePrintFont() for legibility. Caches the result for later calls.
417     * <br>
418     * This creates a TextCellFactory instead of a BitmapFont because it needs to set some extra information so the
419     * distance field font technique this uses can work.
420     * @return the TextCellFactory object that can represent many sizes of the font Noto Sans, by Google
421     */
422    public static TextCellFactory getStretchableCleanFont() {
423        initialize();
424        if (instance.distanceClean == null) {
425            try {
426                instance.distanceClean = new TextCellFactory().fontDistanceField(distanceFieldClean, distanceFieldCleanTexture)
427                        .setSmoothingMultiplier(0.4f).height(30).width(7);
428            } catch (Exception e) {
429                e.printStackTrace();
430            }
431        }
432        if(instance.distanceClean != null)
433            return instance.distanceClean.copy();
434        return null;
435    }
436
437    /**
438     * Gets an image of a (squid-like, for SquidLib) tentacle, 32x32px.
439     * Source is public domain: http://opengameart.org/content/496-pixel-art-icons-for-medievalfantasy-rpg
440     * Created by Henrique Lazarini (7Soul1, http://7soul1.deviantart.com/ )
441     * @return a TextureRegion containing an image of a tentacle.
442     */
443    public static TextureRegion getTentacle()
444    {
445        initialize();
446        if(instance.tentacle == null || instance.tentacleRegion == null)
447        {
448            try {
449                instance.tentacle = new Texture(Gdx.files.internal("Tentacle.png"));
450                instance.tentacleRegion = new TextureRegion(instance.tentacle);
451            } catch (Exception ignored) {
452            }
453        }
454        return instance.tentacleRegion;
455    }
456
457
458    /**
459     * Gets a TextureAtlas containing many icons with a distance field effect applied, allowing them to be used with
460     * "stretchable" fonts and be resized in the same way. These will not look as-expected if stretchable fonts are not
461     * in use, and will seem hazy and indistinct if the shader hasn't been set up for a distance field effect by
462     * TextCellFactory (which stretchable fonts will do automatically). The one page of the TextureAtlas is 2048x2048,
463     * which may be too large for some old, low-end Android phones, and possibly integrated graphics with fairly old
464     * processors on desktop. It has over 2000 icons.
465     * <br>
466     * The icons are CC-BY and the license is distributed with them, though the icons are not necessarily included with
467     * SquidLib. If you use the icon atlas, be sure to include icons-license.txt with it and reference it with your
468     * game's license and/or credits information.
469     * @return a TextureAtlas containing over 2000 icons with a distance field effect
470     */
471    public static TextureAtlas getIconAtlas()
472    {
473        initialize();
474        if(instance.iconAtlas == null)
475        {
476            try {
477                instance.iconAtlas = new TextureAtlas(Gdx.files.internal("icons.atlas"));
478            } catch (Exception ignored) {
479            }
480        }
481        return instance.iconAtlas;
482    }
483
484    /**
485     * This is a static global StatefulRNG that's meant for usage in cases where the seed does not matter and any
486     * changes to this RNG's state will not change behavior elsewhere in the program; this means the GUI mainly.
487     */
488    public static StatefulRNG getGuiRandom()
489    {
490        initialize();
491        if(instance.guiRandom == null)
492        {
493            instance.guiRandom =  new StatefulRNG();
494        }
495        return instance.guiRandom;
496    }
497    /**
498     * This is a static global SquidColorCenter that can be used in places that just need an existing object that can do
499     * things like analyze hue or saturation of a color.
500     */
501    public static SquidColorCenter getSCC()
502    {
503        initialize();
504        if(instance.scc == null)
505        {
506            instance.scc =  new SquidColorCenter();
507        }
508        return instance.scc;
509    }
510
511    /**
512     * Special symbols that can be used as icons if you use the narrow default font.
513     */
514    public static final String narrowFontSymbols = "ሀሁሂሃሄህሆሇለሉሊላሌልሎሏሐሑሒሓሔሕሖሗመሙሚማሜ",
515                                  narrowFontAll = " !\"#$%&'()*+,-./0123\n" +
516                                          "456789:;<=>?@ABCDEFG\n" +
517                                          "HIJKLMNOPQRSTUVWXYZ[\n" +
518                                          "\\]^_`abcdefghijklmno\n" +
519                                          "pqrstuvwxyz{|}~¡¢£¤¥\n" +
520                                          "¦§¨©ª«¬\u00AD®¯°±²³´µ¶·¸¹\n" +
521                                          "º»¼½¾¿×ß÷øɍɎሀሁሂሃሄህሆሇ\n" +
522                                          "ለሉሊላሌልሎሏሐሑሒሓሔሕሖሗመሙሚማ\n" +
523                                          "ሜẞ‐‒–—―‖‗‘’‚‛“”„‟†‡•\n" +
524                                          "…‧‹›€™"+
525                                          "←↑→↓↷↺↻"+ // left, up, right, down, "tap", "counterclockwise", "clockwise"
526                                          "∀∁∂∃∄∅∆\n" +
527                                          "∇∈∉∋∌∎∏∐∑−∓∔∕∖∘∙√∛∜∝\n" +
528                                          "∞∟∠∡∢∣∤∥∦∧∨∩∪∫∬∮∯∱∲∳\n" +
529                                          "∴∵∶∷≈≋≠≡≢≣≤≥≦≧≨≩≪≫─━\n" +
530                                          "│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕\n" +
531                                          "┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩\n" +
532                                          "┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽\n" +
533                                          "┾┿╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏═║\n" +
534                                          "╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥\n" +
535                                          "╦╧╨╩╪╫╬╭╮╯╰╱╲╳╴╵╶╷╸╹\n" +
536                                          "╺╻╼╽╾╿▁▄▅▆▇█▌▐░▒▓▔▖▗\n" +
537                                          "▘▙▚▛▜▝▞▟";
538
539    /**
540     * Called when the {@link Application} is about to pause
541     */
542    @Override
543    public void pause() {
544        if(narrow1 != null) {
545            narrow1.dispose();
546            narrow1 = null;
547        }
548        if(narrow2 != null) {
549            narrow2.dispose();
550            narrow2 = null;
551        }
552        if(narrow3 != null) {
553            narrow3.dispose();
554            narrow3 = null;
555        }
556        if(smooth1 != null) {
557            smooth1.dispose();
558            smooth1 = null;
559        }
560        if(smooth2 != null) {
561            smooth2.dispose();
562            smooth2 = null;
563        }
564        if(square1 != null) {
565            square1.dispose();
566            square1 = null;
567        }
568        if(square2 != null) {
569            square2.dispose();
570            square1 = null;
571        }
572        if(smoothSquare != null) {
573            smoothSquare.dispose();
574            smoothSquare = null;
575        }
576        if(smoothSquareOld != null) {
577            smoothSquareOld.dispose();
578            smoothSquareOld = null;
579        }
580        if(distanceSquare != null) {
581            distanceSquare.dispose();
582            distanceSquare = null;
583        }
584        if(distanceNarrow != null) {
585            distanceNarrow.dispose();
586            distanceNarrow = null;
587        }
588        if(typewriterDistanceNarrow != null) {
589            typewriterDistanceNarrow.dispose();
590            typewriterDistanceNarrow = null;
591        }
592        if(distanceClean != null) {
593            distanceClean.dispose();
594            distanceClean = null;
595        }
596        if(distancePrint != null) {
597            distancePrint.dispose();
598            distancePrint = null;
599        }
600        if (unicode1 != null) {
601            unicode1.dispose();
602            unicode1 = null;
603        }
604        if (unicode2 != null) {
605            unicode2.dispose();
606            unicode2 = null;
607        }
608        if(tentacle != null) {
609            tentacle.dispose();
610            tentacle = null;
611        }
612        if(iconAtlas != null) {
613            iconAtlas.dispose();
614            iconAtlas = null;
615        }
616    }
617
618    /**
619     * Called when the Application is about to be resumed
620     */
621    @Override
622    public void resume() {
623        initialize();
624    }
625
626    /**
627     * Called when the {@link Application} is about to be disposed
628     */
629    @Override
630    public void dispose() {
631        pause();
632        Gdx.app.removeLifecycleListener(this);
633        instance = null;
634    }
635}