org.terasology.rendering.assets.font.FontMeshBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.terasology.rendering.assets.font.FontMeshBuilder.java

Source

/*
 * Copyright 2014 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.terasology.rendering.assets.font;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;

import javax.vecmath.Vector3f;

import org.terasology.rendering.FontColor;
import org.terasology.rendering.assets.material.Material;
import org.terasology.rendering.assets.mesh.Mesh;
import org.terasology.rendering.assets.mesh.MeshBuilder;
import org.terasology.rendering.nui.Color;
import org.terasology.rendering.nui.HorizontalAlign;

import com.google.common.collect.Maps;

/**
 * @author Immortius
 */
public class FontMeshBuilder {

    private static final float SHADOW_DEPTH = -1;

    private Font font;
    private Color defaultColor;

    public FontMeshBuilder(Font font) {
        this.font = font;
    }

    public Map<Material, Mesh> createTextMesh(List<String> lines, int width, HorizontalAlign alignment,
            Color baseColor, Color shadowColor) {
        this.defaultColor = baseColor;
        Map<Material, MeshBuilder> meshBuilders = Maps.newLinkedHashMap();
        addLinesToMesh(lines, meshBuilders, width, alignment, shadowColor);

        Map<Material, Mesh> result = Maps.newLinkedHashMap();
        for (Map.Entry<Material, MeshBuilder> entry : meshBuilders.entrySet()) {
            result.put(entry.getKey(), entry.getValue().build());
        }
        return result;
    }

    private void addLinesToMesh(List<String> lines, Map<Material, MeshBuilder> meshBuilders, int maxWidth,
            HorizontalAlign alignment, Color shadowColor) {
        int y = 0;
        Deque<Color> prevColors = new ArrayDeque<>();
        Color currentColor = defaultColor;

        for (String line : lines) {
            int w = font.getWidth(line);
            int x = alignment.getOffset(w, maxWidth);
            for (char c : line.toCharArray()) {
                FontCharacter character = font.getCharacterData(c);
                if (character != null && character.getPage() != null) {
                    MeshBuilder builder = meshBuilders.get(character.getPageMat());
                    if (builder == null) {
                        builder = new MeshBuilder();
                        meshBuilders.put(character.getPageMat(), builder);
                    }

                    if (shadowColor.a() != 0) {
                        addCharacter(builder, character, x, y, shadowColor, 1, 1, SHADOW_DEPTH);
                    }
                    addCharacter(builder, character, x, y, currentColor, 0, 0, 0);

                    x += character.getxAdvance();
                } else if (FontColor.isValid(c)) {
                    if (c == FontColor.getReset()) {
                        if (!prevColors.isEmpty()) {
                            currentColor = prevColors.removeLast();
                        }
                    } else {
                        prevColors.addLast(currentColor);
                        currentColor = FontColor.toColor(c);
                    }
                }
            }
            y += font.getLineHeight();
        }
    }

    private void addCharacter(MeshBuilder builder, FontCharacter character, int x, int y, Color color,
            float xOffset, float yOffset, float depth) {
        float top = y + character.getyOffset() + yOffset;
        float bottom = top + character.getHeight() + yOffset;
        float left = x + character.getxOffset() + xOffset;
        float right = left + character.getWidth() + xOffset;
        float texTop = character.getY();
        float texBottom = texTop + character.getTexHeight();
        float texLeft = character.getX();
        float texRight = texLeft + character.getTexWidth();

        Vector3f v1 = new Vector3f(left, top, depth);
        Vector3f v2 = new Vector3f(right, top, depth);
        Vector3f v3 = new Vector3f(right, bottom, depth);
        Vector3f v4 = new Vector3f(left, bottom, depth);
        builder.addPoly(v1, v2, v3, v4);
        builder.addColor(color, color, color, color);
        builder.addTexCoord(texLeft, texTop);
        builder.addTexCoord(texRight, texTop);
        builder.addTexCoord(texRight, texBottom);
        builder.addTexCoord(texLeft, texBottom);
    }

}