Reworked a couple systems.
-Added: STBImage support. -Added: Dynamic Font Loader that supports Bitmap/TTF fonts (ttf using java not STB, because small deadline) -Added: NativeMemory Loader as optional parser into asset loading. -Reworked: How Images are made reloadable. -Added: A dynamic AtlasBuilder
This commit is contained in:
parent
9c947c4898
commit
4763e62b53
|
@ -64,5 +64,5 @@ dependencies {
|
|||
compile 'com.google.code.gson:gson:2.8.6'
|
||||
|
||||
//Primitive Collections
|
||||
compile 'de.speiger:Primitive-Collections:0.3.5'
|
||||
compile 'de.speiger:Primitive-Collections:0.4.0'
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package speiger.src.coreengine.application;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.ObjLongConsumer;
|
||||
|
||||
|
@ -11,6 +12,7 @@ import speiger.src.coreengine.assets.AssetManager;
|
|||
import speiger.src.coreengine.assets.reloader.ResourceReloader;
|
||||
import speiger.src.coreengine.rendering.gui.GuiManager;
|
||||
import speiger.src.coreengine.rendering.gui.base.DebugOverlay;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.provider.FontManager;
|
||||
import speiger.src.coreengine.rendering.input.Keyboard;
|
||||
import speiger.src.coreengine.rendering.input.Mouse;
|
||||
import speiger.src.coreengine.rendering.input.camera.Camera;
|
||||
|
@ -18,7 +20,8 @@ import speiger.src.coreengine.rendering.input.window.Window;
|
|||
import speiger.src.coreengine.rendering.input.window.WindowProvider;
|
||||
import speiger.src.coreengine.rendering.shader.ProjectionBuffer;
|
||||
import speiger.src.coreengine.rendering.shader.ShaderTracker;
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
import speiger.src.coreengine.rendering.textures.base.NativeMemoryParser;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
import speiger.src.coreengine.rendering.utils.Cursor;
|
||||
import speiger.src.coreengine.utils.counters.timers.FPSTimer;
|
||||
import speiger.src.coreengine.utils.eventbus.EventBus;
|
||||
|
@ -41,6 +44,7 @@ public abstract class Application
|
|||
|
||||
protected ResourceReloader reloader = new ResourceReloader();
|
||||
protected AssetManager assetManager;
|
||||
protected FontManager fonts = new FontManager();
|
||||
protected ProjectionBuffer projectionBuffer;
|
||||
protected GuiManager uiManager;
|
||||
|
||||
|
@ -49,10 +53,11 @@ public abstract class Application
|
|||
GLFWErrorCallback.createPrint(System.err).set();
|
||||
if(!GLFW.glfwInit()) throw new IllegalStateException("OpenGL can't be loaded");
|
||||
provider.init();
|
||||
boolean initEarly = earlyUILoad();
|
||||
try
|
||||
{
|
||||
mainWindow = createWindow(provider);
|
||||
mainWindow.finishWindow();
|
||||
if(initEarly) mainWindow.finishWindow();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -68,6 +73,7 @@ public abstract class Application
|
|||
file = file.getName().endsWith(".jar") ? file : new File("bin/main");
|
||||
internalInit(file);
|
||||
init(file);
|
||||
if(!initEarly) mainWindow.finishWindow();
|
||||
executor.start(mainWindow);
|
||||
mainWindow.destroy();
|
||||
reloader.deleteResources();
|
||||
|
@ -78,8 +84,12 @@ public abstract class Application
|
|||
protected void internalInit(File file)
|
||||
{
|
||||
assetManager = reloader.addReloadableResource(new AssetManager(file), true);
|
||||
assetManager.registerAssetParser(ByteBuffer.class, new NativeMemoryParser());
|
||||
reloader.addReloadableResource(fonts);
|
||||
fonts.setAssetManager(assetManager);
|
||||
ShaderTracker.INSTANCE.init(assetManager);
|
||||
TextureManager.INSTANCE.init(assetManager);
|
||||
preinit();
|
||||
reloader.addReloadableResource(ShaderTracker.INSTANCE);
|
||||
reloader.addReloadableResource(TextureManager.INSTANCE);
|
||||
camera = new Camera(mainWindow);
|
||||
|
@ -95,8 +105,10 @@ public abstract class Application
|
|||
public void addExtraTickRates(IntConsumer ticks) {};
|
||||
public void addExtraTimers(ObjLongConsumer<String> profiler) {};
|
||||
public boolean initUI() { return true; }
|
||||
public boolean earlyUILoad() { return true; }
|
||||
public DebugOverlay createCustomDebug() { return null; }
|
||||
public abstract Window createWindow(WindowProvider provider) throws Exception;
|
||||
public void preinit() {}
|
||||
public abstract void init(File file);
|
||||
public abstract void update();
|
||||
public abstract void render(float particalTicks);
|
||||
|
|
|
@ -13,7 +13,7 @@ public class BaseUIManager extends GuiManager
|
|||
|
||||
public BaseUIManager(Application application)
|
||||
{
|
||||
super(application.mainWindow, application.eventBus);
|
||||
super(application.mainWindow, application.eventBus, application.fonts);
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ import java.util.function.Function;
|
|||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
|
||||
|
||||
public final class AssetLocation
|
||||
public final class AssetLocation implements Comparable<AssetLocation>
|
||||
{
|
||||
static final Map<String, AssetLocation> LOCATION = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<String, AssetLocation>());
|
||||
static final Map<String, AssetLocation> LOCATION = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>());
|
||||
static final Function<String, AssetLocation> BUILDER = AssetLocation::compute;
|
||||
final String domain;
|
||||
final String location;
|
||||
|
@ -74,6 +74,13 @@ public final class AssetLocation
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AssetLocation o)
|
||||
{
|
||||
int result = domain.compareToIgnoreCase(o.domain);
|
||||
return result != 0 ? result : location.compareToIgnoreCase(location);
|
||||
}
|
||||
|
||||
public boolean matches(AssetLocation location)
|
||||
{
|
||||
return location.domain.equals(domain) && location.location.equals(this.location);
|
||||
|
|
|
@ -5,21 +5,25 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap.Entry;
|
||||
import speiger.src.collections.objects.sets.ObjectLinkedOpenHashSet;
|
||||
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
|
||||
import speiger.src.coreengine.assets.impl.FolderAssetPackage;
|
||||
import speiger.src.coreengine.assets.impl.ZipAssetPackage;
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
|
||||
public class AssetManager implements IReloadableResource
|
||||
{
|
||||
Map<String, DomainAssets> domains = new Object2ObjectLinkedOpenHashMap<>();
|
||||
Object2ObjectMap<String, DomainAssets> domains = new Object2ObjectLinkedOpenHashMap<>();
|
||||
Object2ObjectMap<Class<?>, IAssetParser<?>> parsers = new Object2ObjectLinkedOpenHashMap<>();
|
||||
Path path;
|
||||
|
||||
|
@ -121,11 +125,21 @@ public class AssetManager implements IReloadableResource
|
|||
DomainAssets asset = domains.get(location.getDomain());
|
||||
if(asset == null)
|
||||
{
|
||||
throw new FileNotFoundException("File["+location.toString()+"] not found");
|
||||
throw new FileNotFoundException("Domain & File["+location.toString()+"] not found");
|
||||
}
|
||||
return asset.getAllAssets(location);
|
||||
}
|
||||
|
||||
public Collection<AssetLocation> gatherAssets(String location, int maxDepth, Predicate<String> filter)
|
||||
{
|
||||
Set<AssetLocation> result = new ObjectLinkedOpenHashSet<>();
|
||||
for(Entry<String, DomainAssets> asset : Object2ObjectMaps.fastIterable(domains))
|
||||
{
|
||||
asset.getValue().gatherAssets(AssetLocation.of(asset.getKey(), location), maxDepth, filter, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isZipFile(Path file)
|
||||
{
|
||||
try(ZipFile zip = new ZipFile(file.toFile())) { return true; }
|
||||
|
@ -185,5 +199,13 @@ public class AssetManager implements IReloadableResource
|
|||
}
|
||||
return new MultiAsset(assets.toArray(new IAsset[assets.size()]));
|
||||
}
|
||||
|
||||
public void gatherAssets(AssetLocation folder, int maxDepth, Predicate<String> filter, Collection<AssetLocation> result)
|
||||
{
|
||||
for(IAssetPackage entry : packages)
|
||||
{
|
||||
entry.getAllAssets(folder, filter, maxDepth, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.BufferedReader;
|
|||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
|
@ -16,11 +17,13 @@ public interface IAsset extends Closeable
|
|||
|
||||
public InputStream getStream() throws IOException;
|
||||
|
||||
public BufferedImage getTexture() throws Exception;
|
||||
public ByteBuffer getBytes() throws IOException;
|
||||
|
||||
public BufferedReader getStringReader() throws IOException;
|
||||
|
||||
public JsonObject getJsonObject() throws IOException;
|
||||
|
||||
public BufferedImage getTexture() throws Exception;
|
||||
|
||||
public <T> T getCustom(Class<T> clz) throws IOException;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package speiger.src.coreengine.assets;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface IAssetPackage
|
||||
{
|
||||
public void setParsers(Function<Class<?>, IAssetParser<?>> parsers);
|
||||
public List<String> getDomains();
|
||||
public IAsset getAsset(AssetLocation location);
|
||||
public void getAllAssets(AssetLocation folder, Predicate<String> fileNames, int maxDepth, Collection<AssetLocation> result);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package speiger.src.coreengine.assets;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface IAssetParser<T>
|
||||
{
|
||||
public T parseAsset(Path path, Consumer<Closeable> autoCloser);
|
||||
public T parseAsset(Path path, Consumer<Closeable> autoCloser) throws IOException;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.BufferedReader;
|
|||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
@ -76,6 +77,12 @@ public class FolderAsset implements IAsset
|
|||
return markClosed(Files.newInputStream(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer getBytes() throws IOException
|
||||
{
|
||||
return ByteBuffer.wrap(Files.readAllBytes(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getTexture() throws Exception
|
||||
{
|
||||
|
|
|
@ -5,14 +5,18 @@ import java.io.IOException;
|
|||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.assets.IAssetPackage;
|
||||
import speiger.src.coreengine.assets.IAssetParser;
|
||||
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
|
||||
|
||||
public class FolderAssetPackage implements IAssetPackage
|
||||
{
|
||||
|
@ -59,4 +63,22 @@ public class FolderAssetPackage implements IAssetPackage
|
|||
Path path = baseFolder.resolve(location.getActualLocation());
|
||||
return Files.exists(path) ? new FolderAsset(location, path, parsers) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAllAssets(AssetLocation folder, Predicate<String> fileNames, int maxDepth, Collection<AssetLocation> result)
|
||||
{
|
||||
Path start = baseFolder.resolve(folder.getActualLocation());
|
||||
if(Files.notExists(start)) return;
|
||||
try(Stream<Path> stream = Files.walk(start, maxDepth).filter(Files::isRegularFile).filter(T -> fileNames.test(T.getFileName().toString())))
|
||||
{
|
||||
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
||||
{
|
||||
result.add(folder.subAsset(start.relativize(path).toString()));
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Function;
|
||||
|
@ -71,6 +72,12 @@ public class ZipAsset implements IAsset
|
|||
return Files.newInputStream(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer getBytes() throws IOException
|
||||
{
|
||||
return ByteBuffer.wrap(Files.readAllBytes(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getTexture() throws Exception
|
||||
{
|
||||
|
|
|
@ -7,15 +7,19 @@ import java.nio.file.FileSystem;
|
|||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.assets.IAssetPackage;
|
||||
import speiger.src.coreengine.assets.IAssetParser;
|
||||
import speiger.src.coreengine.utils.collections.iterators.IterableWrapper;
|
||||
|
||||
public class ZipAssetPackage implements IAssetPackage
|
||||
{
|
||||
|
@ -90,4 +94,23 @@ public class ZipAssetPackage implements IAssetPackage
|
|||
}
|
||||
catch(Exception e) { return null; }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAllAssets(AssetLocation folder, Predicate<String> fileNames, int maxDepth, Collection<AssetLocation> result)
|
||||
{
|
||||
try(FileSystem system = FileSystems.newFileSystem(baseFolder, null))
|
||||
{
|
||||
Path start = system.getPath(folder.getActualLocation());
|
||||
if(Files.notExists(start)) return;
|
||||
try(Stream<Path> stream = Files.walk(start, maxDepth).filter(Files::isRegularFile).filter(T -> fileNames.test(T.getFileName().toString())))
|
||||
{
|
||||
for(Path path : IterableWrapper.wrap(stream.iterator()))
|
||||
{
|
||||
result.add(folder.subAsset(start.relativize(path).toString()));
|
||||
}
|
||||
}
|
||||
catch(IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
catch(Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import speiger.src.collections.objects.sets.ObjectLinkedOpenHashSet;
|
|||
|
||||
public class ResourceReloader
|
||||
{
|
||||
Set<IReloadableResource> resources = new ObjectLinkedOpenHashSet<IReloadableResource>();
|
||||
Set<IReloadableResource> resources = new ObjectLinkedOpenHashSet<>();
|
||||
boolean globalRemoval = false;
|
||||
boolean reloading = false;
|
||||
|
||||
|
|
|
@ -316,6 +316,16 @@ public class ColorObject
|
|||
return "Color[r=" + getRedFloat() + ", g=" + getGreenFloat() + ", b=" + getBlueFloat() + ", a=" + getAlphaFloat() + "]";
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(int color, boolean alpha)
|
||||
{
|
||||
byte[] data = new byte[alpha ? 4 : 3];
|
||||
data[0] = (byte)((color >> 16) & 0xFF);
|
||||
data[1] = (byte)((color >> 8) & 0xFF);
|
||||
data[2] = (byte)(color & 0xFF);
|
||||
if(alpha) data[3] = (byte)((color >> 24) & 0xFF);
|
||||
return data;
|
||||
}
|
||||
|
||||
public static void pack(int color, boolean alpha, ByteBuffer buffer)
|
||||
{
|
||||
buffer.put((byte)((color >> 16) & 0xFF)).put((byte)((color >> 8) & 0xFF)).put((byte)(color & 0xFF));
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
package speiger.src.coreengine.rendering.gui;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import speiger.src.collections.chars.maps.impl.hash.Char2ObjectOpenHashMap;
|
||||
import speiger.src.collections.chars.maps.interfaces.Char2ObjectMap;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.FontRenderer;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
||||
import speiger.src.coreengine.rendering.textures.SimpleTexture;
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
|
||||
public class FontLoader
|
||||
{
|
||||
public static FontRenderer createFont(AssetLocation location, String name)
|
||||
{
|
||||
return createFont(location, name, 0.35F);
|
||||
}
|
||||
|
||||
public static FontRenderer createFont(AssetLocation location, String name, float scale)
|
||||
{
|
||||
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location.subAsset(name+".fnt")))
|
||||
{
|
||||
Char2ObjectMap<CharInstance>[] maps = new Char2ObjectMap[]{new Char2ObjectOpenHashMap<CharInstance>(), new Char2ObjectOpenHashMap<CharInstance>()};
|
||||
BufferedReader reader = asset.getStringReader();
|
||||
FontInfo info = new FontInfo(convert(reader.readLine().split(", ")));
|
||||
String value = null;
|
||||
while((value = getNextValidLine(reader)) != null)
|
||||
{
|
||||
Map<String, Integer> dataMap = convert(value.split(", "));
|
||||
CharInstance instance = createChar(dataMap, info);
|
||||
instance.scale(scale);
|
||||
maps[instance.isBold() ? 1 : 0].putIfAbsent(instance.getCharacter(), instance);
|
||||
}
|
||||
info.scale(scale);
|
||||
return new FontRenderer(maps, new SimpleTexture(location.subAsset(name+"-Texture.png")), info.fontHeight, info.lineHeight);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static String getNextValidLine(BufferedReader reader) throws Exception
|
||||
{
|
||||
String line = reader.readLine();
|
||||
if(line == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if(line.isEmpty() || line.startsWith("//"))
|
||||
{
|
||||
return getNextValidLine(reader);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
static CharInstance createChar(Map<String, Integer> data, FontInfo info)
|
||||
{
|
||||
char character = (char)data.get("letter").intValue();
|
||||
int minX = data.get("minX");
|
||||
int minY = data.get("minY");
|
||||
int maxX = data.get("maxX");
|
||||
int maxY = data.get("maxY");
|
||||
return new CharInstance(character, maxX - minX, maxY - minY, info.getTextureU(minX), info.getTextureV(minY), info.getTextureU(maxX), info.getTextureV(maxY), maxX - minX, data.getOrDefault("bold", 0).intValue() == 1);
|
||||
}
|
||||
|
||||
static Map<String, Integer> convert(String[] data)
|
||||
{
|
||||
Map<String, Integer> map = new HashMap<String, Integer>();
|
||||
for(String s : data)
|
||||
{
|
||||
int index = s.indexOf("=");
|
||||
if(index != -1)
|
||||
{
|
||||
String[] split = s.split("=");
|
||||
map.put(split[0], Integer.parseInt(split[1]));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static class FontInfo
|
||||
{
|
||||
int height;
|
||||
int width;
|
||||
float fontHeight;
|
||||
float lineHeight;
|
||||
|
||||
public FontInfo(Map<String, Integer> data)
|
||||
{
|
||||
width = data.get("textureWidth");
|
||||
height = data.get("textureHeight");
|
||||
fontHeight = data.get("fontHeight");
|
||||
lineHeight = data.get("base");
|
||||
}
|
||||
|
||||
public void scale(float scale)
|
||||
{
|
||||
fontHeight *= scale;
|
||||
lineHeight *= scale;
|
||||
}
|
||||
|
||||
public float getTextureU(float value)
|
||||
{
|
||||
return value / width;
|
||||
}
|
||||
|
||||
public float getTextureV(float value)
|
||||
{
|
||||
return value / height;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import speiger.src.coreengine.rendering.gui.base.DebugOverlay;
|
|||
import speiger.src.coreengine.rendering.gui.renderer.FontRenderer;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.GuiShader;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.UIRenderer;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.provider.FontManager;
|
||||
import speiger.src.coreengine.rendering.input.events.KeyEvent.CharTypeEvent;
|
||||
import speiger.src.coreengine.rendering.input.events.KeyEvent.KeyPressEvent;
|
||||
import speiger.src.coreengine.rendering.input.events.MouseEvent;
|
||||
|
@ -31,12 +32,13 @@ public abstract class GuiManager implements IWindowListener
|
|||
protected ScaledResolution res;
|
||||
protected long globalClock = 0L;
|
||||
protected boolean isReloading = false;
|
||||
protected FontRenderer font = FontLoader.createFont(AssetLocation.of("font"), "Roboto-Font");
|
||||
protected FontRenderer font;
|
||||
protected GuiShader shader = ShaderTracker.INSTANCE.register(GuiShader::create, T -> shader = T);
|
||||
|
||||
public GuiManager(Window window, EventBus bus)
|
||||
public GuiManager(Window window, EventBus bus, FontManager manager)
|
||||
{
|
||||
this.window = window;
|
||||
font = manager.loadFont(AssetLocation.of("font/roboto.json"), 18.5F);
|
||||
bus.register(MouseEvent.class, this::onMouseEvent);
|
||||
bus.register(KeyPressEvent.class, (T) -> T.setCanceled(onKeyPressed(T.key)));
|
||||
bus.register(CharTypeEvent.class, (T) -> T.setCanceled(onCharTyped(T.character, T.codePoint)));
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
package speiger.src.coreengine.rendering.gui;
|
||||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.SimpleTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
|
||||
public class UITextures
|
||||
{
|
||||
public static final AssetLocation TEXTURE_LOCATION = AssetLocation.of("textures");
|
||||
|
||||
// public static final ITexture OK_SYMBOL = new SimpleTexture(sub("okSymbol.png"));
|
||||
// public static final ITexture CANCLE_SYMBOL = new SimpleTexture(sub("cancelSymbol.png"));
|
||||
public static final ITexture COLOR_WHEEL = new SimpleTexture(sub("colorWheel.png"));
|
||||
public static final ITexture COLOR_WHEEL = ITexture.simple(sub("colorWheel.png")).makeReloadable();
|
||||
|
||||
public static AssetLocation sub(String name)
|
||||
{
|
||||
|
||||
public static ITexture createReloadable(String name) {
|
||||
return ITexture.simple(sub(name)).makeReloadable();
|
||||
}
|
||||
|
||||
public static ITexture create(String name) {
|
||||
return ITexture.simple(sub(name));
|
||||
}
|
||||
|
||||
public static AssetLocation sub(String name) {
|
||||
return TEXTURE_LOCATION.subAsset(name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package speiger.src.coreengine.rendering.gui.components;
|
|||
|
||||
import speiger.src.coreengine.math.misc.ColorObject;
|
||||
import speiger.src.coreengine.rendering.gui.GuiComponent;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
|
||||
public class IconComponent extends GuiComponent
|
||||
{
|
||||
|
|
|
@ -52,6 +52,7 @@ public class ListComponent<T extends IListEntry> extends GuiComponent
|
|||
protected int selectionMode = 1;
|
||||
protected int updateMode = 1;
|
||||
protected float entryHeight;
|
||||
protected float cachedWidth = 0F;
|
||||
protected ScrollBarComponent verticalBar = new ScrollBarComponent(ColorObject.LIGHT_GRAY);
|
||||
protected ScrollBarComponent horizontalBar = new ScrollBarComponent(ColorObject.LIGHT_GRAY).setHorizontal(true);
|
||||
protected Vec2i lastMouse = Vec2i.newMutable();
|
||||
|
@ -416,6 +417,11 @@ public class ListComponent<T extends IListEntry> extends GuiComponent
|
|||
return rangeIterator(start, MathUtils.clamp(0, entries.size() - 1, start + getIndexWidth()));
|
||||
}
|
||||
|
||||
public float getCachedWidth()
|
||||
{
|
||||
return cachedWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void repaint()
|
||||
{
|
||||
|
@ -434,6 +440,7 @@ public class ListComponent<T extends IListEntry> extends GuiComponent
|
|||
{
|
||||
width = Math.max(width, entries.get(i).getWidth());
|
||||
}
|
||||
this.cachedWidth = width;
|
||||
boolean lastVertical = this.verticalBar.isInUse();
|
||||
boolean lastHorizontal = this.horizontalBar.isInUse();
|
||||
verticalBar.setScrollMax(MathUtils.ceil(this.entries.size() * entryHeight));
|
||||
|
|
|
@ -2,7 +2,7 @@ package speiger.src.coreengine.rendering.gui.components.icon;
|
|||
|
||||
import speiger.src.coreengine.math.misc.ColorObject;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.UIRenderer;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
|
||||
public class TexturedIcon implements IIcon
|
||||
{
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
package speiger.src.coreengine.rendering.gui.helper;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
||||
import speiger.src.coreengine.rendering.textures.custom.TextureAtlas;
|
||||
import speiger.src.coreengine.rendering.textures.custom.TextureAtlas.AtlasEntry;
|
||||
import speiger.src.coreengine.rendering.textures.custom.TextureAtlas.Builder;
|
||||
|
||||
public class FontBuilder
|
||||
{
|
||||
public static final int LITERAL = 1;
|
||||
public static final int PLAIN = 2;
|
||||
public static final int BOLD = 4;
|
||||
|
||||
public static ObjectObjectPair<BufferedImage, JsonObject> createBitmapFont(InputStream stream, float size)
|
||||
{
|
||||
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> result = createBitmapFont(stream, "ISO-8859-1", PLAIN | BOLD, size);
|
||||
if(result == null) return null;
|
||||
JsonArray array = new JsonArray();
|
||||
result.getValue().forEach(T -> array.add(T.seralize()));
|
||||
JsonObject info = new JsonObject();
|
||||
ObjectObjectPair<Vec2i, BufferedImage> key = result.getKey();
|
||||
info.addProperty("width", key.getValue().getWidth());
|
||||
info.addProperty("height", key.getValue().getHeight());
|
||||
info.addProperty("base", key.getKey().getX());
|
||||
info.addProperty("charHeight", key.getKey().getY());
|
||||
info.addProperty("tabs", 4);
|
||||
|
||||
JsonObject data = new JsonObject();
|
||||
data.addProperty("type", "bitmap");
|
||||
data.addProperty("file", "?");
|
||||
data.add("info", info);
|
||||
data.add("chars", array);
|
||||
return ObjectObjectPair.of(key.getValue(), data);
|
||||
}
|
||||
|
||||
public static ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> createBitmapFont(InputStream ttf, String characters, int flags, float size)
|
||||
{
|
||||
try
|
||||
{
|
||||
Map<AssetLocation, CharData> toDraw = new Object2ObjectLinkedOpenHashMap<>();
|
||||
Builder builder = TextureAtlas.create();
|
||||
|
||||
Consumer<CharData> data = T -> {
|
||||
AssetLocation location = T.asLocation();
|
||||
toDraw.put(location, T);
|
||||
if(T.width > 0 && !builder.add(location, T.width, T.getExtraY(T.height))) throw new IllegalStateException("Character: " + location + " isnt Accepted, W=" + T.width + ", H=" + T.height);
|
||||
};
|
||||
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, ttf).deriveFont(size);
|
||||
String validChars = (flags & LITERAL) != 0 ? characters : getChars(characters, font);
|
||||
|
||||
if((flags & PLAIN) != 0) loadFontData(font, validChars, data);
|
||||
if((flags & BOLD) != 0) loadFontData(font.deriveFont(Font.BOLD), validChars, data);
|
||||
|
||||
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> result = ObjectObjectPair.mutableValue(new ObjectArrayList<>());
|
||||
|
||||
builder.buildHollow((K, V) -> {
|
||||
BufferedImage image = new BufferedImage(K.getX(), K.getY(), BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = image.createGraphics();
|
||||
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
|
||||
graphics.setFont(font);
|
||||
|
||||
FontMetrics metric = graphics.getFontMetrics();
|
||||
int extra = 0;
|
||||
|
||||
for(AtlasEntry entry : V)
|
||||
{
|
||||
CharData pair = toDraw.remove(entry.getLocation());
|
||||
extra = pair.extraY;
|
||||
graphics.setFont(pair.getFont());
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.drawString(Character.toString(pair.getLetter()), entry.getX()-pair.xOffset, pair.getExtraY(entry.getY()+metric.getAscent()));
|
||||
result.getValue().add(new WrittenChar(pair.getLetter(), entry.getX(), entry.getY(), entry.getWidth(), entry.getHeight(), pair.isBold()));
|
||||
}
|
||||
toDraw.values().forEach(T -> result.getValue().add(new WrittenChar(T.getLetter(), 0, 0, 0, 0, T.isBold())));
|
||||
result.setKey(ObjectObjectPair.of(Vec2i.newVec(metric.getAscent()+extra, metric.getHeight()+extra), image));
|
||||
graphics.dispose();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static float convert(float pos, float width)
|
||||
{
|
||||
return pos / width;
|
||||
}
|
||||
|
||||
private static String getChars(String s, Font font)
|
||||
{
|
||||
CharsetEncoder encoder = Charset.forName(s).newEncoder();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for(char c = 0;c < Character.MAX_VALUE;c++)
|
||||
{
|
||||
if(encoder.canEncode(c) && font.canDisplay(c)) builder.append(c);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static void loadFontData(Font font, String chars, Consumer<CharData> listener)
|
||||
{
|
||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = (Graphics2D)image.getGraphics();
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
graphics.setFont(font);
|
||||
FontMetrics metric = graphics.getFontMetrics();
|
||||
int extraHeight = 0;
|
||||
List<CharData> data = new ObjectArrayList<>();
|
||||
for(char letter : chars.toCharArray())
|
||||
{
|
||||
Rectangle rect = font.layoutGlyphVector(graphics.getFontRenderContext(), new char[] {letter }, 0, 1, 0).getGlyphPixelBounds(0, graphics.getFontRenderContext(), 0.0F, 0.0F);
|
||||
extraHeight = Math.min(extraHeight, rect.y);
|
||||
data.add(new CharData(font, letter, rect, metric.charWidth(letter), metric.getHeight(), font.isBold()));
|
||||
}
|
||||
extraHeight = -(extraHeight+metric.getAscent());
|
||||
for(int i = 0,m=data.size();i<m;listener.accept(data.get(i++).offset(extraHeight)));
|
||||
graphics.dispose();
|
||||
}
|
||||
|
||||
public static class WrittenChar
|
||||
{
|
||||
char letter;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
boolean bold;
|
||||
|
||||
public WrittenChar(char letter, int x, int y, int width, int height, boolean bold)
|
||||
{
|
||||
this.letter = letter;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public JsonObject seralize()
|
||||
{
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("char", (int)letter);
|
||||
obj.addProperty("minX", x);
|
||||
obj.addProperty("minY", y);
|
||||
obj.addProperty("maxX", x+width);
|
||||
obj.addProperty("maxY", y+height);
|
||||
obj.addProperty("bold", bold);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public CharInstance create(int textureWidth, int textureHeight)
|
||||
{
|
||||
return new CharInstance(letter, width, height, convert(x, textureWidth), convert(y, textureHeight), convert(x+width, textureWidth), convert(y+height, textureHeight), width, bold);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CharData
|
||||
{
|
||||
Font font;
|
||||
char letter;
|
||||
int xOffset;
|
||||
int width;
|
||||
int height;
|
||||
boolean bold;
|
||||
int extraY = 0;
|
||||
|
||||
public CharData(Font font, char letter, Rectangle bounds, int width, int height, boolean bold)
|
||||
{
|
||||
this.font = font;
|
||||
this.letter = letter;
|
||||
if(bounds.x >= 0) this.width = width;
|
||||
else
|
||||
{
|
||||
this.width = bounds.width == 0 ? width : bounds.width;
|
||||
xOffset = bounds.x;
|
||||
}
|
||||
this.height = height;
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
private CharData offset(int offset)
|
||||
{
|
||||
extraY += offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isBold()
|
||||
{
|
||||
return bold;
|
||||
}
|
||||
|
||||
public Font getFont()
|
||||
{
|
||||
return font;
|
||||
}
|
||||
|
||||
public int getExtraY(int asent)
|
||||
{
|
||||
return extraY + asent;
|
||||
}
|
||||
|
||||
public char getLetter()
|
||||
{
|
||||
return letter;
|
||||
}
|
||||
|
||||
public AssetLocation asLocation()
|
||||
{
|
||||
return AssetLocation.of("base", font.getFontName().replaceAll(" ", "_") + (bold ? "_Bold" : "") + "_" + ((int)letter));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ public class TextFilter
|
|||
public static final Predicate<String> INTEGER_ONLY = T -> {
|
||||
try {
|
||||
if(T == null || T.isEmpty());
|
||||
else if(T.length() == 1 && T.charAt(0) == '-');
|
||||
else Integer.parseInt(T);
|
||||
return true;
|
||||
}
|
||||
|
@ -16,6 +17,7 @@ public class TextFilter
|
|||
public static final Predicate<String> FLOAT_ONLY = T -> {
|
||||
try {
|
||||
if(T == null || T.isEmpty());
|
||||
else if(T.length() == 1 && T.charAt(0) == '-');
|
||||
else Float.parseFloat(T);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.Locale;
|
|||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import speiger.src.collections.chars.maps.interfaces.Char2ObjectMap;
|
||||
import speiger.src.collections.floats.lists.FloatArrayList;
|
||||
import speiger.src.collections.floats.lists.FloatList;
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
|
@ -20,11 +19,12 @@ import speiger.src.coreengine.rendering.gui.renderer.lexer.Line;
|
|||
import speiger.src.coreengine.rendering.gui.renderer.lexer.TextContext;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.lexer.TextContext.WordContext;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.lexer.TextLexer;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.provider.IFontProvider;
|
||||
import speiger.src.coreengine.rendering.models.DrawCall;
|
||||
import speiger.src.coreengine.rendering.tesselation.IVertexBuilder;
|
||||
import speiger.src.coreengine.rendering.tesselation.Tesselator;
|
||||
import speiger.src.coreengine.rendering.tesselation.VertexType;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.utils.helpers.TextUtil;
|
||||
|
||||
public class FontRenderer implements IFontRenderer
|
||||
|
@ -36,45 +36,51 @@ public class FontRenderer implements IFontRenderer
|
|||
public static final char LINE_SEPERATOR = '\n';
|
||||
Tesselator bufferBuilder = new Tesselator(655340);
|
||||
|
||||
IFontProvider provider;
|
||||
final TextLexer lexer = new TextLexer(this);
|
||||
final DelayedRenderBuffer lineBuffer = new DelayedRenderBuffer();
|
||||
final Char2ObjectMap<CharInstance>[] chars;
|
||||
final ITexture texture;
|
||||
final float height;
|
||||
final float baseLine;
|
||||
final float space;
|
||||
|
||||
public FontRenderer(Char2ObjectMap<CharInstance>[] chars, ITexture texture, float height, float baseLine)
|
||||
public void setProvider(IFontProvider provider)
|
||||
{
|
||||
this.chars = chars;
|
||||
this.texture = texture;
|
||||
this.height = height;
|
||||
this.baseLine = baseLine;
|
||||
space = chars[0].get(' ').getXAdvance();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharInstance getInstance(char letter, boolean isBold)
|
||||
{
|
||||
return chars[isBold ? 1 : 0].get(letter);
|
||||
return provider.getCharacter(letter, isBold);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFontHeight()
|
||||
{
|
||||
return height;
|
||||
return provider.getFontHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBaseLine()
|
||||
{
|
||||
return baseLine;
|
||||
return provider.getBaseLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITexture getTexture()
|
||||
{
|
||||
return texture;
|
||||
return provider.getTexture();
|
||||
}
|
||||
|
||||
public IFontProvider getProvider()
|
||||
{
|
||||
return provider;
|
||||
}
|
||||
|
||||
public void destory()
|
||||
{
|
||||
if(provider != null)
|
||||
{
|
||||
provider.destroy();
|
||||
provider = null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<DrawCall> renderText(String text, float x, float y, float z)
|
||||
|
@ -96,12 +102,12 @@ public class FontRenderer implements IFontRenderer
|
|||
{
|
||||
xOffset += renderChar(letter, xOffset, yOffset, context.getScale(), effects.italic, effects.flipped, textColor, builder, true);
|
||||
}
|
||||
yOffset += height * context.getScale();
|
||||
yOffset += getFontHeight() * context.getScale();
|
||||
}
|
||||
bufferBuilder.finishData();
|
||||
if(bufferBuilder.getVertexCount() > 0)
|
||||
{
|
||||
drawCalls.add(bufferBuilder.getDrawCall(texture.getTextureID()));
|
||||
drawCalls.add(bufferBuilder.getDrawCall(getTexture().getTextureID()));
|
||||
}
|
||||
bufferBuilder.setOffset(0F, 0F, 0F);
|
||||
return drawCalls;
|
||||
|
@ -125,8 +131,8 @@ public class FontRenderer implements IFontRenderer
|
|||
return;
|
||||
}
|
||||
bufferBuilder.begin(GL11.GL_TRIANGLES, VertexType.UI);
|
||||
int maxLanes = component.isHeightLimited() ? Math.min((int)(boxHeight / (height * context.getScale())), lines.size()) : lines.size();
|
||||
float maxHeight = maxLanes * height * context.getScale();
|
||||
int maxLanes = component.isHeightLimited() ? Math.min((int)(boxHeight / (getFontHeight() * context.getScale())), lines.size()) : lines.size();
|
||||
float maxHeight = maxLanes * getFontHeight() * context.getScale();
|
||||
float maxWidth = 0F;
|
||||
float yOffset = component.getVertical().align(boxHeight, maxHeight);
|
||||
float startX = component.getHorizontal().align(boxWidth, lines.get(0).getWidth());
|
||||
|
@ -182,11 +188,11 @@ public class FontRenderer implements IFontRenderer
|
|||
{
|
||||
addUnderline(underline, xOffset - underline, yOffset, textColor, lineBuffer, false);
|
||||
}
|
||||
yOffset += height * context.getScale();
|
||||
yOffset += getFontHeight() * context.getScale();
|
||||
component.getMetadata().addLine(lines.get(i));
|
||||
}
|
||||
maxWidth /= 2;
|
||||
buffer.finishShape(texture.getTextureID(), bufferBuilder);
|
||||
buffer.finishShape(getTexture().getTextureID(), bufferBuilder);
|
||||
if(lineBuffer.hasData())
|
||||
{
|
||||
Tesselator tes = buffer.start(GL11.GL_TRIANGLES, VertexType.UI).offset(0F, 0F, 0.001F);
|
||||
|
@ -201,9 +207,9 @@ public class FontRenderer implements IFontRenderer
|
|||
switch(instance.getCharacter())
|
||||
{
|
||||
case TAB:
|
||||
return space * 4 * scale;
|
||||
return provider.getTabWidth() * scale;
|
||||
case SPACE:
|
||||
return space * scale;
|
||||
return provider.getSpaceWidth() * scale;
|
||||
}
|
||||
if(instance.getXAdvance() <= 0F)
|
||||
{
|
||||
|
@ -231,7 +237,7 @@ public class FontRenderer implements IFontRenderer
|
|||
{
|
||||
float lineWidth = lines.get(i).getWidth();
|
||||
float xOffset = align.align(width, lineWidth);
|
||||
float maxY = flipPos ? yPos - height : yPos + height;
|
||||
float maxY = flipPos ? yPos - getFontHeight() : yPos + getFontHeight();
|
||||
tes.pos(xOffset, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
tes.pos(xOffset, yPos, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
tes.pos(xOffset + lineWidth, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
|
@ -244,12 +250,12 @@ public class FontRenderer implements IFontRenderer
|
|||
|
||||
protected void addUnderline(float xStart, float width, float yStart, ColorObject color, IVertexBuilder buffer, boolean flipPos)
|
||||
{
|
||||
float minY = yStart + baseLine + 0.5F;
|
||||
float maxY = yStart + baseLine + 1.5F;
|
||||
float minY = yStart + getBaseLine() + 0.5F;
|
||||
float maxY = yStart + getBaseLine() + 1.5F;
|
||||
if(flipPos)
|
||||
{
|
||||
minY = yStart - baseLine - 0.5F;
|
||||
maxY = yStart - baseLine - 1.5F;
|
||||
minY = yStart - getBaseLine() - 0.5F;
|
||||
maxY = yStart - getBaseLine() - 1.5F;
|
||||
}
|
||||
buffer.pos(xStart, maxY, 0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
buffer.pos(xStart, minY, 0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
|
@ -261,8 +267,8 @@ public class FontRenderer implements IFontRenderer
|
|||
|
||||
protected void addStrikeThrough(float xStart, float width, float yStart, ColorObject color, IVertexBuilder buffer)
|
||||
{
|
||||
float minY = yStart + height / 2.0F;
|
||||
float maxY = yStart + height / 2.0F + 1.4F;
|
||||
float minY = yStart + getFontHeight() / 2.0F;
|
||||
float maxY = yStart + getFontHeight() / 2.0F + 1.4F;
|
||||
buffer.pos(xStart, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
buffer.pos(xStart, minY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
buffer.pos(xStart + width, maxY, 0.0F).tex(0F, 0F).color4f(color).endVertex();
|
||||
|
@ -301,9 +307,9 @@ public class FontRenderer implements IFontRenderer
|
|||
switch(letter)
|
||||
{
|
||||
case SPACE:
|
||||
return space;
|
||||
return provider.getSpaceWidth();
|
||||
case TAB:
|
||||
return space * 4;
|
||||
return provider.getTabWidth();
|
||||
default:
|
||||
CharInstance instance = getInstance(letter, bold);
|
||||
return instance == null ? 0F : instance.getXAdvance();
|
||||
|
@ -321,7 +327,7 @@ public class FontRenderer implements IFontRenderer
|
|||
char character = text.charAt(i);
|
||||
if(LINE_SEPERATOR == character)
|
||||
{
|
||||
result = Math.max(result, current += space);
|
||||
result = Math.max(result, current += provider.getSpaceWidth());
|
||||
current = 0.0F;
|
||||
continue;
|
||||
}
|
||||
|
@ -391,13 +397,13 @@ public class FontRenderer implements IFontRenderer
|
|||
@Override
|
||||
public float getTextHeight(String text, int flags)
|
||||
{
|
||||
return getTextLengths(text, flags).length - 1 * height;
|
||||
return getTextLengths(text, flags).length - 1 * getFontHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCharValid(char letter)
|
||||
{
|
||||
return chars[0].containsKey(letter);
|
||||
return provider.isCharacterValid(letter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package speiger.src.coreengine.rendering.gui.renderer;
|
||||
|
||||
import speiger.src.coreengine.rendering.gui.components.TextComponent;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
|
||||
public interface IFontRenderer
|
||||
{
|
||||
|
@ -62,6 +62,12 @@ public interface IFontRenderer
|
|||
float xAdvance;
|
||||
boolean bold;
|
||||
|
||||
public CharInstance(char character, boolean bold)
|
||||
{
|
||||
this.character = character;
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
public CharInstance(char character, int width, int height, float minU, float minV, float maxU, float maxV, int xAdvance, boolean bold)
|
||||
{
|
||||
this.character = character;
|
||||
|
|
|
@ -28,8 +28,8 @@ import speiger.src.coreengine.rendering.shader.uniforms.UniformVec2f;
|
|||
import speiger.src.coreengine.rendering.tesselation.GLCall;
|
||||
import speiger.src.coreengine.rendering.tesselation.Tesselator;
|
||||
import speiger.src.coreengine.rendering.tesselation.VertexType;
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
import speiger.src.coreengine.rendering.utils.GLUtils;
|
||||
import speiger.src.coreengine.utils.collections.pools.SimplePool;
|
||||
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
package speiger.src.coreengine.rendering.gui.renderer.provider;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import speiger.src.collections.chars.maps.impl.hash.Char2ObjectOpenHashMap;
|
||||
import speiger.src.collections.chars.maps.interfaces.Char2ObjectMap;
|
||||
import speiger.src.collections.chars.utils.maps.Char2ObjectMaps;
|
||||
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.AssetManager;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
||||
import speiger.src.coreengine.rendering.gui.helper.FontBuilder;
|
||||
import speiger.src.coreengine.rendering.gui.helper.FontBuilder.WrittenChar;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
import speiger.src.coreengine.utils.helpers.JsonUtil;
|
||||
|
||||
public class BitmapFontProvider implements IFontProvider
|
||||
{
|
||||
FontInfo info;
|
||||
ITexture texture;
|
||||
Char2ObjectMap<CharInstance>[] instances;
|
||||
float space;
|
||||
|
||||
public BitmapFontProvider(FontInfo info, ITexture texture, Char2ObjectMap<CharInstance>[] instances)
|
||||
{
|
||||
this.info = info;
|
||||
this.texture = texture;
|
||||
this.instances = instances;
|
||||
if(instances[0].containsKey(' ')) space = instances[0].get(' ').getXAdvance();
|
||||
else if(instances[1].containsKey(' ')) space = instances[1].get(' ').getXAdvance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
if(texture != null)
|
||||
{
|
||||
texture.destroy();
|
||||
texture = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITexture getTexture()
|
||||
{
|
||||
return texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCharacterValid(char value)
|
||||
{
|
||||
return instances[0].containsKey(value) || instances[1].containsKey(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharInstance getCharacter(char value, boolean bold)
|
||||
{
|
||||
Char2ObjectMap<CharInstance> map = instances[bold ? 1 : 0];
|
||||
return (map.isEmpty() ? instances[bold ? 0 : 1] : map).get(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFontHeight()
|
||||
{
|
||||
return info.fontHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBaseLine()
|
||||
{
|
||||
return info.fontBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSpaceWidth()
|
||||
{
|
||||
return space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTabWidth()
|
||||
{
|
||||
return space * info.tabs;
|
||||
}
|
||||
|
||||
public static IFontProvider load(JsonObject object, float desiredSize, AssetManager manager)
|
||||
{
|
||||
FontInfo info = new FontInfo(object.getAsJsonObject("info"));
|
||||
float multiplier = info.setDesiredHeight(desiredSize);
|
||||
Char2ObjectMap<CharInstance>[] maps = new Char2ObjectMap[]{new Char2ObjectOpenHashMap<CharInstance>(), new Char2ObjectOpenHashMap<CharInstance>()};
|
||||
JsonUtil.iterate(object.get("chars"), T -> {
|
||||
CharInstance instance = info.create(T);
|
||||
instance.scale(multiplier);
|
||||
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
||||
});
|
||||
if(maps[0].isEmpty()) maps[0] = Char2ObjectMaps.empty();
|
||||
if(maps[1].isEmpty()) maps[1] = Char2ObjectMaps.empty();
|
||||
return new BitmapFontProvider(info, ITexture.simple(AssetLocation.of(object.get("file").getAsString())), maps);
|
||||
}
|
||||
|
||||
public static IFontProvider create(JsonObject object, float desiredSize, AssetManager manager)
|
||||
{
|
||||
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(AssetLocation.of(object.get("file").getAsString())))
|
||||
{
|
||||
JsonObject info = object.getAsJsonObject("info");
|
||||
int tabs = JsonUtil.getOrDefault(info, "tabs", 4);
|
||||
boolean literal = JsonUtil.getOrDefault(info, "literal", false);
|
||||
boolean plain = JsonUtil.getOrDefault(info, "plain", true);
|
||||
boolean bold = JsonUtil.getOrDefault(info, "bold", true);
|
||||
if(!plain && !bold) throw new IllegalStateException("You need a plain or bold font at the very least");
|
||||
|
||||
int flags = (literal ? FontBuilder.LITERAL : 0) | (plain ? FontBuilder.PLAIN : 0) | (bold ? FontBuilder.BOLD : 0);
|
||||
ObjectObjectPair<ObjectObjectPair<Vec2i, BufferedImage>, List<WrittenChar>> written = FontBuilder.createBitmapFont(asset.getStream(), info.get("charset").getAsString(), flags, info.get("size").getAsFloat());
|
||||
BufferedImage image = written.getKey().getValue();
|
||||
Vec2i size = written.getKey().getKey();
|
||||
FontInfo fontInfo = new FontInfo(image.getWidth(), image.getHeight(), size.getY(), size.getX(), tabs);
|
||||
float mulitplier = fontInfo.setDesiredHeight(desiredSize);
|
||||
Char2ObjectMap<CharInstance>[] maps = new Char2ObjectMap[]{new Char2ObjectOpenHashMap<CharInstance>(), new Char2ObjectOpenHashMap<CharInstance>()};
|
||||
for(WrittenChar entry : written.getValue())
|
||||
{
|
||||
CharInstance instance = entry.create(fontInfo.textureWidth, fontInfo.textureHeight);
|
||||
instance.scale(mulitplier);
|
||||
maps[instance.isBold() ? 1 : 0].put(instance.getCharacter(), instance);
|
||||
}
|
||||
if(maps[0].isEmpty()) maps[0] = Char2ObjectMaps.empty();
|
||||
if(maps[1].isEmpty()) maps[1] = Char2ObjectMaps.empty();
|
||||
return new BitmapFontProvider(fontInfo, ITexture.direct(image), maps);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package speiger.src.coreengine.rendering.gui.renderer.provider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2FloatLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap.Entry;
|
||||
import speiger.src.collections.objects.utils.maps.Object2FloatMaps;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.AssetManager;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
import speiger.src.coreengine.rendering.gui.renderer.FontRenderer;
|
||||
|
||||
public class FontManager implements IReloadableResource
|
||||
{
|
||||
Map<AssetLocation, FontRenderer> fontRenders = new Object2ObjectLinkedOpenHashMap<>();
|
||||
Object2FloatMap<AssetLocation> fontSizes = new Object2FloatLinkedOpenHashMap<>();
|
||||
Map<String, IFontLoader> loaders = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
AssetManager manager;
|
||||
|
||||
public FontManager()
|
||||
{
|
||||
registerFontLoader("bitmap", BitmapFontProvider::load);
|
||||
registerFontLoader("java-ttf", BitmapFontProvider::create);
|
||||
}
|
||||
|
||||
public void setAssetManager(AssetManager manager)
|
||||
{
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public void registerFontLoader(String id, IFontLoader provider)
|
||||
{
|
||||
loaders.put(id, provider);
|
||||
}
|
||||
|
||||
public FontRenderer loadFont(AssetLocation location, float desiredSize)
|
||||
{
|
||||
FontRenderer render = fontRenders.get(location);
|
||||
if(render == null)
|
||||
{
|
||||
IFontProvider provider = loadProvider(location, desiredSize);
|
||||
if(provider != null)
|
||||
{
|
||||
render = new FontRenderer();
|
||||
render.setProvider(provider);
|
||||
fontRenders.put(location, render);
|
||||
fontSizes.putIfAbsent(location, desiredSize);
|
||||
}
|
||||
}
|
||||
return render;
|
||||
}
|
||||
|
||||
private IFontProvider loadProvider(AssetLocation location, float desiredSize)
|
||||
{
|
||||
try(IAsset asset = manager.getAsset(location))
|
||||
{
|
||||
JsonObject obj = asset.getJsonObject();
|
||||
IFontLoader loader = loaders.get(obj.get("type").getAsString());
|
||||
if(loader == null) return null;
|
||||
return loader.create(obj, desiredSize, manager);
|
||||
}
|
||||
catch(Exception e) { e.printStackTrace(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
public static interface IFontLoader
|
||||
{
|
||||
public IFontProvider create(JsonObject obj, float desiredSize, AssetManager loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload()
|
||||
{
|
||||
List<IFontProvider> providers = new ObjectArrayList<>();
|
||||
for(Entry<AssetLocation> entry : Object2FloatMaps.fastIterable(fontSizes))
|
||||
{
|
||||
AssetLocation location = entry.getKey();
|
||||
FontRenderer font = fontRenders.get(location);
|
||||
providers.add(font.getProvider());
|
||||
font.setProvider(loadProvider(location, entry.getFloatValue()));
|
||||
}
|
||||
for(int i = 0,m=providers.size();i<m;providers.get(i++).destroy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
fontRenders.values().forEach(FontRenderer::destory);
|
||||
fontRenders.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package speiger.src.coreengine.rendering.gui.renderer.provider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import speiger.src.coreengine.rendering.gui.renderer.IFontRenderer.CharInstance;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.utils.helpers.JsonUtil;
|
||||
|
||||
public interface IFontProvider
|
||||
{
|
||||
public ITexture getTexture();
|
||||
public boolean isCharacterValid(char value);
|
||||
public CharInstance getCharacter(char value, boolean bold);
|
||||
public float getFontHeight();
|
||||
public float getBaseLine();
|
||||
|
||||
public float getSpaceWidth();
|
||||
public float getTabWidth();
|
||||
|
||||
public void destroy();
|
||||
|
||||
public static class FontInfo
|
||||
{
|
||||
public int textureWidth;
|
||||
public int textureHeight;
|
||||
public float fontHeight;
|
||||
public float fontBase;
|
||||
public int tabs;
|
||||
|
||||
public FontInfo(JsonObject obj)
|
||||
{
|
||||
this(obj.get("width").getAsInt(), obj.get("height").getAsInt(), obj.get("charHeight").getAsInt(), obj.get("base").getAsInt(), JsonUtil.getOrDefault(obj, "tabs", 4));
|
||||
}
|
||||
|
||||
public FontInfo(int textureWidth, int textureHeight, float fontHeight, float fontBase, int tabs)
|
||||
{
|
||||
this.textureWidth = textureWidth;
|
||||
this.textureHeight = textureHeight;
|
||||
this.fontHeight = fontHeight;
|
||||
this.fontBase = fontBase;
|
||||
this.tabs = tabs;
|
||||
}
|
||||
|
||||
public float setDesiredHeight(float desired)
|
||||
{
|
||||
float multiplier = desired / fontHeight;
|
||||
fontHeight *= multiplier;
|
||||
fontBase *= multiplier;
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
public CharInstance create(JsonObject obj)
|
||||
{
|
||||
return create((char)obj.get("char").getAsInt(), obj.get("minX").getAsInt(), obj.get("minY").getAsInt(), obj.get("maxX").getAsInt(), obj.get("maxY").getAsInt(), JsonUtil.getOrDefault(obj, "bold", false));
|
||||
}
|
||||
|
||||
public CharInstance create(char character, int minX, int minY, int maxX, int maxY, boolean bold)
|
||||
{
|
||||
return new CharInstance(character, maxX - minX, maxY - minY, getTextureU(minX), getTextureV(minY), getTextureU(maxX), getTextureV(maxY), maxX - minX, bold);
|
||||
}
|
||||
|
||||
public float getTextureU(float value)
|
||||
{
|
||||
return value / textureWidth;
|
||||
}
|
||||
|
||||
public float getTextureV(float value)
|
||||
{
|
||||
return value / textureHeight;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package speiger.src.coreengine.rendering.models;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
|
||||
public enum DataType
|
||||
{
|
||||
BYTE("byte", 1),
|
||||
SHORT("short", 2),
|
||||
INT("int", 4),
|
||||
LONG("long", 8),
|
||||
FLOAT("float", 4),
|
||||
DOUBLE("double", 8);
|
||||
|
||||
static final Map<String, DataType> BY_ID = new Object2ObjectOpenHashMap<>();
|
||||
final String type;
|
||||
final int byteSize;
|
||||
|
||||
private DataType(String type, int byteSize)
|
||||
{
|
||||
this.type = type;
|
||||
this.byteSize = byteSize;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getByteSize()
|
||||
{
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
public boolean isFloatingPoint()
|
||||
{
|
||||
return this == FLOAT || this == DOUBLE;
|
||||
}
|
||||
|
||||
public static DataType byID(String id)
|
||||
{
|
||||
return BY_ID.get(id);
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
for(DataType type : values())
|
||||
{
|
||||
BY_ID.put(type.getType(), type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +1,56 @@
|
|||
package speiger.src.coreengine.rendering.models;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import speiger.src.collections.ints.maps.impl.hash.Int2ObjectOpenHashMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
|
||||
|
||||
public class GLDataType
|
||||
{
|
||||
static final Int2ObjectMap<GLDataType> ID_TO_TYPE = new Int2ObjectOpenHashMap<>();
|
||||
static final Map<String, GLDataType> NAME_TO_TYPE = new Object2ObjectOpenHashMap<>();
|
||||
//Normal Types
|
||||
public static final GLDataType BYTE = new GLDataType(GL11.GL_BYTE, 1);
|
||||
public static final GLDataType UNSIGNED_BYTE = new GLDataType(GL11.GL_UNSIGNED_BYTE, 1);
|
||||
public static final GLDataType SHORT = new GLDataType(GL11.GL_SHORT, 2);
|
||||
public static final GLDataType UNSIGNED_SHORT = new GLDataType(GL11.GL_UNSIGNED_SHORT, 2);
|
||||
public static final GLDataType INT = new GLDataType(GL11.GL_INT, 4);
|
||||
public static final GLDataType UNSIGNED_INT = new GLDataType(GL11.GL_UNSIGNED_INT, 4);
|
||||
public static final GLDataType FLOAT = new GLDataType(GL11.GL_FLOAT, 4);
|
||||
public static final GLDataType BYTE = new GLDataType(GL11.GL_BYTE, DataType.BYTE, "byte");
|
||||
public static final GLDataType UNSIGNED_BYTE = new GLDataType(GL11.GL_UNSIGNED_BYTE, DataType.BYTE, "u_byte");
|
||||
public static final GLDataType SHORT = new GLDataType(GL11.GL_SHORT, DataType.SHORT, "short");
|
||||
public static final GLDataType UNSIGNED_SHORT = new GLDataType(GL11.GL_UNSIGNED_SHORT, DataType.SHORT, "u_short");
|
||||
public static final GLDataType INT = new GLDataType(GL11.GL_INT, DataType.INT, "int");
|
||||
public static final GLDataType UNSIGNED_INT = new GLDataType(GL11.GL_UNSIGNED_INT, DataType.INT, "u_int");
|
||||
public static final GLDataType FLOAT = new GLDataType(GL11.GL_FLOAT, DataType.FLOAT, "float");
|
||||
public static final GLDataType DOUBLE = new GLDataType(GL11.GL_DOUBLE, DataType.DOUBLE, "double");
|
||||
|
||||
|
||||
//Compression Types
|
||||
public static final GLDataType UNSIGNED_INT_10_10_10_2 = new GLDataType(GL12.GL_UNSIGNED_INT_10_10_10_2, 4, true);
|
||||
public static final GLDataType UNSIGNED_INT_2_10_10_10_REV = new GLDataType(GL12.GL_UNSIGNED_INT_2_10_10_10_REV, 4, true);
|
||||
public static final GLDataType UNSIGNED_INT_10_10_10_2 = new GLDataType(GL12.GL_UNSIGNED_INT_10_10_10_2, DataType.INT, true, "u_int_10_10_10_2");
|
||||
public static final GLDataType UNSIGNED_INT_2_10_10_10_REV = new GLDataType(GL12.GL_UNSIGNED_INT_2_10_10_10_REV, DataType.INT, true, "u_int_2_10_10_10_rev");
|
||||
|
||||
//Special Types
|
||||
public static final GLDataType UNSIGNED_INT_10F_11F_11F_REV = new GLDataType(GL30.GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true);
|
||||
public static final GLDataType UNSIGNED_INT_5_9_9_9_REV = new GLDataType(GL30.GL_UNSIGNED_INT_5_9_9_9_REV, 4, true);
|
||||
public static final GLDataType UNSIGNED_INT_10F_11F_11F_REV = new GLDataType(GL30.GL_UNSIGNED_INT_10F_11F_11F_REV, DataType.INT, true, "u_int_10_11_11_rev");
|
||||
public static final GLDataType UNSIGNED_INT_5_9_9_9_REV = new GLDataType(GL30.GL_UNSIGNED_INT_5_9_9_9_REV, DataType.INT, true, "u_int_5_9_9_9_rev");
|
||||
|
||||
final int glType;
|
||||
final int byteSize;
|
||||
final DataType dataType;
|
||||
final boolean ignoreAttributeSize;
|
||||
final String name;
|
||||
|
||||
public GLDataType(int glType, int byteSize)
|
||||
public GLDataType(int glType, DataType dataType, String name)
|
||||
{
|
||||
this(glType, byteSize, false);
|
||||
this(glType, dataType, false, name);
|
||||
}
|
||||
|
||||
public GLDataType(int glType, int byteSize, boolean ignoreAttributeSize)
|
||||
public GLDataType(int glType, DataType dataType, boolean ignoreAttributeSize, String name)
|
||||
{
|
||||
this.glType = glType;
|
||||
this.byteSize = byteSize;
|
||||
this.dataType = dataType;
|
||||
this.ignoreAttributeSize = ignoreAttributeSize;
|
||||
this.name = name;
|
||||
ID_TO_TYPE.put(glType, this);
|
||||
NAME_TO_TYPE.put(name, this);
|
||||
}
|
||||
|
||||
public int getGLType()
|
||||
|
@ -44,13 +58,28 @@ public class GLDataType
|
|||
return glType;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getByteSize()
|
||||
{
|
||||
return byteSize;
|
||||
return dataType.getByteSize();
|
||||
}
|
||||
|
||||
public boolean isSpecialType()
|
||||
{
|
||||
return ignoreAttributeSize;
|
||||
}
|
||||
|
||||
public DataType getDataType()
|
||||
{
|
||||
return dataType;
|
||||
}
|
||||
|
||||
public int calulateSize(int attributeSize)
|
||||
{
|
||||
return ignoreAttributeSize ? byteSize : attributeSize * byteSize;
|
||||
return ignoreAttributeSize ? dataType.getByteSize() : attributeSize * dataType.getByteSize();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import java.util.function.Consumer;
|
|||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
|
||||
import speiger.src.coreengine.rendering.utils.AllocationTracker;
|
||||
import speiger.src.coreengine.utils.io.GameLog;
|
||||
|
||||
|
@ -213,12 +213,12 @@ public class VertexBuffer
|
|||
return this;
|
||||
}
|
||||
|
||||
public VertexBuffer fillBuffer(List<Entry<byte[]>> data)
|
||||
public VertexBuffer fillBuffer(List<IntObjectPair<byte[]>> data)
|
||||
{
|
||||
return fillBuffer(0, data);
|
||||
}
|
||||
|
||||
public VertexBuffer fillBuffer(int byteOffset, List<Entry<byte[]>> data)
|
||||
public VertexBuffer fillBuffer(int byteOffset, List<IntObjectPair<byte[]>> data)
|
||||
{
|
||||
if(data.isEmpty())
|
||||
{
|
||||
|
@ -228,7 +228,7 @@ public class VertexBuffer
|
|||
ByteBuffer buffer = GL15.glMapBuffer(bufferType, GL15.GL_WRITE_ONLY);
|
||||
for(int i = 0,m=data.size();i<m;i++)
|
||||
{
|
||||
Entry<byte[]> entry = data.get(i);
|
||||
IntObjectPair<byte[]> entry = data.get(i);
|
||||
buffer.position(entry.getIntKey()+byteOffset);
|
||||
buffer.put(entry.getValue());
|
||||
totalData += entry.getValue().length;
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.lwjgl.opengl.GL13;
|
|||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class TextureAttachment implements IFrameAttachment
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package speiger.src.coreengine.rendering.shader.uniforms;
|
||||
|
||||
import speiger.src.coreengine.rendering.textures.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class UniformTexture extends UniformInt
|
||||
{
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
|
||||
public interface ITexture extends IReloadableResource
|
||||
{
|
||||
public int getTextureID();
|
||||
|
||||
public void bindTexture();
|
||||
public void deleteTexture();
|
||||
|
||||
public int getWidth();
|
||||
public int getHeight();
|
||||
|
||||
public float getUMin();
|
||||
public float getVMin();
|
||||
public float getUMax();
|
||||
public float getVMax();
|
||||
|
||||
public default float getInterpolatedU(float u){return getUMin() + ((getUMax() - getUMin()) * u);}
|
||||
public default float getINterpolatedV(float v){return getUMin() + ((getUMax() - getUMin()) * v);}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.base;
|
||||
|
||||
public abstract class AbstractTexture implements ITexture
|
||||
{
|
||||
int textureID;
|
||||
protected int textureID;
|
||||
|
||||
public AbstractTexture()
|
||||
@Override
|
||||
public ITexture makeReloadable()
|
||||
{
|
||||
TextureManager.INSTANCE.addTexture(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setTextureID(int textureID)
|
|
@ -0,0 +1,56 @@
|
|||
package speiger.src.coreengine.rendering.textures.base;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
import speiger.src.coreengine.rendering.textures.normal.DirectTexture;
|
||||
import speiger.src.coreengine.rendering.textures.normal.SimpleTexture;
|
||||
import speiger.src.coreengine.rendering.textures.stb.STBDirectTexture;
|
||||
import speiger.src.coreengine.rendering.textures.stb.STBTexture;
|
||||
|
||||
public interface ITexture extends IReloadableResource
|
||||
{
|
||||
public int getTextureID();
|
||||
|
||||
public void bindTexture();
|
||||
public void deleteTexture();
|
||||
|
||||
public int getWidth();
|
||||
public int getHeight();
|
||||
|
||||
public float getUMin();
|
||||
public float getVMin();
|
||||
public float getUMax();
|
||||
public float getVMax();
|
||||
|
||||
public ITexture makeReloadable();
|
||||
|
||||
public default float getInterpolatedU(float u){return getUMin() + ((getUMax() - getUMin()) * u);}
|
||||
public default float getInterpolatedV(float v){return getUMin() + ((getUMax() - getUMin()) * v);}
|
||||
|
||||
public static ITexture simple(AssetLocation location) {
|
||||
return new STBTexture(location);
|
||||
}
|
||||
|
||||
public static ITexture direct(ByteBuffer stbImageData, int width, int height) {
|
||||
return new STBDirectTexture(stbImageData, width, height);
|
||||
}
|
||||
|
||||
public static ITexture direct(long stbImageData, int width, int height) {
|
||||
return new STBDirectTexture(stbImageData, width, height);
|
||||
}
|
||||
|
||||
public static ITexture direct(BufferedImage imageData) {
|
||||
return new STBDirectTexture(imageData);
|
||||
}
|
||||
|
||||
public static ITexture awtSimple(AssetLocation location) {
|
||||
return new SimpleTexture(location);
|
||||
}
|
||||
|
||||
public static ITexture awtDirect(BufferedImage imageData) {
|
||||
return new DirectTexture(imageData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package speiger.src.coreengine.rendering.textures.base;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import speiger.src.coreengine.assets.IAssetParser;
|
||||
|
||||
public class NativeMemoryParser implements IAssetParser<ByteBuffer>
|
||||
{
|
||||
|
||||
@Override
|
||||
public ByteBuffer parseAsset(Path path, Consumer<Closeable> autoCloser) throws IOException
|
||||
{
|
||||
byte[] data = Files.readAllBytes(path);
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(data.length);
|
||||
buffer.put(data);
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.base;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -13,6 +13,8 @@ import speiger.src.coreengine.assets.AssetManager;
|
|||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
import speiger.src.coreengine.assets.reloader.ResourceReloader;
|
||||
import speiger.src.coreengine.rendering.textures.base.ITexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
import speiger.src.coreengine.rendering.utils.GLUtils;
|
||||
import speiger.src.coreengine.rendering.utils.states.GLState;
|
||||
import speiger.src.coreengine.utils.io.GameLog;
|
|
@ -1,4 +1,4 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.base;
|
||||
|
||||
public class WrappedTexture implements ITexture
|
||||
{
|
||||
|
@ -8,7 +8,13 @@ public class WrappedTexture implements ITexture
|
|||
{
|
||||
this.textureId = textureId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ITexture makeReloadable()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload()
|
||||
{
|
|
@ -1,4 +1,4 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.custom;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
|
@ -16,6 +16,8 @@ import speiger.src.collections.ints.sets.IntSet;
|
|||
import speiger.src.collections.ints.utils.maps.Int2ObjectMaps;
|
||||
import speiger.src.collections.utils.ITrimmable;
|
||||
import speiger.src.coreengine.math.BitUtil;
|
||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
import speiger.src.coreengine.rendering.utils.AllocationTracker;
|
||||
|
||||
public class DynamicTexture extends AbstractTexture
|
||||
|
@ -132,8 +134,9 @@ public class DynamicTexture extends AbstractTexture
|
|||
@Override
|
||||
public void reload()
|
||||
{
|
||||
TextureManager.INSTANCE.removeTexture(getTextureID());
|
||||
int old = getTextureID();
|
||||
setTextureID(GL11.glGenTextures());
|
||||
TextureManager.INSTANCE.removeTexture(old);
|
||||
dirtyChunks.clear();
|
||||
first = true;
|
||||
updateData();
|
|
@ -0,0 +1,304 @@
|
|||
package speiger.src.coreengine.rendering.textures.custom;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
|
||||
import speiger.src.collections.objects.misc.pairs.ObjectObjectPair;
|
||||
import speiger.src.collections.objects.sets.ObjectOpenHashSet;
|
||||
import speiger.src.collections.objects.utils.ObjectIterators;
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
||||
import speiger.src.coreengine.rendering.textures.custom.TextureAtlas;
|
||||
|
||||
/**
|
||||
* Inspired by: <a href=https://github.com/lukaszdk/texture-atlas-generator/blob/master/AtlasGenerator.java>AtlasGenerator</a>
|
||||
*/
|
||||
public class TextureAtlas
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
Object2ObjectMap<AssetLocation, AtlasEntry> textures;
|
||||
|
||||
protected TextureAtlas(Vec2i bounds, Object2ObjectMap<AssetLocation, AtlasEntry> textures)
|
||||
{
|
||||
width = bounds.getX();
|
||||
height = bounds.getY();
|
||||
this.textures = textures;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public AtlasEntry getTexture(AssetLocation texture)
|
||||
{
|
||||
return textures.getObject(texture);
|
||||
}
|
||||
|
||||
public Iterator<AtlasEntry> getContents()
|
||||
{
|
||||
return ObjectIterators.unmodifiable(textures.values().iterator());
|
||||
}
|
||||
|
||||
public static Builder create()
|
||||
{
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
Set<AssetLocation> names = new ObjectOpenHashSet<>();
|
||||
List<Record> records = new ObjectArrayList<>();
|
||||
int pixelsUsed = 0;
|
||||
|
||||
public boolean add(AssetLocation location, int width, int height)
|
||||
{
|
||||
return add(location, width, height, 0);
|
||||
}
|
||||
|
||||
public boolean add(AssetLocation location, int width, int height, int padding)
|
||||
{
|
||||
if(location == null || width <= 0 || height <= 0 || padding < 0 || !names.add(location)) return false;
|
||||
records.add(new Record(location, width, height, padding));
|
||||
pixelsUsed += (width + padding) * (height + padding);
|
||||
return true;
|
||||
}
|
||||
|
||||
private ObjectObjectPair<Vec2i, Object2ObjectMap<AssetLocation, AtlasEntry>> stitch()
|
||||
{
|
||||
int textureWidth = 2;
|
||||
int textureHeight = 2;
|
||||
boolean height = false;
|
||||
for(;textureHeight * textureWidth <= pixelsUsed;height = !height)
|
||||
{
|
||||
if(height) textureHeight *= 2;
|
||||
else textureWidth *= 2;
|
||||
}
|
||||
records.sort(null);
|
||||
int attempts = 0;
|
||||
while(attempts < 50)
|
||||
{
|
||||
Slot slot = new Slot(0, 0, textureWidth, textureHeight);
|
||||
boolean failed = false;
|
||||
for(int i = 0,m=records.size();i<m;i++)
|
||||
{
|
||||
if(slot.addRecord(records.get(i))) continue;
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
if(failed)
|
||||
{
|
||||
if(height) textureHeight *= 2;
|
||||
else textureWidth *= 2;
|
||||
attempts++;
|
||||
height = !height;
|
||||
continue;
|
||||
}
|
||||
Object2ObjectMap<AssetLocation, AtlasEntry> entries = new Object2ObjectLinkedOpenHashMap<>();
|
||||
slot.build(entries::put);
|
||||
return ObjectObjectPair.of(Vec2i.newVec(textureWidth, textureHeight), entries);
|
||||
}
|
||||
throw new IllegalStateException("Couldn't fit Texture Atlas after growing it 5 Times");
|
||||
}
|
||||
|
||||
public void buildHollow(BiConsumer<Vec2i, Iterable<AtlasEntry>> builder)
|
||||
{
|
||||
ObjectObjectPair<Vec2i, Object2ObjectMap<AssetLocation, AtlasEntry>> pairs = stitch();
|
||||
builder.accept(pairs.getKey(), pairs.getValue().values());
|
||||
}
|
||||
|
||||
public TextureAtlas build(BiConsumer<Vec2i, Iterable<AtlasEntry>> builder)
|
||||
{
|
||||
ObjectObjectPair<Vec2i, Object2ObjectMap<AssetLocation, AtlasEntry>> pairs = stitch();
|
||||
builder.accept(pairs.getKey(), pairs.getValue().values());
|
||||
return new TextureAtlas(pairs.getKey(), pairs.getValue());
|
||||
}
|
||||
|
||||
public TextureAtlas build()
|
||||
{
|
||||
ObjectObjectPair<Vec2i, Object2ObjectMap<AssetLocation, AtlasEntry>> pairs = stitch();
|
||||
return new TextureAtlas(pairs.getKey(), pairs.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static class AtlasEntry
|
||||
{
|
||||
AssetLocation location;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
private AtlasEntry(Slot slot)
|
||||
{
|
||||
Record record = slot.record;
|
||||
location = record == null ? null : record.getLocation();
|
||||
x = slot.x;
|
||||
y = slot.y;
|
||||
width = record == null ? slot.width : record.width;
|
||||
height = record == null ? slot.height : record.height;
|
||||
}
|
||||
|
||||
public AssetLocation getLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Slot
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
Record record;
|
||||
Slot[] children = null;
|
||||
|
||||
public Slot(int x, int y, int width, int height)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public boolean isLeaf()
|
||||
{
|
||||
return children == null;
|
||||
}
|
||||
|
||||
public void build(BiConsumer<AssetLocation, AtlasEntry> builder)
|
||||
{
|
||||
if(!isLeaf())
|
||||
{
|
||||
for(int i = 0,m=children.length;i<m;i++)
|
||||
{
|
||||
children[i].build(builder);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(record == null) return;
|
||||
builder.accept(record.getLocation(), new AtlasEntry(this));
|
||||
}
|
||||
|
||||
public boolean addRecord(Record record)
|
||||
{
|
||||
if(isLeaf())
|
||||
{
|
||||
int rw = record.getWidth();
|
||||
int rh = record.getHeight();
|
||||
if(this.record != null || rw > width || rh > height) return false;
|
||||
if(rw == width && rh == height)
|
||||
{
|
||||
this.record = record;
|
||||
return true;
|
||||
}
|
||||
int p = record.getPadding();
|
||||
int dw = width - rw;
|
||||
int dh = height - rh;
|
||||
children = new Slot[dw > 0 && dh > 0 ? 3 : 2];
|
||||
children[0] = new Slot(x, y, rw, rh);
|
||||
if(dw > 0 && dh > 0)
|
||||
{
|
||||
if(dw > dh)
|
||||
{
|
||||
children[1] = new Slot(x + rw + p, y, dw - p, rh);
|
||||
children[2] = new Slot(x, y + rh + p, width, dh - p);
|
||||
}
|
||||
else
|
||||
{
|
||||
children[1] = new Slot(x, y + rh + p, rw, dh - p);
|
||||
children[2] = new Slot(x + rw + p, y, dw - p, height);
|
||||
}
|
||||
}
|
||||
else if(dw == 0) children[1] = new Slot(x, y + rh + p, rw, dh - p);
|
||||
else if(dh == 0) children[1] = new Slot(x + rw + p, y, dw - p, rh);
|
||||
return children[0].addRecord(record);
|
||||
}
|
||||
for(int i = 0,m=children.length;i<m;i++)
|
||||
{
|
||||
if(children[i].addRecord(record)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Record implements Comparable<Record>
|
||||
{
|
||||
AssetLocation location;
|
||||
int width;
|
||||
int height;
|
||||
int padding;
|
||||
|
||||
public Record(AssetLocation location, int width, int height, int padding)
|
||||
{
|
||||
this.location = location;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getPadding()
|
||||
{
|
||||
return padding;
|
||||
}
|
||||
|
||||
public AssetLocation getLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
private int getPixelCount()
|
||||
{
|
||||
return (width + padding) * (height + padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Record o)
|
||||
{
|
||||
int result = Integer.compare(o.getPixelCount(), getPixelCount());
|
||||
return result == 0 ? getLocation().compareTo(o.getLocation()) : result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.normal;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -8,6 +8,9 @@ import org.lwjgl.opengl.GL13;
|
|||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class DirectTexture extends AbstractTexture
|
||||
{
|
||||
BufferedImage image;
|
||||
|
@ -93,7 +96,8 @@ public class DirectTexture extends AbstractTexture
|
|||
@Override
|
||||
public void reload()
|
||||
{
|
||||
TextureManager.INSTANCE.removeTexture(textureID);
|
||||
int old = textureID;
|
||||
loadTexture();
|
||||
TextureManager.INSTANCE.removeTexture(old);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package speiger.src.coreengine.rendering.textures;
|
||||
package speiger.src.coreengine.rendering.textures.normal;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -10,6 +10,8 @@ import org.lwjgl.system.MemoryUtil;
|
|||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class SimpleTexture extends AbstractTexture
|
||||
{
|
||||
|
@ -66,8 +68,9 @@ public class SimpleTexture extends AbstractTexture
|
|||
@Override
|
||||
public void reload()
|
||||
{
|
||||
TextureManager.INSTANCE.removeTexture(textureID);
|
||||
int old = textureID;
|
||||
loadTexture();
|
||||
TextureManager.INSTANCE.removeTexture(old);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,109 @@
|
|||
package speiger.src.coreengine.rendering.textures.stb;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class STBDirectTexture extends AbstractTexture
|
||||
{
|
||||
long imageData;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
public STBDirectTexture(BufferedImage imageData)
|
||||
{
|
||||
this(convert(imageData), imageData.getWidth(), imageData.getHeight());
|
||||
}
|
||||
|
||||
public STBDirectTexture(ByteBuffer imageData, int width, int height)
|
||||
{
|
||||
this(MemoryUtil.memAddress(imageData), width, height);
|
||||
}
|
||||
|
||||
public STBDirectTexture(long imageData, int width, int height)
|
||||
{
|
||||
this.imageData = imageData;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
loadTexture();
|
||||
}
|
||||
|
||||
protected void loadTexture()
|
||||
{
|
||||
setTextureID(GL11.glGenTextures());
|
||||
bindTexture();
|
||||
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER);
|
||||
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData);
|
||||
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload()
|
||||
{
|
||||
int old = textureID;
|
||||
loadTexture();
|
||||
TextureManager.INSTANCE.removeTexture(old);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTexture()
|
||||
{
|
||||
if(imageData != 0)
|
||||
{
|
||||
STBImage.nstbi_image_free(imageData);
|
||||
imageData = 0;
|
||||
}
|
||||
super.deleteTexture();
|
||||
}
|
||||
|
||||
private static ByteBuffer convert(BufferedImage image)
|
||||
{
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "png", stream);
|
||||
ByteBuffer buffer = MemoryUtil.memAlloc(stream.size());
|
||||
buffer.put(stream.toByteArray());
|
||||
buffer.flip();
|
||||
ByteBuffer result = STBImage.stbi_load_from_memory(buffer, new int[1], new int[1], new int[1], 4);
|
||||
if(result == null) {
|
||||
MemoryUtil.memFree(buffer);
|
||||
throw new IOException("Could not load image: " + STBImage.stbi_failure_reason());
|
||||
}
|
||||
MemoryUtil.memFree(buffer);
|
||||
return result;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package speiger.src.coreengine.rendering.textures.stb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.IAsset;
|
||||
import speiger.src.coreengine.rendering.textures.base.AbstractTexture;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public class STBTexture extends AbstractTexture
|
||||
{
|
||||
AssetLocation location;
|
||||
long imageData;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
public STBTexture(AssetLocation location)
|
||||
{
|
||||
this.location = location;
|
||||
loadTexture();
|
||||
}
|
||||
|
||||
private void loadTexture()
|
||||
{
|
||||
try(IAsset asset = TextureManager.INSTANCE.getManager().getAsset(location))
|
||||
{
|
||||
ByteBuffer buffer = asset.getCustom(ByteBuffer.class);
|
||||
int[] width = new int[1];
|
||||
int[] height = new int[1];
|
||||
int[] fileChannels = new int[1];
|
||||
ByteBuffer image = STBImage.stbi_load_from_memory(buffer, width, height, fileChannels, 4);
|
||||
if(image == null) {
|
||||
MemoryUtil.memFree(buffer);
|
||||
throw new IOException("Could not load image: " + STBImage.stbi_failure_reason());
|
||||
}
|
||||
imageData = MemoryUtil.memAddress(image);
|
||||
this.width = width[0];
|
||||
this.height = height[0];
|
||||
MemoryUtil.memFree(buffer);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
setTextureID(GL11.glGenTextures());
|
||||
bindTexture();
|
||||
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL13.GL_CLAMP_TO_BORDER);
|
||||
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData);
|
||||
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload()
|
||||
{
|
||||
if(imageData != 0)
|
||||
{
|
||||
STBImage.nstbi_image_free(imageData);
|
||||
imageData = 0;
|
||||
}
|
||||
int old = textureID;
|
||||
loadTexture();
|
||||
TextureManager.INSTANCE.removeTexture(old);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTexture()
|
||||
{
|
||||
super.deleteTexture();
|
||||
if(imageData != 0)
|
||||
{
|
||||
STBImage.nstbi_image_free(imageData);
|
||||
imageData = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
|
|||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.assets.reloader.IReloadableResource;
|
||||
import speiger.src.coreengine.rendering.input.window.Window;
|
||||
import speiger.src.coreengine.rendering.textures.TextureManager;
|
||||
import speiger.src.coreengine.rendering.textures.base.TextureManager;
|
||||
|
||||
public final class Cursor implements IReloadableResource
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ public class CollectionUtils
|
|||
List<T>[] list = new List[size];
|
||||
for(int i = 0;i<size;i++)
|
||||
{
|
||||
list[i] = new ObjectArrayList<T>();
|
||||
list[i] = new ObjectArrayList<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -6,10 +6,9 @@ import java.util.Set;
|
|||
|
||||
import speiger.src.collections.ints.collections.IntIterator;
|
||||
import speiger.src.collections.ints.maps.abstracts.AbstractInt2IntMap.BasicEntry;
|
||||
import speiger.src.collections.ints.maps.abstracts.AbstractInt2ObjectMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2IntMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
|
||||
import speiger.src.collections.ints.sets.IntAVLTreeSet;
|
||||
import speiger.src.collections.ints.sets.IntSet;
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
|
@ -166,7 +165,7 @@ public class DynamicDataManager<T>
|
|||
}
|
||||
return;
|
||||
}
|
||||
List<Entry<byte[]>> list = new ObjectArrayList<>();
|
||||
List<IntObjectPair<byte[]>> list = new ObjectArrayList<>();
|
||||
while(!changedSlots.isEmpty())
|
||||
{
|
||||
DataSlot start = null;
|
||||
|
@ -196,7 +195,7 @@ public class DynamicDataManager<T>
|
|||
bytesAllocated += start.getUsedBytes();
|
||||
start = start.next;
|
||||
}
|
||||
list.add(new AbstractInt2ObjectMap.BasicEntry<>(byteOffset, data));
|
||||
list.add(IntObjectPair.of(byteOffset, data));
|
||||
}
|
||||
if(!list.isEmpty())
|
||||
{
|
||||
|
|
|
@ -2,10 +2,10 @@ package speiger.src.coreengine.utils.collections.managers.dynamic;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
|
||||
|
||||
public interface IDynamicDataHandler<T>
|
||||
{
|
||||
public byte[] toBytes(T entry);
|
||||
public void uploadBytes(List<Entry<byte[]>> list, int newArraySize);
|
||||
public void uploadBytes(List<IntObjectPair<byte[]>> list, int newArraySize);
|
||||
}
|
||||
|
|
|
@ -10,10 +10,9 @@ import speiger.src.collections.ints.collections.IntIterator;
|
|||
import speiger.src.collections.ints.functions.IntComparator;
|
||||
import speiger.src.collections.ints.lists.IntArrayList;
|
||||
import speiger.src.collections.ints.lists.IntList;
|
||||
import speiger.src.collections.ints.maps.abstracts.AbstractInt2ObjectMap.BasicEntry;
|
||||
import speiger.src.collections.ints.maps.impl.hash.Int2IntOpenHashMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2IntMap;
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
|
||||
import speiger.src.collections.ints.sets.IntAVLTreeSet;
|
||||
import speiger.src.collections.ints.sets.IntLinkedOpenHashSet;
|
||||
import speiger.src.collections.ints.sets.IntSet;
|
||||
|
@ -284,7 +283,7 @@ public class FixedDataManager
|
|||
{
|
||||
ObjectArrays.quickSort(slots);
|
||||
List<FixedSlot> fixed = new ObjectArrayList<FixedSlot>();
|
||||
List<Entry<byte[]>> data = new ObjectArrayList<Entry<byte[]>>();
|
||||
List<IntObjectPair<byte[]>> data = new ObjectArrayList<>();
|
||||
FixedSlot first = null;
|
||||
FixedSlot last = null;
|
||||
for(int i = 0,m=slots.length;i<m;i++)
|
||||
|
@ -304,7 +303,7 @@ public class FixedDataManager
|
|||
ByteBuffer buffer = ByteBuffer.allocate(fixed.size() * bytes).order(ByteOrder.nativeOrder());
|
||||
handler.createData(buffer, fixed.size(), fixed);
|
||||
fixed.clear();
|
||||
data.add(new BasicEntry<byte[]>(first.index * bytes, buffer.array()));
|
||||
data.add(IntObjectPair.of(first.index * bytes, buffer.array()));
|
||||
i--;
|
||||
first = last = null;
|
||||
}
|
||||
|
@ -313,7 +312,7 @@ public class FixedDataManager
|
|||
ByteBuffer buffer = ByteBuffer.allocate(fixed.size() * bytes).order(ByteOrder.nativeOrder());
|
||||
handler.createData(buffer, fixed.size(), fixed);
|
||||
fixed.clear();
|
||||
data.add(new BasicEntry<byte[]>(first.index * bytes, buffer.array()));
|
||||
data.add(IntObjectPair.of(first.index * bytes, buffer.array()));
|
||||
}
|
||||
SLOTS.accept(slots);
|
||||
return new FinishingTask(handler, data, size);
|
||||
|
@ -339,10 +338,10 @@ public class FixedDataManager
|
|||
static class FinishingTask implements Runnable
|
||||
{
|
||||
IFixedDataHandler handler;
|
||||
List<Entry<byte[]>> data;
|
||||
List<IntObjectPair<byte[]>> data;
|
||||
int size;
|
||||
|
||||
public FinishingTask(IFixedDataHandler handler, List<Entry<byte[]>> data, int size)
|
||||
public FinishingTask(IFixedDataHandler handler, List<IntObjectPair<byte[]>> data, int size)
|
||||
{
|
||||
this.handler = handler;
|
||||
this.data = data;
|
||||
|
|
|
@ -3,11 +3,11 @@ package speiger.src.coreengine.utils.collections.managers.fixed;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap.Entry;
|
||||
import speiger.src.collections.ints.misc.pairs.IntObjectPair;
|
||||
|
||||
public interface IFixedDataHandler
|
||||
{
|
||||
public void createData(ByteBuffer data, int size, List<FixedSlot> slots);
|
||||
|
||||
public void updateData(List<Entry<byte[]>> list, int newSize);
|
||||
public void updateData(List<IntObjectPair<byte[]>> list, int newSize);
|
||||
}
|
|
@ -8,6 +8,8 @@ import java.io.InputStreamReader;
|
|||
import java.io.Reader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
|
@ -55,6 +57,32 @@ public class JsonUtil
|
|||
}
|
||||
}
|
||||
|
||||
public static void iterate(JsonElement element, Consumer<JsonObject> listener)
|
||||
{
|
||||
if(element.isJsonObject()) listener.accept(element.getAsJsonObject());
|
||||
else if(element.isJsonArray())
|
||||
{
|
||||
JsonArray array = element.getAsJsonArray();
|
||||
for(int i = 0,m=array.size();i<m;i++)
|
||||
{
|
||||
iterate(array.get(i), listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void iterate(JsonElement element, T input, BiConsumer<JsonObject, T> listener)
|
||||
{
|
||||
if(element.isJsonObject()) listener.accept(element.getAsJsonObject(), input);
|
||||
else if(element.isJsonArray())
|
||||
{
|
||||
JsonArray array = element.getAsJsonArray();
|
||||
for(int i = 0,m=array.size();i<m;i++)
|
||||
{
|
||||
iterate(array.get(i), input, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getOrDefault(JsonObject obj, String name, boolean defaultValue)
|
||||
{
|
||||
JsonElement el = obj.get(name);
|
||||
|
@ -103,6 +131,7 @@ public class JsonUtil
|
|||
return el == null ? defaultValue : el.getAsString();
|
||||
}
|
||||
|
||||
|
||||
public static JsonArray toArray(byte[] values)
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
|
@ -113,7 +142,28 @@ public class JsonUtil
|
|||
return array;
|
||||
}
|
||||
|
||||
public static byte[] parseArray(JsonArray array)
|
||||
public static JsonArray toArray(float[] values)
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
for(int i = 0,m=values.length;i<m;i++)
|
||||
{
|
||||
array.add(values[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static JsonArray toArray(Number[] values)
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
for(int i = 0,m=values.length;i<m;i++)
|
||||
{
|
||||
array.add(values[i]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] parseByteArray(JsonArray array)
|
||||
{
|
||||
byte[] data = new byte[array.size()];
|
||||
for(int i = 0,m=data.length;i<m;i++)
|
||||
|
@ -122,4 +172,14 @@ public class JsonUtil
|
|||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static float[] parseFloatArray(JsonArray array)
|
||||
{
|
||||
float[] data = new float[array.size()];
|
||||
for(int i = 0,m=data.length;i<m;i++)
|
||||
{
|
||||
data[i] = array.get(i).getAsFloat();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 72 KiB |
|
@ -1,395 +0,0 @@
|
|||
textureWidth=1024, textureHeight=512, base=39, fontHeight=50
|
||||
letter=0, minX=0, minY=0, maxX=0, maxY=50, bold=0
|
||||
letter=2, minX=0, minY=0, maxX=0, maxY=50, bold=0
|
||||
letter=9, minX=0, minY=0, maxX=0, maxY=50, bold=0
|
||||
letter=10, minX=0, minY=0, maxX=0, maxY=50, bold=0
|
||||
letter=13, minX=0, minY=0, maxX=0, maxY=50, bold=0
|
||||
letter=32, minX=0, minY=0, maxX=10, maxY=50, bold=0
|
||||
letter=33, minX=10, minY=0, maxX=21, maxY=50, bold=0
|
||||
letter=34, minX=21, minY=0, maxX=35, maxY=50, bold=0
|
||||
letter=35, minX=35, minY=0, maxX=61, maxY=50, bold=0
|
||||
letter=36, minX=61, minY=0, maxX=85, maxY=50, bold=0
|
||||
letter=37, minX=85, minY=0, maxX=116, maxY=50, bold=0
|
||||
letter=38, minX=116, minY=0, maxX=143, maxY=50, bold=0
|
||||
letter=39, minX=143, minY=0, maxX=150, maxY=50, bold=0
|
||||
letter=40, minX=150, minY=0, maxX=165, maxY=50, bold=0
|
||||
letter=41, minX=165, minY=0, maxX=180, maxY=50, bold=0
|
||||
letter=42, minX=180, minY=0, maxX=199, maxY=50, bold=0
|
||||
letter=43, minX=199, minY=0, maxX=222, maxY=50, bold=0
|
||||
letter=44, minX=222, minY=0, maxX=231, maxY=50, bold=0
|
||||
letter=45, minX=231, minY=0, maxX=245, maxY=50, bold=0
|
||||
letter=46, minX=245, minY=0, maxX=257, maxY=50, bold=0
|
||||
letter=47, minX=257, minY=0, maxX=274, maxY=50, bold=0
|
||||
letter=48, minX=274, minY=0, maxX=298, maxY=50, bold=0
|
||||
letter=49, minX=298, minY=0, maxX=322, maxY=50, bold=0
|
||||
letter=50, minX=322, minY=0, maxX=346, maxY=50, bold=0
|
||||
letter=51, minX=346, minY=0, maxX=370, maxY=50, bold=0
|
||||
letter=52, minX=370, minY=0, maxX=394, maxY=50, bold=0
|
||||
letter=53, minX=394, minY=0, maxX=418, maxY=50, bold=0
|
||||
letter=54, minX=418, minY=0, maxX=442, maxY=50, bold=0
|
||||
letter=55, minX=442, minY=0, maxX=466, maxY=50, bold=0
|
||||
letter=56, minX=466, minY=0, maxX=490, maxY=50, bold=0
|
||||
letter=57, minX=490, minY=0, maxX=514, maxY=50, bold=0
|
||||
letter=58, minX=514, minY=0, maxX=525, maxY=50, bold=0
|
||||
letter=59, minX=525, minY=0, maxX=535, maxY=50, bold=0
|
||||
letter=60, minX=535, minY=0, maxX=556, maxY=50, bold=0
|
||||
letter=61, minX=556, minY=0, maxX=580, maxY=50, bold=0
|
||||
letter=62, minX=580, minY=0, maxX=602, maxY=50, bold=0
|
||||
letter=63, minX=602, minY=0, maxX=622, maxY=50, bold=0
|
||||
letter=64, minX=622, minY=0, maxX=660, maxY=50, bold=0
|
||||
letter=65, minX=660, minY=0, maxX=688, maxY=50, bold=0
|
||||
letter=66, minX=688, minY=0, maxX=715, maxY=50, bold=0
|
||||
letter=67, minX=715, minY=0, maxX=742, maxY=50, bold=0
|
||||
letter=68, minX=742, minY=0, maxX=769, maxY=50, bold=0
|
||||
letter=69, minX=769, minY=0, maxX=793, maxY=50, bold=0
|
||||
letter=70, minX=793, minY=0, maxX=816, maxY=50, bold=0
|
||||
letter=71, minX=816, minY=0, maxX=845, maxY=50, bold=0
|
||||
letter=72, minX=845, minY=0, maxX=875, maxY=50, bold=0
|
||||
letter=73, minX=875, minY=0, maxX=887, maxY=50, bold=0
|
||||
letter=74, minX=887, minY=0, maxX=910, maxY=50, bold=0
|
||||
letter=75, minX=910, minY=0, maxX=936, maxY=50, bold=0
|
||||
letter=76, minX=936, minY=0, maxX=959, maxY=50, bold=0
|
||||
letter=77, minX=959, minY=0, maxX=996, maxY=50, bold=0
|
||||
letter=78, minX=0, minY=51, maxX=30, maxY=101, bold=0
|
||||
letter=79, minX=30, minY=51, maxX=59, maxY=101, bold=0
|
||||
letter=80, minX=59, minY=51, maxX=86, maxY=101, bold=0
|
||||
letter=81, minX=86, minY=51, maxX=115, maxY=101, bold=0
|
||||
letter=82, minX=115, minY=51, maxX=141, maxY=101, bold=0
|
||||
letter=83, minX=141, minY=51, maxX=166, maxY=101, bold=0
|
||||
letter=84, minX=166, minY=51, maxX=191, maxY=101, bold=0
|
||||
letter=85, minX=191, minY=51, maxX=218, maxY=101, bold=0
|
||||
letter=86, minX=218, minY=51, maxX=245, maxY=101, bold=0
|
||||
letter=87, minX=245, minY=51, maxX=282, maxY=101, bold=0
|
||||
letter=88, minX=282, minY=51, maxX=309, maxY=101, bold=0
|
||||
letter=89, minX=309, minY=51, maxX=335, maxY=101, bold=0
|
||||
letter=90, minX=335, minY=51, maxX=360, maxY=101, bold=0
|
||||
letter=91, minX=360, minY=51, maxX=372, maxY=101, bold=0
|
||||
letter=92, minX=372, minY=51, maxX=390, maxY=101, bold=0
|
||||
letter=93, minX=390, minY=51, maxX=402, maxY=101, bold=0
|
||||
letter=94, minX=402, minY=51, maxX=420, maxY=101, bold=0
|
||||
letter=95, minX=420, minY=51, maxX=439, maxY=101, bold=0
|
||||
letter=96, minX=439, minY=51, maxX=453, maxY=101, bold=0
|
||||
letter=97, minX=453, minY=51, maxX=476, maxY=101, bold=0
|
||||
letter=98, minX=476, minY=51, maxX=500, maxY=101, bold=0
|
||||
letter=99, minX=500, minY=51, maxX=522, maxY=101, bold=0
|
||||
letter=100, minX=522, minY=51, maxX=546, maxY=101, bold=0
|
||||
letter=101, minX=546, minY=51, maxX=569, maxY=101, bold=0
|
||||
letter=102, minX=569, minY=51, maxX=584, maxY=101, bold=0
|
||||
letter=103, minX=584, minY=51, maxX=608, maxY=101, bold=0
|
||||
letter=104, minX=608, minY=51, maxX=631, maxY=101, bold=0
|
||||
letter=105, minX=631, minY=51, maxX=642, maxY=101, bold=0
|
||||
letter=32, minX=642, minY=51, maxX=652, maxY=101, bold=0
|
||||
letter=106, minX=652, minY=51, maxX=663, maxY=101, bold=0
|
||||
letter=107, minX=663, minY=51, maxX=685, maxY=101, bold=0
|
||||
letter=108, minX=685, minY=51, maxX=696, maxY=101, bold=0
|
||||
letter=109, minX=696, minY=51, maxX=733, maxY=101, bold=0
|
||||
letter=110, minX=733, minY=51, maxX=756, maxY=101, bold=0
|
||||
letter=111, minX=756, minY=51, maxX=780, maxY=101, bold=0
|
||||
letter=112, minX=780, minY=51, maxX=804, maxY=101, bold=0
|
||||
letter=113, minX=804, minY=51, maxX=828, maxY=101, bold=0
|
||||
letter=114, minX=828, minY=51, maxX=843, maxY=101, bold=0
|
||||
letter=115, minX=843, minY=51, maxX=865, maxY=101, bold=0
|
||||
letter=116, minX=865, minY=51, maxX=879, maxY=101, bold=0
|
||||
letter=117, minX=879, minY=51, maxX=902, maxY=101, bold=0
|
||||
letter=118, minX=902, minY=51, maxX=923, maxY=101, bold=0
|
||||
letter=119, minX=923, minY=51, maxX=954, maxY=101, bold=0
|
||||
letter=120, minX=954, minY=51, maxX=975, maxY=101, bold=0
|
||||
letter=121, minX=975, minY=51, maxX=995, maxY=101, bold=0
|
||||
letter=122, minX=995, minY=51, maxX=1016, maxY=101, bold=0
|
||||
letter=123, minX=0, minY=102, maxX=14, maxY=152, bold=0
|
||||
letter=124, minX=14, minY=102, maxX=25, maxY=152, bold=0
|
||||
letter=125, minX=25, minY=102, maxX=39, maxY=152, bold=0
|
||||
letter=126, minX=39, minY=102, maxX=67, maxY=152, bold=0
|
||||
letter=160, minX=67, minY=102, maxX=77, maxY=152, bold=0
|
||||
letter=161, minX=77, minY=102, maxX=88, maxY=152, bold=0
|
||||
letter=162, minX=88, minY=102, maxX=112, maxY=152, bold=0
|
||||
letter=163, minX=112, minY=102, maxX=137, maxY=152, bold=0
|
||||
letter=164, minX=137, minY=102, maxX=166, maxY=152, bold=0
|
||||
letter=165, minX=166, minY=102, maxX=188, maxY=152, bold=0
|
||||
letter=166, minX=188, minY=102, maxX=198, maxY=152, bold=0
|
||||
letter=167, minX=198, minY=102, maxX=224, maxY=152, bold=0
|
||||
letter=168, minX=224, minY=102, maxX=242, maxY=152, bold=0
|
||||
letter=169, minX=242, minY=102, maxX=275, maxY=152, bold=0
|
||||
letter=170, minX=275, minY=102, maxX=294, maxY=152, bold=0
|
||||
letter=171, minX=294, minY=102, maxX=314, maxY=152, bold=0
|
||||
letter=172, minX=314, minY=102, maxX=337, maxY=152, bold=0
|
||||
letter=173, minX=337, minY=102, maxX=351, maxY=152, bold=0
|
||||
letter=174, minX=351, minY=102, maxX=384, maxY=152, bold=0
|
||||
letter=175, minX=384, minY=102, maxX=404, maxY=152, bold=0
|
||||
letter=176, minX=404, minY=102, maxX=420, maxY=152, bold=0
|
||||
letter=177, minX=420, minY=102, maxX=443, maxY=152, bold=0
|
||||
letter=178, minX=443, minY=102, maxX=459, maxY=152, bold=0
|
||||
letter=179, minX=459, minY=102, maxX=475, maxY=152, bold=0
|
||||
letter=180, minX=475, minY=102, maxX=489, maxY=152, bold=0
|
||||
letter=181, minX=489, minY=102, maxX=514, maxY=152, bold=0
|
||||
letter=182, minX=514, minY=102, maxX=535, maxY=152, bold=0
|
||||
letter=183, minX=535, minY=102, maxX=547, maxY=152, bold=0
|
||||
letter=184, minX=547, minY=102, maxX=558, maxY=152, bold=0
|
||||
letter=185, minX=558, minY=102, maxX=574, maxY=152, bold=0
|
||||
letter=186, minX=574, minY=102, maxX=593, maxY=152, bold=0
|
||||
letter=187, minX=593, minY=102, maxX=613, maxY=152, bold=0
|
||||
letter=188, minX=613, minY=102, maxX=644, maxY=152, bold=0
|
||||
letter=189, minX=644, minY=102, maxX=676, maxY=152, bold=0
|
||||
letter=190, minX=676, minY=102, maxX=709, maxY=152, bold=0
|
||||
letter=191, minX=709, minY=102, maxX=729, maxY=152, bold=0
|
||||
letter=192, minX=729, minY=102, maxX=757, maxY=152, bold=0
|
||||
letter=193, minX=757, minY=102, maxX=785, maxY=152, bold=0
|
||||
letter=194, minX=785, minY=102, maxX=813, maxY=152, bold=0
|
||||
letter=195, minX=813, minY=102, maxX=841, maxY=152, bold=0
|
||||
letter=196, minX=841, minY=102, maxX=869, maxY=152, bold=0
|
||||
letter=197, minX=869, minY=102, maxX=897, maxY=152, bold=0
|
||||
letter=198, minX=897, minY=102, maxX=936, maxY=152, bold=0
|
||||
letter=199, minX=936, minY=102, maxX=963, maxY=152, bold=0
|
||||
letter=200, minX=963, minY=102, maxX=987, maxY=152, bold=0
|
||||
letter=201, minX=987, minY=102, maxX=1011, maxY=152, bold=0
|
||||
letter=202, minX=0, minY=153, maxX=24, maxY=203, bold=0
|
||||
letter=203, minX=24, minY=153, maxX=48, maxY=203, bold=0
|
||||
letter=204, minX=48, minY=153, maxX=60, maxY=203, bold=0
|
||||
letter=205, minX=60, minY=153, maxX=72, maxY=203, bold=0
|
||||
letter=206, minX=72, minY=153, maxX=84, maxY=203, bold=0
|
||||
letter=207, minX=84, minY=153, maxX=96, maxY=203, bold=0
|
||||
letter=208, minX=96, minY=153, maxX=124, maxY=203, bold=0
|
||||
letter=209, minX=124, minY=153, maxX=154, maxY=203, bold=0
|
||||
letter=210, minX=154, minY=153, maxX=183, maxY=203, bold=0
|
||||
letter=211, minX=183, minY=153, maxX=212, maxY=203, bold=0
|
||||
letter=212, minX=212, minY=153, maxX=241, maxY=203, bold=0
|
||||
letter=213, minX=241, minY=153, maxX=270, maxY=203, bold=0
|
||||
letter=214, minX=270, minY=153, maxX=299, maxY=203, bold=0
|
||||
letter=215, minX=299, minY=153, maxX=321, maxY=203, bold=0
|
||||
letter=216, minX=321, minY=153, maxX=350, maxY=203, bold=0
|
||||
letter=217, minX=350, minY=153, maxX=377, maxY=203, bold=0
|
||||
letter=218, minX=377, minY=153, maxX=404, maxY=203, bold=0
|
||||
letter=219, minX=404, minY=153, maxX=431, maxY=203, bold=0
|
||||
letter=220, minX=431, minY=153, maxX=458, maxY=203, bold=0
|
||||
letter=221, minX=458, minY=153, maxX=484, maxY=203, bold=0
|
||||
letter=222, minX=484, minY=153, maxX=509, maxY=203, bold=0
|
||||
letter=223, minX=509, minY=153, maxX=535, maxY=203, bold=0
|
||||
letter=224, minX=535, minY=153, maxX=558, maxY=203, bold=0
|
||||
letter=225, minX=558, minY=153, maxX=581, maxY=203, bold=0
|
||||
letter=226, minX=581, minY=153, maxX=604, maxY=203, bold=0
|
||||
letter=227, minX=604, minY=153, maxX=627, maxY=203, bold=0
|
||||
letter=228, minX=627, minY=153, maxX=650, maxY=203, bold=0
|
||||
letter=229, minX=650, minY=153, maxX=673, maxY=203, bold=0
|
||||
letter=230, minX=673, minY=153, maxX=708, maxY=203, bold=0
|
||||
letter=231, minX=708, minY=153, maxX=730, maxY=203, bold=0
|
||||
letter=232, minX=730, minY=153, maxX=753, maxY=203, bold=0
|
||||
letter=233, minX=753, minY=153, maxX=776, maxY=203, bold=0
|
||||
letter=234, minX=776, minY=153, maxX=799, maxY=203, bold=0
|
||||
letter=235, minX=799, minY=153, maxX=822, maxY=203, bold=0
|
||||
letter=236, minX=822, minY=153, maxX=833, maxY=203, bold=0
|
||||
letter=237, minX=833, minY=153, maxX=844, maxY=203, bold=0
|
||||
letter=238, minX=844, minY=153, maxX=855, maxY=203, bold=0
|
||||
letter=239, minX=855, minY=153, maxX=866, maxY=203, bold=0
|
||||
letter=240, minX=866, minY=153, maxX=890, maxY=203, bold=0
|
||||
letter=241, minX=890, minY=153, maxX=913, maxY=203, bold=0
|
||||
letter=242, minX=913, minY=153, maxX=937, maxY=203, bold=0
|
||||
letter=243, minX=937, minY=153, maxX=961, maxY=203, bold=0
|
||||
letter=244, minX=961, minY=153, maxX=985, maxY=203, bold=0
|
||||
letter=245, minX=985, minY=153, maxX=1009, maxY=203, bold=0
|
||||
letter=246, minX=0, minY=204, maxX=24, maxY=254, bold=0
|
||||
letter=247, minX=24, minY=204, maxX=48, maxY=254, bold=0
|
||||
letter=248, minX=48, minY=204, maxX=72, maxY=254, bold=0
|
||||
letter=249, minX=72, minY=204, maxX=95, maxY=254, bold=0
|
||||
letter=250, minX=95, minY=204, maxX=118, maxY=254, bold=0
|
||||
letter=251, minX=118, minY=204, maxX=141, maxY=254, bold=0
|
||||
letter=252, minX=141, minY=204, maxX=164, maxY=254, bold=0
|
||||
letter=253, minX=164, minY=204, maxX=184, maxY=254, bold=0
|
||||
letter=254, minX=184, minY=204, maxX=208, maxY=254, bold=0
|
||||
letter=255, minX=208, minY=204, maxX=228, maxY=254, bold=0
|
||||
letter=0, minX=0, minY=0, maxX=0, maxY=50, bold=1
|
||||
letter=2, minX=0, minY=0, maxX=0, maxY=50, bold=1
|
||||
letter=9, minX=0, minY=0, maxX=0, maxY=50, bold=1
|
||||
letter=10, minX=0, minY=0, maxX=0, maxY=50, bold=1
|
||||
letter=13, minX=0, minY=0, maxX=0, maxY=50, bold=1
|
||||
letter=32, minX=228, minY=204, maxX=240, maxY=254, bold=1
|
||||
letter=33, minX=240, minY=204, maxX=253, maxY=254, bold=1
|
||||
letter=34, minX=253, minY=204, maxX=269, maxY=254, bold=1
|
||||
letter=35, minX=269, minY=204, maxX=297, maxY=254, bold=1
|
||||
letter=36, minX=297, minY=204, maxX=323, maxY=254, bold=1
|
||||
letter=37, minX=323, minY=204, maxX=356, maxY=254, bold=1
|
||||
letter=38, minX=356, minY=204, maxX=385, maxY=254, bold=1
|
||||
letter=39, minX=385, minY=204, maxX=394, maxY=254, bold=1
|
||||
letter=40, minX=394, minY=204, maxX=411, maxY=254, bold=1
|
||||
letter=41, minX=411, minY=204, maxX=428, maxY=254, bold=1
|
||||
letter=42, minX=428, minY=204, maxX=449, maxY=254, bold=1
|
||||
letter=43, minX=449, minY=204, maxX=474, maxY=254, bold=1
|
||||
letter=44, minX=474, minY=204, maxX=485, maxY=254, bold=1
|
||||
letter=45, minX=485, minY=204, maxX=501, maxY=254, bold=1
|
||||
letter=46, minX=501, minY=204, maxX=515, maxY=254, bold=1
|
||||
letter=47, minX=515, minY=204, maxX=534, maxY=254, bold=1
|
||||
letter=48, minX=534, minY=204, maxX=560, maxY=254, bold=1
|
||||
letter=49, minX=560, minY=204, maxX=586, maxY=254, bold=1
|
||||
letter=50, minX=586, minY=204, maxX=612, maxY=254, bold=1
|
||||
letter=51, minX=612, minY=204, maxX=638, maxY=254, bold=1
|
||||
letter=52, minX=638, minY=204, maxX=664, maxY=254, bold=1
|
||||
letter=53, minX=664, minY=204, maxX=690, maxY=254, bold=1
|
||||
letter=54, minX=690, minY=204, maxX=716, maxY=254, bold=1
|
||||
letter=55, minX=716, minY=204, maxX=742, maxY=254, bold=1
|
||||
letter=56, minX=742, minY=204, maxX=768, maxY=254, bold=1
|
||||
letter=57, minX=768, minY=204, maxX=794, maxY=254, bold=1
|
||||
letter=58, minX=794, minY=204, maxX=807, maxY=254, bold=1
|
||||
letter=59, minX=807, minY=204, maxX=819, maxY=254, bold=1
|
||||
letter=60, minX=819, minY=204, maxX=842, maxY=254, bold=1
|
||||
letter=61, minX=842, minY=204, maxX=868, maxY=254, bold=1
|
||||
letter=62, minX=868, minY=204, maxX=892, maxY=254, bold=1
|
||||
letter=63, minX=892, minY=204, maxX=914, maxY=254, bold=1
|
||||
letter=64, minX=914, minY=204, maxX=954, maxY=254, bold=1
|
||||
letter=65, minX=954, minY=204, maxX=984, maxY=254, bold=1
|
||||
letter=66, minX=984, minY=204, maxX=1013, maxY=254, bold=1
|
||||
letter=67, minX=0, minY=255, maxX=29, maxY=305, bold=1
|
||||
letter=68, minX=29, minY=255, maxX=58, maxY=305, bold=1
|
||||
letter=69, minX=58, minY=255, maxX=84, maxY=305, bold=1
|
||||
letter=70, minX=84, minY=255, maxX=109, maxY=305, bold=1
|
||||
letter=71, minX=109, minY=255, maxX=140, maxY=305, bold=1
|
||||
letter=72, minX=140, minY=255, maxX=172, maxY=305, bold=1
|
||||
letter=73, minX=172, minY=255, maxX=186, maxY=305, bold=1
|
||||
letter=74, minX=186, minY=255, maxX=211, maxY=305, bold=1
|
||||
letter=75, minX=211, minY=255, maxX=239, maxY=305, bold=1
|
||||
letter=76, minX=239, minY=255, maxX=264, maxY=305, bold=1
|
||||
letter=77, minX=264, minY=255, maxX=303, maxY=305, bold=1
|
||||
letter=78, minX=303, minY=255, maxX=335, maxY=305, bold=1
|
||||
letter=79, minX=335, minY=255, maxX=366, maxY=305, bold=1
|
||||
letter=80, minX=366, minY=255, maxX=395, maxY=305, bold=1
|
||||
letter=81, minX=395, minY=255, maxX=426, maxY=305, bold=1
|
||||
letter=82, minX=426, minY=255, maxX=454, maxY=305, bold=1
|
||||
letter=83, minX=454, minY=255, maxX=481, maxY=305, bold=1
|
||||
letter=84, minX=481, minY=255, maxX=508, maxY=305, bold=1
|
||||
letter=85, minX=508, minY=255, maxX=537, maxY=305, bold=1
|
||||
letter=86, minX=537, minY=255, maxX=566, maxY=305, bold=1
|
||||
letter=87, minX=566, minY=255, maxX=605, maxY=305, bold=1
|
||||
letter=88, minX=605, minY=255, maxX=634, maxY=305, bold=1
|
||||
letter=89, minX=634, minY=255, maxX=662, maxY=305, bold=1
|
||||
letter=90, minX=662, minY=255, maxX=689, maxY=305, bold=1
|
||||
letter=91, minX=689, minY=255, maxX=703, maxY=305, bold=1
|
||||
letter=92, minX=703, minY=255, maxX=723, maxY=305, bold=1
|
||||
letter=93, minX=723, minY=255, maxX=737, maxY=305, bold=1
|
||||
letter=94, minX=737, minY=255, maxX=757, maxY=305, bold=1
|
||||
letter=95, minX=757, minY=255, maxX=778, maxY=305, bold=1
|
||||
letter=96, minX=778, minY=255, maxX=794, maxY=305, bold=1
|
||||
letter=97, minX=794, minY=255, maxX=819, maxY=305, bold=1
|
||||
letter=98, minX=819, minY=255, maxX=845, maxY=305, bold=1
|
||||
letter=99, minX=845, minY=255, maxX=869, maxY=305, bold=1
|
||||
letter=100, minX=869, minY=255, maxX=895, maxY=305, bold=1
|
||||
letter=101, minX=895, minY=255, maxX=920, maxY=305, bold=1
|
||||
letter=102, minX=920, minY=255, maxX=937, maxY=305, bold=1
|
||||
letter=103, minX=937, minY=255, maxX=963, maxY=305, bold=1
|
||||
letter=104, minX=963, minY=255, maxX=988, maxY=305, bold=1
|
||||
letter=105, minX=988, minY=255, maxX=1001, maxY=305, bold=1
|
||||
letter=32, minX=1001, minY=255, maxX=1013, maxY=305, bold=1
|
||||
letter=106, minX=0, minY=306, maxX=13, maxY=356, bold=1
|
||||
letter=107, minX=13, minY=306, maxX=37, maxY=356, bold=1
|
||||
letter=108, minX=37, minY=306, maxX=50, maxY=356, bold=1
|
||||
letter=109, minX=50, minY=306, maxX=89, maxY=356, bold=1
|
||||
letter=110, minX=89, minY=306, maxX=114, maxY=356, bold=1
|
||||
letter=111, minX=114, minY=306, maxX=140, maxY=356, bold=1
|
||||
letter=112, minX=140, minY=306, maxX=166, maxY=356, bold=1
|
||||
letter=113, minX=166, minY=306, maxX=192, maxY=356, bold=1
|
||||
letter=114, minX=192, minY=306, maxX=209, maxY=356, bold=1
|
||||
letter=115, minX=209, minY=306, maxX=233, maxY=356, bold=1
|
||||
letter=116, minX=233, minY=306, maxX=249, maxY=356, bold=1
|
||||
letter=117, minX=249, minY=306, maxX=274, maxY=356, bold=1
|
||||
letter=118, minX=274, minY=306, maxX=297, maxY=356, bold=1
|
||||
letter=119, minX=297, minY=306, maxX=330, maxY=356, bold=1
|
||||
letter=120, minX=330, minY=306, maxX=353, maxY=356, bold=1
|
||||
letter=121, minX=353, minY=306, maxX=375, maxY=356, bold=1
|
||||
letter=122, minX=375, minY=306, maxX=398, maxY=356, bold=1
|
||||
letter=123, minX=398, minY=306, maxX=414, maxY=356, bold=1
|
||||
letter=124, minX=414, minY=306, maxX=427, maxY=356, bold=1
|
||||
letter=125, minX=427, minY=306, maxX=443, maxY=356, bold=1
|
||||
letter=126, minX=443, minY=306, maxX=473, maxY=356, bold=1
|
||||
letter=160, minX=473, minY=306, maxX=485, maxY=356, bold=1
|
||||
letter=161, minX=485, minY=306, maxX=498, maxY=356, bold=1
|
||||
letter=162, minX=498, minY=306, maxX=524, maxY=356, bold=1
|
||||
letter=163, minX=524, minY=306, maxX=551, maxY=356, bold=1
|
||||
letter=164, minX=551, minY=306, maxX=582, maxY=356, bold=1
|
||||
letter=165, minX=582, minY=306, maxX=606, maxY=356, bold=1
|
||||
letter=166, minX=606, minY=306, maxX=618, maxY=356, bold=1
|
||||
letter=167, minX=618, minY=306, maxX=646, maxY=356, bold=1
|
||||
letter=168, minX=646, minY=306, maxX=666, maxY=356, bold=1
|
||||
letter=169, minX=666, minY=306, maxX=701, maxY=356, bold=1
|
||||
letter=170, minX=701, minY=306, maxX=722, maxY=356, bold=1
|
||||
letter=171, minX=722, minY=306, maxX=744, maxY=356, bold=1
|
||||
letter=172, minX=744, minY=306, maxX=769, maxY=356, bold=1
|
||||
letter=173, minX=769, minY=306, maxX=785, maxY=356, bold=1
|
||||
letter=174, minX=785, minY=306, maxX=820, maxY=356, bold=1
|
||||
letter=175, minX=820, minY=306, maxX=842, maxY=356, bold=1
|
||||
letter=176, minX=842, minY=306, maxX=860, maxY=356, bold=1
|
||||
letter=177, minX=860, minY=306, maxX=885, maxY=356, bold=1
|
||||
letter=178, minX=885, minY=306, maxX=903, maxY=356, bold=1
|
||||
letter=179, minX=903, minY=306, maxX=921, maxY=356, bold=1
|
||||
letter=180, minX=921, minY=306, maxX=937, maxY=356, bold=1
|
||||
letter=181, minX=937, minY=306, maxX=964, maxY=356, bold=1
|
||||
letter=182, minX=964, minY=306, maxX=987, maxY=356, bold=1
|
||||
letter=183, minX=987, minY=306, maxX=1001, maxY=356, bold=1
|
||||
letter=184, minX=1001, minY=306, maxX=1014, maxY=356, bold=1
|
||||
letter=185, minX=0, minY=357, maxX=18, maxY=407, bold=1
|
||||
letter=186, minX=18, minY=357, maxX=39, maxY=407, bold=1
|
||||
letter=187, minX=39, minY=357, maxX=61, maxY=407, bold=1
|
||||
letter=188, minX=61, minY=357, maxX=94, maxY=407, bold=1
|
||||
letter=189, minX=94, minY=357, maxX=128, maxY=407, bold=1
|
||||
letter=190, minX=128, minY=357, maxX=163, maxY=407, bold=1
|
||||
letter=191, minX=163, minY=357, maxX=185, maxY=407, bold=1
|
||||
letter=192, minX=185, minY=357, maxX=215, maxY=407, bold=1
|
||||
letter=193, minX=215, minY=357, maxX=245, maxY=407, bold=1
|
||||
letter=194, minX=245, minY=357, maxX=275, maxY=407, bold=1
|
||||
letter=195, minX=275, minY=357, maxX=305, maxY=407, bold=1
|
||||
letter=196, minX=305, minY=357, maxX=335, maxY=407, bold=1
|
||||
letter=197, minX=335, minY=357, maxX=365, maxY=407, bold=1
|
||||
letter=198, minX=365, minY=357, maxX=406, maxY=407, bold=1
|
||||
letter=199, minX=406, minY=357, maxX=435, maxY=407, bold=1
|
||||
letter=200, minX=435, minY=357, maxX=461, maxY=407, bold=1
|
||||
letter=201, minX=461, minY=357, maxX=487, maxY=407, bold=1
|
||||
letter=202, minX=487, minY=357, maxX=513, maxY=407, bold=1
|
||||
letter=203, minX=513, minY=357, maxX=539, maxY=407, bold=1
|
||||
letter=204, minX=539, minY=357, maxX=553, maxY=407, bold=1
|
||||
letter=205, minX=553, minY=357, maxX=567, maxY=407, bold=1
|
||||
letter=206, minX=567, minY=357, maxX=581, maxY=407, bold=1
|
||||
letter=207, minX=581, minY=357, maxX=595, maxY=407, bold=1
|
||||
letter=208, minX=595, minY=357, maxX=625, maxY=407, bold=1
|
||||
letter=209, minX=625, minY=357, maxX=657, maxY=407, bold=1
|
||||
letter=210, minX=657, minY=357, maxX=688, maxY=407, bold=1
|
||||
letter=211, minX=688, minY=357, maxX=719, maxY=407, bold=1
|
||||
letter=212, minX=719, minY=357, maxX=750, maxY=407, bold=1
|
||||
letter=213, minX=750, minY=357, maxX=781, maxY=407, bold=1
|
||||
letter=214, minX=781, minY=357, maxX=812, maxY=407, bold=1
|
||||
letter=215, minX=812, minY=357, maxX=836, maxY=407, bold=1
|
||||
letter=216, minX=836, minY=357, maxX=867, maxY=407, bold=1
|
||||
letter=217, minX=867, minY=357, maxX=896, maxY=407, bold=1
|
||||
letter=218, minX=896, minY=357, maxX=925, maxY=407, bold=1
|
||||
letter=219, minX=925, minY=357, maxX=954, maxY=407, bold=1
|
||||
letter=220, minX=954, minY=357, maxX=983, maxY=407, bold=1
|
||||
letter=221, minX=983, minY=357, maxX=1011, maxY=407, bold=1
|
||||
letter=222, minX=0, minY=408, maxX=27, maxY=458, bold=1
|
||||
letter=223, minX=27, minY=408, maxX=55, maxY=458, bold=1
|
||||
letter=224, minX=55, minY=408, maxX=80, maxY=458, bold=1
|
||||
letter=225, minX=80, minY=408, maxX=105, maxY=458, bold=1
|
||||
letter=226, minX=105, minY=408, maxX=130, maxY=458, bold=1
|
||||
letter=227, minX=130, minY=408, maxX=155, maxY=458, bold=1
|
||||
letter=228, minX=155, minY=408, maxX=180, maxY=458, bold=1
|
||||
letter=229, minX=180, minY=408, maxX=205, maxY=458, bold=1
|
||||
letter=230, minX=205, minY=408, maxX=242, maxY=458, bold=1
|
||||
letter=231, minX=242, minY=408, maxX=266, maxY=458, bold=1
|
||||
letter=232, minX=266, minY=408, maxX=291, maxY=458, bold=1
|
||||
letter=233, minX=291, minY=408, maxX=316, maxY=458, bold=1
|
||||
letter=234, minX=316, minY=408, maxX=341, maxY=458, bold=1
|
||||
letter=235, minX=341, minY=408, maxX=366, maxY=458, bold=1
|
||||
letter=236, minX=366, minY=408, maxX=379, maxY=458, bold=1
|
||||
letter=237, minX=379, minY=408, maxX=392, maxY=458, bold=1
|
||||
letter=238, minX=392, minY=408, maxX=405, maxY=458, bold=1
|
||||
letter=239, minX=405, minY=408, maxX=418, maxY=458, bold=1
|
||||
letter=240, minX=418, minY=408, maxX=444, maxY=458, bold=1
|
||||
letter=241, minX=444, minY=408, maxX=469, maxY=458, bold=1
|
||||
letter=242, minX=469, minY=408, maxX=495, maxY=458, bold=1
|
||||
letter=243, minX=495, minY=408, maxX=521, maxY=458, bold=1
|
||||
letter=244, minX=521, minY=408, maxX=547, maxY=458, bold=1
|
||||
letter=245, minX=547, minY=408, maxX=573, maxY=458, bold=1
|
||||
letter=246, minX=573, minY=408, maxX=599, maxY=458, bold=1
|
||||
letter=247, minX=599, minY=408, maxX=625, maxY=458, bold=1
|
||||
letter=248, minX=625, minY=408, maxX=651, maxY=458, bold=1
|
||||
letter=249, minX=651, minY=408, maxX=676, maxY=458, bold=1
|
||||
letter=250, minX=676, minY=408, maxX=701, maxY=458, bold=1
|
||||
letter=251, minX=701, minY=408, maxX=726, maxY=458, bold=1
|
||||
letter=252, minX=726, minY=408, maxX=751, maxY=458, bold=1
|
||||
letter=253, minX=751, minY=408, maxX=773, maxY=458, bold=1
|
||||
letter=254, minX=773, minY=408, maxX=799, maxY=458, bold=1
|
||||
letter=255, minX=799, minY=408, maxX=821, maxY=458, bold=1
|
|
@ -0,0 +1,405 @@
|
|||
{
|
||||
"type": "bitmap",
|
||||
"file": "base:font/roboto_texture.png",
|
||||
"info": {
|
||||
"width": 2048,
|
||||
"height": 1024,
|
||||
"base": 80,
|
||||
"charHeight": 100,
|
||||
"tabs": 4
|
||||
},
|
||||
"chars": [
|
||||
{"char": 198, "minX": 0, "minY": 0, "maxX": 79, "maxY": 100, "bold": true},
|
||||
{"char": 64, "minX": 79, "minY": 0, "maxX": 154, "maxY": 100, "bold": true},
|
||||
{"char": 109, "minX": 154, "minY": 0, "maxX": 227, "maxY": 100, "bold": true},
|
||||
{"char": 87, "minX": 227, "minY": 0, "maxX": 300, "maxY": 100, "bold": true},
|
||||
{"char": 77, "minX": 300, "minY": 0, "maxX": 373, "maxY": 100, "bold": true},
|
||||
{"char": 198, "minX": 373, "minY": 0, "maxX": 448, "maxY": 96, "bold": false},
|
||||
{"char": 64, "minX": 448, "minY": 0, "maxX": 520, "maxY": 96, "bold": false},
|
||||
{"char": 109, "minX": 520, "minY": 0, "maxX": 590, "maxY": 96, "bold": false},
|
||||
{"char": 87, "minX": 590, "minY": 0, "maxX": 660, "maxY": 96, "bold": false},
|
||||
{"char": 77, "minX": 660, "minY": 0, "maxX": 730, "maxY": 96, "bold": false},
|
||||
{"char": 230, "minX": 730, "minY": 0, "maxX": 798, "maxY": 96, "bold": false},
|
||||
{"char": 190, "minX": 798, "minY": 0, "maxX": 861, "maxY": 96, "bold": false},
|
||||
{"char": 174, "minX": 861, "minY": 0, "maxX": 924, "maxY": 96, "bold": false},
|
||||
{"char": 169, "minX": 924, "minY": 0, "maxX": 987, "maxY": 96, "bold": false},
|
||||
{"char": 189, "minX": 987, "minY": 0, "maxX": 1049, "maxY": 96, "bold": false},
|
||||
{"char": 119, "minX": 1049, "minY": 0, "maxX": 1108, "maxY": 96, "bold": false},
|
||||
{"char": 37, "minX": 1108, "minY": 0, "maxX": 1167, "maxY": 96, "bold": false},
|
||||
{"char": 188, "minX": 1167, "minY": 0, "maxX": 1225, "maxY": 96, "bold": false},
|
||||
{"char": 209, "minX": 1225, "minY": 0, "maxX": 1282, "maxY": 96, "bold": false},
|
||||
{"char": 72, "minX": 1282, "minY": 0, "maxX": 1339, "maxY": 96, "bold": false},
|
||||
{"char": 78, "minX": 1339, "minY": 0, "maxX": 1396, "maxY": 96, "bold": false},
|
||||
{"char": 164, "minX": 1396, "minY": 0, "maxX": 1452, "maxY": 96, "bold": false},
|
||||
{"char": 210, "minX": 1452, "minY": 0, "maxX": 1507, "maxY": 96, "bold": false},
|
||||
{"char": 211, "minX": 1507, "minY": 0, "maxX": 1562, "maxY": 96, "bold": false},
|
||||
{"char": 212, "minX": 1562, "minY": 0, "maxX": 1617, "maxY": 96, "bold": false},
|
||||
{"char": 213, "minX": 1617, "minY": 0, "maxX": 1672, "maxY": 96, "bold": false},
|
||||
{"char": 214, "minX": 1672, "minY": 0, "maxX": 1727, "maxY": 96, "bold": false},
|
||||
{"char": 216, "minX": 1727, "minY": 0, "maxX": 1782, "maxY": 96, "bold": false},
|
||||
{"char": 79, "minX": 1782, "minY": 0, "maxX": 1837, "maxY": 96, "bold": false},
|
||||
{"char": 81, "minX": 1837, "minY": 0, "maxX": 1892, "maxY": 96, "bold": false},
|
||||
{"char": 71, "minX": 1892, "minY": 0, "maxX": 1946, "maxY": 96, "bold": false},
|
||||
{"char": 196, "minX": 1946, "minY": 0, "maxX": 1999, "maxY": 96, "bold": false},
|
||||
{"char": 221, "minX": 1999, "minY": 0, "maxX": 2048, "maxY": 96, "bold": false},
|
||||
{"char": 230, "minX": 0, "minY": 100, "maxX": 71, "maxY": 200, "bold": true},
|
||||
{"char": 190, "minX": 71, "minY": 100, "maxX": 137, "maxY": 200, "bold": true},
|
||||
{"char": 174, "minX": 137, "minY": 100, "maxX": 203, "maxY": 200, "bold": true},
|
||||
{"char": 169, "minX": 203, "minY": 100, "maxX": 269, "maxY": 200, "bold": true},
|
||||
{"char": 189, "minX": 269, "minY": 100, "maxX": 334, "maxY": 200, "bold": true},
|
||||
{"char": 119, "minX": 334, "minY": 100, "maxX": 396, "maxY": 200, "bold": true},
|
||||
{"char": 37, "minX": 396, "minY": 100, "maxX": 458, "maxY": 200, "bold": true},
|
||||
{"char": 188, "minX": 458, "minY": 100, "maxX": 519, "maxY": 200, "bold": true},
|
||||
{"char": 209, "minX": 519, "minY": 100, "maxX": 579, "maxY": 200, "bold": true},
|
||||
{"char": 72, "minX": 579, "minY": 100, "maxX": 639, "maxY": 200, "bold": true},
|
||||
{"char": 78, "minX": 639, "minY": 100, "maxX": 699, "maxY": 200, "bold": true},
|
||||
{"char": 164, "minX": 699, "minY": 100, "maxX": 758, "maxY": 200, "bold": true},
|
||||
{"char": 210, "minX": 758, "minY": 100, "maxX": 816, "maxY": 200, "bold": true},
|
||||
{"char": 211, "minX": 816, "minY": 100, "maxX": 874, "maxY": 200, "bold": true},
|
||||
{"char": 212, "minX": 874, "minY": 100, "maxX": 932, "maxY": 200, "bold": true},
|
||||
{"char": 213, "minX": 932, "minY": 100, "maxX": 990, "maxY": 200, "bold": true},
|
||||
{"char": 214, "minX": 990, "minY": 100, "maxX": 1048, "maxY": 200, "bold": true},
|
||||
{"char": 216, "minX": 1048, "minY": 100, "maxX": 1106, "maxY": 200, "bold": true},
|
||||
{"char": 196, "minX": 1106, "minY": 100, "maxX": 1164, "maxY": 200, "bold": true},
|
||||
{"char": 197, "minX": 1164, "minY": 100, "maxX": 1222, "maxY": 200, "bold": true},
|
||||
{"char": 192, "minX": 1222, "minY": 100, "maxX": 1280, "maxY": 200, "bold": true},
|
||||
{"char": 193, "minX": 1280, "minY": 100, "maxX": 1338, "maxY": 200, "bold": true},
|
||||
{"char": 194, "minX": 1338, "minY": 100, "maxX": 1396, "maxY": 200, "bold": true},
|
||||
{"char": 195, "minX": 1396, "minY": 100, "maxX": 1454, "maxY": 200, "bold": true},
|
||||
{"char": 79, "minX": 1454, "minY": 100, "maxX": 1512, "maxY": 200, "bold": true},
|
||||
{"char": 81, "minX": 1512, "minY": 100, "maxX": 1570, "maxY": 200, "bold": true},
|
||||
{"char": 65, "minX": 1570, "minY": 100, "maxX": 1628, "maxY": 200, "bold": true},
|
||||
{"char": 71, "minX": 1628, "minY": 100, "maxX": 1685, "maxY": 200, "bold": true},
|
||||
{"char": 126, "minX": 1685, "minY": 100, "maxX": 1741, "maxY": 200, "bold": true},
|
||||
{"char": 220, "minX": 1741, "minY": 100, "maxX": 1796, "maxY": 200, "bold": true},
|
||||
{"char": 217, "minX": 1796, "minY": 100, "maxX": 1851, "maxY": 200, "bold": true},
|
||||
{"char": 218, "minX": 1851, "minY": 100, "maxX": 1906, "maxY": 200, "bold": true},
|
||||
{"char": 219, "minX": 1906, "minY": 100, "maxX": 1961, "maxY": 200, "bold": true},
|
||||
{"char": 199, "minX": 1961, "minY": 100, "maxX": 2016, "maxY": 200, "bold": true},
|
||||
{"char": 239, "minX": 2016, "minY": 100, "maxX": 2048, "maxY": 200, "bold": true},
|
||||
{"char": 85, "minX": 0, "minY": 200, "maxX": 55, "maxY": 300, "bold": true},
|
||||
{"char": 86, "minX": 55, "minY": 200, "maxX": 110, "maxY": 300, "bold": true},
|
||||
{"char": 67, "minX": 110, "minY": 200, "maxX": 165, "maxY": 300, "bold": true},
|
||||
{"char": 68, "minX": 165, "minY": 200, "maxX": 220, "maxY": 300, "bold": true},
|
||||
{"char": 221, "minX": 220, "minY": 200, "maxX": 274, "maxY": 300, "bold": true},
|
||||
{"char": 208, "minX": 274, "minY": 200, "maxX": 328, "maxY": 300, "bold": true},
|
||||
{"char": 80, "minX": 328, "minY": 200, "maxX": 382, "maxY": 300, "bold": true},
|
||||
{"char": 88, "minX": 382, "minY": 200, "maxX": 436, "maxY": 300, "bold": true},
|
||||
{"char": 89, "minX": 436, "minY": 200, "maxX": 490, "maxY": 300, "bold": true},
|
||||
{"char": 38, "minX": 490, "minY": 200, "maxX": 544, "maxY": 300, "bold": true},
|
||||
{"char": 167, "minX": 544, "minY": 200, "maxX": 597, "maxY": 300, "bold": true},
|
||||
{"char": 82, "minX": 597, "minY": 200, "maxX": 650, "maxY": 300, "bold": true},
|
||||
{"char": 75, "minX": 650, "minY": 200, "maxX": 703, "maxY": 300, "bold": true},
|
||||
{"char": 66, "minX": 703, "minY": 200, "maxX": 756, "maxY": 300, "bold": true},
|
||||
{"char": 223, "minX": 756, "minY": 200, "maxX": 808, "maxY": 300, "bold": true},
|
||||
{"char": 84, "minX": 808, "minY": 200, "maxX": 860, "maxY": 300, "bold": true},
|
||||
{"char": 35, "minX": 860, "minY": 200, "maxX": 912, "maxY": 300, "bold": true},
|
||||
{"char": 222, "minX": 912, "minY": 200, "maxX": 963, "maxY": 300, "bold": true},
|
||||
{"char": 83, "minX": 963, "minY": 200, "maxX": 1014, "maxY": 300, "bold": true},
|
||||
{"char": 90, "minX": 1014, "minY": 200, "maxX": 1065, "maxY": 300, "bold": true},
|
||||
{"char": 197, "minX": 1065, "minY": 200, "maxX": 1118, "maxY": 296, "bold": false},
|
||||
{"char": 192, "minX": 1118, "minY": 200, "maxX": 1171, "maxY": 296, "bold": false},
|
||||
{"char": 193, "minX": 1171, "minY": 200, "maxX": 1224, "maxY": 296, "bold": false},
|
||||
{"char": 194, "minX": 1224, "minY": 200, "maxX": 1277, "maxY": 296, "bold": false},
|
||||
{"char": 195, "minX": 1277, "minY": 200, "maxX": 1330, "maxY": 296, "bold": false},
|
||||
{"char": 126, "minX": 1330, "minY": 200, "maxX": 1383, "maxY": 296, "bold": false},
|
||||
{"char": 65, "minX": 1383, "minY": 200, "maxX": 1436, "maxY": 296, "bold": false},
|
||||
{"char": 220, "minX": 1436, "minY": 200, "maxX": 1488, "maxY": 296, "bold": false},
|
||||
{"char": 217, "minX": 1488, "minY": 200, "maxX": 1540, "maxY": 296, "bold": false},
|
||||
{"char": 218, "minX": 1540, "minY": 200, "maxX": 1592, "maxY": 296, "bold": false},
|
||||
{"char": 219, "minX": 1592, "minY": 200, "maxX": 1644, "maxY": 296, "bold": false},
|
||||
{"char": 199, "minX": 1644, "minY": 200, "maxX": 1696, "maxY": 296, "bold": false},
|
||||
{"char": 85, "minX": 1696, "minY": 200, "maxX": 1748, "maxY": 296, "bold": false},
|
||||
{"char": 86, "minX": 1748, "minY": 200, "maxX": 1800, "maxY": 296, "bold": false},
|
||||
{"char": 67, "minX": 1800, "minY": 200, "maxX": 1852, "maxY": 296, "bold": false},
|
||||
{"char": 68, "minX": 1852, "minY": 200, "maxX": 1904, "maxY": 296, "bold": false},
|
||||
{"char": 208, "minX": 1904, "minY": 200, "maxX": 1955, "maxY": 296, "bold": false},
|
||||
{"char": 80, "minX": 1955, "minY": 200, "maxX": 2006, "maxY": 296, "bold": false},
|
||||
{"char": 231, "minX": 2006, "minY": 200, "maxX": 2048, "maxY": 296, "bold": false},
|
||||
{"char": 240, "minX": 0, "minY": 300, "maxX": 50, "maxY": 400, "bold": true},
|
||||
{"char": 181, "minX": 50, "minY": 300, "maxX": 100, "maxY": 400, "bold": true},
|
||||
{"char": 163, "minX": 100, "minY": 300, "maxX": 150, "maxY": 400, "bold": true},
|
||||
{"char": 244, "minX": 150, "minY": 300, "maxX": 199, "maxY": 400, "bold": true},
|
||||
{"char": 245, "minX": 199, "minY": 300, "maxX": 248, "maxY": 400, "bold": true},
|
||||
{"char": 246, "minX": 248, "minY": 300, "maxX": 297, "maxY": 400, "bold": true},
|
||||
{"char": 247, "minX": 297, "minY": 300, "maxX": 346, "maxY": 400, "bold": true},
|
||||
{"char": 254, "minX": 346, "minY": 300, "maxX": 395, "maxY": 400, "bold": true},
|
||||
{"char": 242, "minX": 395, "minY": 300, "maxX": 444, "maxY": 400, "bold": true},
|
||||
{"char": 243, "minX": 444, "minY": 300, "maxX": 493, "maxY": 400, "bold": true},
|
||||
{"char": 111, "minX": 493, "minY": 300, "maxX": 542, "maxY": 400, "bold": true},
|
||||
{"char": 88, "minX": 542, "minY": 300, "maxX": 593, "maxY": 396, "bold": false},
|
||||
{"char": 38, "minX": 593, "minY": 300, "maxX": 644, "maxY": 396, "bold": false},
|
||||
{"char": 167, "minX": 644, "minY": 300, "maxX": 694, "maxY": 396, "bold": false},
|
||||
{"char": 82, "minX": 694, "minY": 300, "maxX": 744, "maxY": 396, "bold": false},
|
||||
{"char": 75, "minX": 744, "minY": 300, "maxX": 794, "maxY": 396, "bold": false},
|
||||
{"char": 66, "minX": 794, "minY": 300, "maxX": 844, "maxY": 396, "bold": false},
|
||||
{"char": 223, "minX": 844, "minY": 300, "maxX": 893, "maxY": 396, "bold": false},
|
||||
{"char": 84, "minX": 893, "minY": 300, "maxX": 942, "maxY": 396, "bold": false},
|
||||
{"char": 89, "minX": 942, "minY": 300, "maxX": 991, "maxY": 396, "bold": false},
|
||||
{"char": 35, "minX": 991, "minY": 300, "maxX": 1040, "maxY": 396, "bold": false},
|
||||
{"char": 222, "minX": 1040, "minY": 300, "maxX": 1088, "maxY": 396, "bold": false},
|
||||
{"char": 83, "minX": 1088, "minY": 300, "maxX": 1136, "maxY": 396, "bold": false},
|
||||
{"char": 90, "minX": 1136, "minY": 300, "maxX": 1184, "maxY": 396, "bold": false},
|
||||
{"char": 240, "minX": 1184, "minY": 300, "maxX": 1231, "maxY": 396, "bold": false},
|
||||
{"char": 181, "minX": 1231, "minY": 300, "maxX": 1278, "maxY": 396, "bold": false},
|
||||
{"char": 163, "minX": 1278, "minY": 300, "maxX": 1325, "maxY": 396, "bold": false},
|
||||
{"char": 244, "minX": 1325, "minY": 300, "maxX": 1371, "maxY": 396, "bold": false},
|
||||
{"char": 245, "minX": 1371, "minY": 300, "maxX": 1417, "maxY": 396, "bold": false},
|
||||
{"char": 246, "minX": 1417, "minY": 300, "maxX": 1463, "maxY": 396, "bold": false},
|
||||
{"char": 247, "minX": 1463, "minY": 300, "maxX": 1509, "maxY": 396, "bold": false},
|
||||
{"char": 254, "minX": 1509, "minY": 300, "maxX": 1555, "maxY": 396, "bold": false},
|
||||
{"char": 242, "minX": 1555, "minY": 300, "maxX": 1601, "maxY": 396, "bold": false},
|
||||
{"char": 243, "minX": 1601, "minY": 300, "maxX": 1647, "maxY": 396, "bold": false},
|
||||
{"char": 111, "minX": 1647, "minY": 300, "maxX": 1693, "maxY": 396, "bold": false},
|
||||
{"char": 248, "minX": 1693, "minY": 300, "maxX": 1738, "maxY": 396, "bold": false},
|
||||
{"char": 241, "minX": 1738, "minY": 300, "maxX": 1783, "maxY": 396, "bold": false},
|
||||
{"char": 200, "minX": 1783, "minY": 300, "maxX": 1828, "maxY": 396, "bold": false},
|
||||
{"char": 201, "minX": 1828, "minY": 300, "maxX": 1873, "maxY": 396, "bold": false},
|
||||
{"char": 202, "minX": 1873, "minY": 300, "maxX": 1918, "maxY": 396, "bold": false},
|
||||
{"char": 203, "minX": 1918, "minY": 300, "maxX": 1963, "maxY": 396, "bold": false},
|
||||
{"char": 162, "minX": 1963, "minY": 300, "maxX": 2008, "maxY": 396, "bold": false},
|
||||
{"char": 118, "minX": 2008, "minY": 300, "maxX": 2048, "maxY": 396, "bold": false},
|
||||
{"char": 248, "minX": 0, "minY": 400, "maxX": 48, "maxY": 500, "bold": true},
|
||||
{"char": 241, "minX": 48, "minY": 400, "maxX": 96, "maxY": 500, "bold": true},
|
||||
{"char": 200, "minX": 96, "minY": 400, "maxX": 144, "maxY": 500, "bold": true},
|
||||
{"char": 201, "minX": 144, "minY": 400, "maxX": 192, "maxY": 500, "bold": true},
|
||||
{"char": 202, "minX": 192, "minY": 400, "maxX": 240, "maxY": 500, "bold": true},
|
||||
{"char": 203, "minX": 240, "minY": 400, "maxX": 288, "maxY": 500, "bold": true},
|
||||
{"char": 162, "minX": 288, "minY": 400, "maxX": 336, "maxY": 500, "bold": true},
|
||||
{"char": 165, "minX": 336, "minY": 400, "maxX": 384, "maxY": 500, "bold": true},
|
||||
{"char": 103, "minX": 384, "minY": 400, "maxX": 432, "maxY": 500, "bold": true},
|
||||
{"char": 110, "minX": 432, "minY": 400, "maxX": 480, "maxY": 500, "bold": true},
|
||||
{"char": 112, "minX": 480, "minY": 400, "maxX": 528, "maxY": 500, "bold": true},
|
||||
{"char": 113, "minX": 528, "minY": 400, "maxX": 576, "maxY": 500, "bold": true},
|
||||
{"char": 98, "minX": 576, "minY": 400, "maxX": 624, "maxY": 500, "bold": true},
|
||||
{"char": 100, "minX": 624, "minY": 400, "maxX": 672, "maxY": 500, "bold": true},
|
||||
{"char": 69, "minX": 672, "minY": 400, "maxX": 720, "maxY": 500, "bold": true},
|
||||
{"char": 55, "minX": 720, "minY": 400, "maxX": 768, "maxY": 500, "bold": true},
|
||||
{"char": 56, "minX": 768, "minY": 400, "maxX": 816, "maxY": 500, "bold": true},
|
||||
{"char": 57, "minX": 816, "minY": 400, "maxX": 864, "maxY": 500, "bold": true},
|
||||
{"char": 61, "minX": 864, "minY": 400, "maxX": 912, "maxY": 500, "bold": true},
|
||||
{"char": 43, "minX": 912, "minY": 400, "maxX": 960, "maxY": 500, "bold": true},
|
||||
{"char": 48, "minX": 960, "minY": 400, "maxX": 1008, "maxY": 500, "bold": true},
|
||||
{"char": 49, "minX": 1008, "minY": 400, "maxX": 1056, "maxY": 500, "bold": true},
|
||||
{"char": 50, "minX": 1056, "minY": 400, "maxX": 1104, "maxY": 500, "bold": true},
|
||||
{"char": 51, "minX": 1104, "minY": 400, "maxX": 1152, "maxY": 500, "bold": true},
|
||||
{"char": 52, "minX": 1152, "minY": 400, "maxX": 1200, "maxY": 500, "bold": true},
|
||||
{"char": 53, "minX": 1200, "minY": 400, "maxX": 1248, "maxY": 500, "bold": true},
|
||||
{"char": 54, "minX": 1248, "minY": 400, "maxX": 1296, "maxY": 500, "bold": true},
|
||||
{"char": 36, "minX": 1296, "minY": 400, "maxX": 1344, "maxY": 500, "bold": true},
|
||||
{"char": 249, "minX": 1344, "minY": 400, "maxX": 1391, "maxY": 500, "bold": true},
|
||||
{"char": 250, "minX": 1391, "minY": 400, "maxX": 1438, "maxY": 500, "bold": true},
|
||||
{"char": 251, "minX": 1438, "minY": 400, "maxX": 1485, "maxY": 500, "bold": true},
|
||||
{"char": 252, "minX": 1485, "minY": 400, "maxX": 1532, "maxY": 500, "bold": true},
|
||||
{"char": 172, "minX": 1532, "minY": 400, "maxX": 1579, "maxY": 500, "bold": true},
|
||||
{"char": 117, "minX": 1579, "minY": 400, "maxX": 1626, "maxY": 500, "bold": true},
|
||||
{"char": 104, "minX": 1626, "minY": 400, "maxX": 1673, "maxY": 500, "bold": true},
|
||||
{"char": 70, "minX": 1673, "minY": 400, "maxX": 1720, "maxY": 500, "bold": true},
|
||||
{"char": 74, "minX": 1720, "minY": 400, "maxX": 1767, "maxY": 500, "bold": true},
|
||||
{"char": 232, "minX": 1767, "minY": 400, "maxX": 1813, "maxY": 500, "bold": true},
|
||||
{"char": 233, "minX": 1813, "minY": 400, "maxX": 1859, "maxY": 500, "bold": true},
|
||||
{"char": 234, "minX": 1859, "minY": 400, "maxX": 1905, "maxY": 500, "bold": true},
|
||||
{"char": 235, "minX": 1905, "minY": 400, "maxX": 1951, "maxY": 500, "bold": true},
|
||||
{"char": 224, "minX": 1951, "minY": 400, "maxX": 1997, "maxY": 500, "bold": true},
|
||||
{"char": 225, "minX": 1997, "minY": 400, "maxX": 2043, "maxY": 500, "bold": true},
|
||||
{"char": 226, "minX": 0, "minY": 500, "maxX": 46, "maxY": 600, "bold": true},
|
||||
{"char": 227, "minX": 46, "minY": 500, "maxX": 92, "maxY": 600, "bold": true},
|
||||
{"char": 228, "minX": 92, "minY": 500, "maxX": 138, "maxY": 600, "bold": true},
|
||||
{"char": 229, "minX": 138, "minY": 500, "maxX": 184, "maxY": 600, "bold": true},
|
||||
{"char": 215, "minX": 184, "minY": 500, "maxX": 230, "maxY": 600, "bold": true},
|
||||
{"char": 177, "minX": 230, "minY": 500, "maxX": 276, "maxY": 600, "bold": true},
|
||||
{"char": 97, "minX": 276, "minY": 500, "maxX": 322, "maxY": 600, "bold": true},
|
||||
{"char": 101, "minX": 322, "minY": 500, "maxX": 368, "maxY": 600, "bold": true},
|
||||
{"char": 76, "minX": 368, "minY": 500, "maxX": 414, "maxY": 600, "bold": true},
|
||||
{"char": 231, "minX": 414, "minY": 500, "maxX": 459, "maxY": 600, "bold": true},
|
||||
{"char": 120, "minX": 459, "minY": 500, "maxX": 504, "maxY": 600, "bold": true},
|
||||
{"char": 107, "minX": 504, "minY": 500, "maxX": 549, "maxY": 600, "bold": true},
|
||||
{"char": 99, "minX": 549, "minY": 500, "maxX": 594, "maxY": 600, "bold": true},
|
||||
{"char": 62, "minX": 594, "minY": 500, "maxX": 639, "maxY": 600, "bold": true},
|
||||
{"char": 253, "minX": 639, "minY": 500, "maxX": 683, "maxY": 600, "bold": true},
|
||||
{"char": 255, "minX": 683, "minY": 500, "maxX": 727, "maxY": 600, "bold": true},
|
||||
{"char": 115, "minX": 727, "minY": 500, "maxX": 771, "maxY": 600, "bold": true},
|
||||
{"char": 121, "minX": 771, "minY": 500, "maxX": 815, "maxY": 600, "bold": true},
|
||||
{"char": 60, "minX": 815, "minY": 500, "maxX": 859, "maxY": 600, "bold": true},
|
||||
{"char": 103, "minX": 859, "minY": 500, "maxX": 904, "maxY": 596, "bold": false},
|
||||
{"char": 110, "minX": 904, "minY": 500, "maxX": 949, "maxY": 596, "bold": false},
|
||||
{"char": 112, "minX": 949, "minY": 500, "maxX": 994, "maxY": 596, "bold": false},
|
||||
{"char": 113, "minX": 994, "minY": 500, "maxX": 1039, "maxY": 596, "bold": false},
|
||||
{"char": 98, "minX": 1039, "minY": 500, "maxX": 1084, "maxY": 596, "bold": false},
|
||||
{"char": 100, "minX": 1084, "minY": 500, "maxX": 1129, "maxY": 596, "bold": false},
|
||||
{"char": 69, "minX": 1129, "minY": 500, "maxX": 1174, "maxY": 596, "bold": false},
|
||||
{"char": 55, "minX": 1174, "minY": 500, "maxX": 1219, "maxY": 596, "bold": false},
|
||||
{"char": 56, "minX": 1219, "minY": 500, "maxX": 1264, "maxY": 596, "bold": false},
|
||||
{"char": 57, "minX": 1264, "minY": 500, "maxX": 1309, "maxY": 596, "bold": false},
|
||||
{"char": 61, "minX": 1309, "minY": 500, "maxX": 1354, "maxY": 596, "bold": false},
|
||||
{"char": 43, "minX": 1354, "minY": 500, "maxX": 1399, "maxY": 596, "bold": false},
|
||||
{"char": 48, "minX": 1399, "minY": 500, "maxX": 1444, "maxY": 596, "bold": false},
|
||||
{"char": 49, "minX": 1444, "minY": 500, "maxX": 1489, "maxY": 596, "bold": false},
|
||||
{"char": 50, "minX": 1489, "minY": 500, "maxX": 1534, "maxY": 596, "bold": false},
|
||||
{"char": 51, "minX": 1534, "minY": 500, "maxX": 1579, "maxY": 596, "bold": false},
|
||||
{"char": 52, "minX": 1579, "minY": 500, "maxX": 1624, "maxY": 596, "bold": false},
|
||||
{"char": 53, "minX": 1624, "minY": 500, "maxX": 1669, "maxY": 596, "bold": false},
|
||||
{"char": 54, "minX": 1669, "minY": 500, "maxX": 1714, "maxY": 596, "bold": false},
|
||||
{"char": 36, "minX": 1714, "minY": 500, "maxX": 1759, "maxY": 596, "bold": false},
|
||||
{"char": 249, "minX": 1759, "minY": 500, "maxX": 1803, "maxY": 596, "bold": false},
|
||||
{"char": 250, "minX": 1803, "minY": 500, "maxX": 1847, "maxY": 596, "bold": false},
|
||||
{"char": 251, "minX": 1847, "minY": 500, "maxX": 1891, "maxY": 596, "bold": false},
|
||||
{"char": 252, "minX": 1891, "minY": 500, "maxX": 1935, "maxY": 596, "bold": false},
|
||||
{"char": 172, "minX": 1935, "minY": 500, "maxX": 1979, "maxY": 596, "bold": false},
|
||||
{"char": 117, "minX": 1979, "minY": 500, "maxX": 2023, "maxY": 596, "bold": false},
|
||||
{"char": 205, "minX": 2023, "minY": 500, "maxX": 2046, "maxY": 596, "bold": false},
|
||||
{"char": 118, "minX": 0, "minY": 600, "maxX": 43, "maxY": 700, "bold": true},
|
||||
{"char": 122, "minX": 43, "minY": 600, "maxX": 86, "maxY": 700, "bold": true},
|
||||
{"char": 104, "minX": 86, "minY": 600, "maxX": 130, "maxY": 696, "bold": false},
|
||||
{"char": 70, "minX": 130, "minY": 600, "maxX": 174, "maxY": 696, "bold": false},
|
||||
{"char": 74, "minX": 174, "minY": 600, "maxX": 218, "maxY": 696, "bold": false},
|
||||
{"char": 232, "minX": 218, "minY": 600, "maxX": 261, "maxY": 696, "bold": false},
|
||||
{"char": 233, "minX": 261, "minY": 600, "maxX": 304, "maxY": 696, "bold": false},
|
||||
{"char": 234, "minX": 304, "minY": 600, "maxX": 347, "maxY": 696, "bold": false},
|
||||
{"char": 235, "minX": 347, "minY": 600, "maxX": 390, "maxY": 696, "bold": false},
|
||||
{"char": 224, "minX": 390, "minY": 600, "maxX": 433, "maxY": 696, "bold": false},
|
||||
{"char": 225, "minX": 433, "minY": 600, "maxX": 476, "maxY": 696, "bold": false},
|
||||
{"char": 226, "minX": 476, "minY": 600, "maxX": 519, "maxY": 696, "bold": false},
|
||||
{"char": 227, "minX": 519, "minY": 600, "maxX": 562, "maxY": 696, "bold": false},
|
||||
{"char": 228, "minX": 562, "minY": 600, "maxX": 605, "maxY": 696, "bold": false},
|
||||
{"char": 229, "minX": 605, "minY": 600, "maxX": 648, "maxY": 696, "bold": false},
|
||||
{"char": 215, "minX": 648, "minY": 600, "maxX": 691, "maxY": 696, "bold": false},
|
||||
{"char": 177, "minX": 691, "minY": 600, "maxX": 734, "maxY": 696, "bold": false},
|
||||
{"char": 165, "minX": 734, "minY": 600, "maxX": 777, "maxY": 696, "bold": false},
|
||||
{"char": 97, "minX": 777, "minY": 600, "maxX": 820, "maxY": 696, "bold": false},
|
||||
{"char": 101, "minX": 820, "minY": 600, "maxX": 863, "maxY": 696, "bold": false},
|
||||
{"char": 76, "minX": 863, "minY": 600, "maxX": 906, "maxY": 696, "bold": false},
|
||||
{"char": 107, "minX": 906, "minY": 600, "maxX": 948, "maxY": 696, "bold": false},
|
||||
{"char": 99, "minX": 948, "minY": 600, "maxX": 990, "maxY": 696, "bold": false},
|
||||
{"char": 62, "minX": 990, "minY": 600, "maxX": 1032, "maxY": 696, "bold": false},
|
||||
{"char": 115, "minX": 1032, "minY": 600, "maxX": 1073, "maxY": 696, "bold": false},
|
||||
{"char": 60, "minX": 1073, "minY": 600, "maxX": 1114, "maxY": 696, "bold": false},
|
||||
{"char": 120, "minX": 1114, "minY": 600, "maxX": 1154, "maxY": 696, "bold": false},
|
||||
{"char": 122, "minX": 1154, "minY": 600, "maxX": 1194, "maxY": 696, "bold": false},
|
||||
{"char": 253, "minX": 1194, "minY": 600, "maxX": 1233, "maxY": 696, "bold": false},
|
||||
{"char": 255, "minX": 1233, "minY": 600, "maxX": 1272, "maxY": 696, "bold": false},
|
||||
{"char": 187, "minX": 1272, "minY": 600, "maxX": 1311, "maxY": 696, "bold": false},
|
||||
{"char": 191, "minX": 1311, "minY": 600, "maxX": 1350, "maxY": 696, "bold": false},
|
||||
{"char": 175, "minX": 1350, "minY": 600, "maxX": 1389, "maxY": 696, "bold": false},
|
||||
{"char": 182, "minX": 1389, "minY": 600, "maxX": 1428, "maxY": 696, "bold": false},
|
||||
{"char": 171, "minX": 1428, "minY": 600, "maxX": 1467, "maxY": 696, "bold": false},
|
||||
{"char": 121, "minX": 1467, "minY": 600, "maxX": 1506, "maxY": 696, "bold": false},
|
||||
{"char": 63, "minX": 1506, "minY": 600, "maxX": 1545, "maxY": 696, "bold": false},
|
||||
{"char": 186, "minX": 1545, "minY": 600, "maxX": 1582, "maxY": 696, "bold": false},
|
||||
{"char": 170, "minX": 1582, "minY": 600, "maxX": 1618, "maxY": 696, "bold": false},
|
||||
{"char": 95, "minX": 1618, "minY": 600, "maxX": 1654, "maxY": 696, "bold": false},
|
||||
{"char": 168, "minX": 1654, "minY": 600, "maxX": 1689, "maxY": 696, "bold": false},
|
||||
{"char": 42, "minX": 1689, "minY": 600, "maxX": 1724, "maxY": 696, "bold": false},
|
||||
{"char": 94, "minX": 1724, "minY": 600, "maxX": 1758, "maxY": 696, "bold": false},
|
||||
{"char": 92, "minX": 1758, "minY": 600, "maxX": 1791, "maxY": 696, "bold": false},
|
||||
{"char": 47, "minX": 1791, "minY": 600, "maxX": 1823, "maxY": 696, "bold": false},
|
||||
{"char": 185, "minX": 1823, "minY": 600, "maxX": 1853, "maxY": 696, "bold": false},
|
||||
{"char": 176, "minX": 1853, "minY": 600, "maxX": 1883, "maxY": 696, "bold": false},
|
||||
{"char": 178, "minX": 1883, "minY": 600, "maxX": 1913, "maxY": 696, "bold": false},
|
||||
{"char": 179, "minX": 1913, "minY": 600, "maxX": 1943, "maxY": 696, "bold": false},
|
||||
{"char": 239, "minX": 1943, "minY": 600, "maxX": 1972, "maxY": 696, "bold": false},
|
||||
{"char": 207, "minX": 1972, "minY": 600, "maxX": 2001, "maxY": 696, "bold": false},
|
||||
{"char": 238, "minX": 2001, "minY": 600, "maxX": 2029, "maxY": 696, "bold": false},
|
||||
{"char": 106, "minX": 2029, "minY": 600, "maxX": 2048, "maxY": 696, "bold": false},
|
||||
{"char": 187, "minX": 0, "minY": 700, "maxX": 42, "maxY": 800, "bold": true},
|
||||
{"char": 191, "minX": 42, "minY": 700, "maxX": 84, "maxY": 800, "bold": true},
|
||||
{"char": 175, "minX": 84, "minY": 700, "maxX": 126, "maxY": 800, "bold": true},
|
||||
{"char": 182, "minX": 126, "minY": 700, "maxX": 168, "maxY": 800, "bold": true},
|
||||
{"char": 171, "minX": 168, "minY": 700, "maxX": 210, "maxY": 800, "bold": true},
|
||||
{"char": 63, "minX": 210, "minY": 700, "maxX": 252, "maxY": 800, "bold": true},
|
||||
{"char": 186, "minX": 252, "minY": 700, "maxX": 292, "maxY": 800, "bold": true},
|
||||
{"char": 170, "minX": 292, "minY": 700, "maxX": 331, "maxY": 800, "bold": true},
|
||||
{"char": 95, "minX": 331, "minY": 700, "maxX": 370, "maxY": 800, "bold": true},
|
||||
{"char": 168, "minX": 370, "minY": 700, "maxX": 408, "maxY": 800, "bold": true},
|
||||
{"char": 42, "minX": 408, "minY": 700, "maxX": 446, "maxY": 800, "bold": true},
|
||||
{"char": 94, "minX": 446, "minY": 700, "maxX": 483, "maxY": 800, "bold": true},
|
||||
{"char": 92, "minX": 483, "minY": 700, "maxX": 519, "maxY": 800, "bold": true},
|
||||
{"char": 47, "minX": 519, "minY": 700, "maxX": 554, "maxY": 800, "bold": true},
|
||||
{"char": 185, "minX": 554, "minY": 700, "maxX": 587, "maxY": 800, "bold": true},
|
||||
{"char": 176, "minX": 587, "minY": 700, "maxX": 620, "maxY": 800, "bold": true},
|
||||
{"char": 178, "minX": 620, "minY": 700, "maxX": 653, "maxY": 800, "bold": true},
|
||||
{"char": 179, "minX": 653, "minY": 700, "maxX": 686, "maxY": 800, "bold": true},
|
||||
{"char": 207, "minX": 686, "minY": 700, "maxX": 718, "maxY": 800, "bold": true},
|
||||
{"char": 238, "minX": 718, "minY": 700, "maxX": 749, "maxY": 800, "bold": true},
|
||||
{"char": 206, "minX": 749, "minY": 700, "maxX": 780, "maxY": 800, "bold": true},
|
||||
{"char": 114, "minX": 780, "minY": 700, "maxX": 811, "maxY": 800, "bold": true},
|
||||
{"char": 102, "minX": 811, "minY": 700, "maxX": 842, "maxY": 800, "bold": true},
|
||||
{"char": 40, "minX": 842, "minY": 700, "maxX": 873, "maxY": 800, "bold": true},
|
||||
{"char": 41, "minX": 873, "minY": 700, "maxX": 904, "maxY": 800, "bold": true},
|
||||
{"char": 116, "minX": 904, "minY": 700, "maxX": 934, "maxY": 800, "bold": true},
|
||||
{"char": 123, "minX": 934, "minY": 700, "maxX": 964, "maxY": 800, "bold": true},
|
||||
{"char": 125, "minX": 964, "minY": 700, "maxX": 994, "maxY": 800, "bold": true},
|
||||
{"char": 173, "minX": 994, "minY": 700, "maxX": 1023, "maxY": 800, "bold": true},
|
||||
{"char": 180, "minX": 1023, "minY": 700, "maxX": 1052, "maxY": 800, "bold": true},
|
||||
{"char": 45, "minX": 1052, "minY": 700, "maxX": 1081, "maxY": 800, "bold": true},
|
||||
{"char": 34, "minX": 1081, "minY": 700, "maxX": 1110, "maxY": 800, "bold": true},
|
||||
{"char": 206, "minX": 1110, "minY": 700, "maxX": 1138, "maxY": 796, "bold": false},
|
||||
{"char": 114, "minX": 1138, "minY": 700, "maxX": 1166, "maxY": 796, "bold": false},
|
||||
{"char": 102, "minX": 1166, "minY": 700, "maxX": 1194, "maxY": 796, "bold": false},
|
||||
{"char": 40, "minX": 1194, "minY": 700, "maxX": 1222, "maxY": 796, "bold": false},
|
||||
{"char": 41, "minX": 1222, "minY": 700, "maxX": 1250, "maxY": 796, "bold": false},
|
||||
{"char": 116, "minX": 1250, "minY": 700, "maxX": 1277, "maxY": 796, "bold": false},
|
||||
{"char": 123, "minX": 1277, "minY": 700, "maxX": 1304, "maxY": 796, "bold": false},
|
||||
{"char": 125, "minX": 1304, "minY": 700, "maxX": 1331, "maxY": 796, "bold": false},
|
||||
{"char": 173, "minX": 1331, "minY": 700, "maxX": 1357, "maxY": 796, "bold": false},
|
||||
{"char": 180, "minX": 1357, "minY": 700, "maxX": 1383, "maxY": 796, "bold": false},
|
||||
{"char": 96, "minX": 1383, "minY": 700, "maxX": 1409, "maxY": 796, "bold": false},
|
||||
{"char": 45, "minX": 1409, "minY": 700, "maxX": 1435, "maxY": 796, "bold": false},
|
||||
{"char": 34, "minX": 1435, "minY": 700, "maxX": 1461, "maxY": 796, "bold": false},
|
||||
{"char": 183, "minX": 1461, "minY": 700, "maxX": 1484, "maxY": 796, "bold": false},
|
||||
{"char": 73, "minX": 1484, "minY": 700, "maxX": 1507, "maxY": 796, "bold": false},
|
||||
{"char": 91, "minX": 1507, "minY": 700, "maxX": 1529, "maxY": 796, "bold": false},
|
||||
{"char": 93, "minX": 1529, "minY": 700, "maxX": 1551, "maxY": 796, "bold": false},
|
||||
{"char": 46, "minX": 1551, "minY": 700, "maxX": 1573, "maxY": 796, "bold": false},
|
||||
{"char": 237, "minX": 1573, "minY": 700, "maxX": 1594, "maxY": 796, "bold": false},
|
||||
{"char": 184, "minX": 1594, "minY": 700, "maxX": 1615, "maxY": 796, "bold": false},
|
||||
{"char": 161, "minX": 1615, "minY": 700, "maxX": 1636, "maxY": 796, "bold": false},
|
||||
{"char": 58, "minX": 1636, "minY": 700, "maxX": 1657, "maxY": 796, "bold": false},
|
||||
{"char": 33, "minX": 1657, "minY": 700, "maxX": 1678, "maxY": 796, "bold": false},
|
||||
{"char": 236, "minX": 1678, "minY": 700, "maxX": 1698, "maxY": 796, "bold": false},
|
||||
{"char": 204, "minX": 1698, "minY": 700, "maxX": 1718, "maxY": 796, "bold": false},
|
||||
{"char": 160, "minX": 1718, "minY": 700, "maxX": 1738, "maxY": 796, "bold": false},
|
||||
{"char": 166, "minX": 1738, "minY": 700, "maxX": 1758, "maxY": 796, "bold": false},
|
||||
{"char": 124, "minX": 1758, "minY": 700, "maxX": 1778, "maxY": 796, "bold": false},
|
||||
{"char": 105, "minX": 1778, "minY": 700, "maxX": 1798, "maxY": 796, "bold": false},
|
||||
{"char": 108, "minX": 1798, "minY": 700, "maxX": 1818, "maxY": 796, "bold": false},
|
||||
{"char": 32, "minX": 1818, "minY": 700, "maxX": 1838, "maxY": 796, "bold": false},
|
||||
{"char": 59, "minX": 1838, "minY": 700, "maxX": 1857, "maxY": 796, "bold": false},
|
||||
{"char": 44, "minX": 1857, "minY": 700, "maxX": 1875, "maxY": 796, "bold": false},
|
||||
{"char": 39, "minX": 1875, "minY": 700, "maxX": 1889, "maxY": 796, "bold": false},
|
||||
{"char": 236, "minX": 0, "minY": 800, "maxX": 26, "maxY": 900, "bold": true},
|
||||
{"char": 204, "minX": 26, "minY": 800, "maxX": 52, "maxY": 900, "bold": true},
|
||||
{"char": 205, "minX": 52, "minY": 800, "maxX": 78, "maxY": 900, "bold": true},
|
||||
{"char": 183, "minX": 78, "minY": 800, "maxX": 104, "maxY": 900, "bold": true},
|
||||
{"char": 96, "minX": 104, "minY": 800, "maxX": 130, "maxY": 900, "bold": true},
|
||||
{"char": 73, "minX": 130, "minY": 800, "maxX": 156, "maxY": 900, "bold": true},
|
||||
{"char": 91, "minX": 156, "minY": 800, "maxX": 181, "maxY": 900, "bold": true},
|
||||
{"char": 93, "minX": 181, "minY": 800, "maxX": 206, "maxY": 900, "bold": true},
|
||||
{"char": 46, "minX": 206, "minY": 800, "maxX": 231, "maxY": 900, "bold": true},
|
||||
{"char": 237, "minX": 231, "minY": 800, "maxX": 255, "maxY": 900, "bold": true},
|
||||
{"char": 184, "minX": 255, "minY": 800, "maxX": 279, "maxY": 900, "bold": true},
|
||||
{"char": 161, "minX": 279, "minY": 800, "maxX": 303, "maxY": 900, "bold": true},
|
||||
{"char": 58, "minX": 303, "minY": 800, "maxX": 327, "maxY": 900, "bold": true},
|
||||
{"char": 33, "minX": 327, "minY": 800, "maxX": 351, "maxY": 900, "bold": true},
|
||||
{"char": 160, "minX": 351, "minY": 800, "maxX": 374, "maxY": 900, "bold": true},
|
||||
{"char": 166, "minX": 374, "minY": 800, "maxX": 397, "maxY": 900, "bold": true},
|
||||
{"char": 124, "minX": 397, "minY": 800, "maxX": 420, "maxY": 900, "bold": true},
|
||||
{"char": 105, "minX": 420, "minY": 800, "maxX": 443, "maxY": 900, "bold": true},
|
||||
{"char": 108, "minX": 443, "minY": 800, "maxX": 466, "maxY": 900, "bold": true},
|
||||
{"char": 32, "minX": 466, "minY": 800, "maxX": 489, "maxY": 900, "bold": true},
|
||||
{"char": 106, "minX": 489, "minY": 800, "maxX": 511, "maxY": 900, "bold": true},
|
||||
{"char": 59, "minX": 511, "minY": 800, "maxX": 533, "maxY": 900, "bold": true},
|
||||
{"char": 44, "minX": 533, "minY": 800, "maxX": 554, "maxY": 900, "bold": true},
|
||||
{"char": 39, "minX": 554, "minY": 800, "maxX": 571, "maxY": 900, "bold": true},
|
||||
{"char": 0, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": false},
|
||||
{"char": 2, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": false},
|
||||
{"char": 9, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": false},
|
||||
{"char": 10, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": false},
|
||||
{"char": 13, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": false},
|
||||
{"char": 0, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": true},
|
||||
{"char": 2, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": true},
|
||||
{"char": 9, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": true},
|
||||
{"char": 10, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": true},
|
||||
{"char": 13, "minX": 0, "minY": 0, "maxX": 0, "maxY": 0, "bold": true}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 186 KiB |
Loading…
Reference in New Issue