LWJGL / STB: несоответствие при работе в IntelliJ и при работе через консоль - PullRequest
0 голосов
/ 30 июня 2019

У меня проблема при использовании LWJGL и STB TrueType в IntelliJ.

Когда я сейчас пытаюсь создать растровое изображение и поместить все в Main (' Code 1 ' ниже), все работает нормально.
Как только я пытаюсь разделить это и , создайте контекст OpenGL (Если я разделю это без создания контекста OpenGL, то это тоже хорошо работает) , загруженный шрифт как-то повреждается и либо программа аварийно завершает работу с ACCESS_VIOLATION, либо запускается без создания растрового изображения. Вы можете увидеть неработающий код как « Код 2 » ниже.

Неправильное поведение, однако, возникает только при запуске с аргументами java run, которые IntelliJ использует - либо через Intellij Run, либо через Console.
Это не происходит, не происходит при сборке в JAR и запуске этого.

Проблемный аргумент заключается в следующем. Если этот файл отсутствует в консоли, он запускается.

-javaagent: \ Lib \ idea_rt.jar = 52850 \ Bin

Я прочитал здесь , что файл idea_rt.jar "необходим для обеспечения изящных функций завершения работы / выхода / stacktrace", и поэтому я не хочу отключать его в IntelliJ.


ПРИМЕЧАНИЕ: В неработающем коде («Код 2» ниже) вы увидите «ненужную» строку
ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");, который имитирует загрузку нескольких шрифтов. Если я загружаю только один шрифт, все работает нормально.
Вы также заметите создание контекста OpenGL в коде 2, что также является причиной проблемы (как я описал выше)


Код 1 (работает)

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;

import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;


public class STBTTExampleOnlyMain {
    private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
        try(InputStream stream = STBTTExampleOnlyMain .class.getResourceAsStream(resource)) {
            byte[] bytes = stream.readAllBytes();

            ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
            buffer.put(bytes);
            buffer.flip();

            return buffer;
        }
    }

    public static void main(String[] args) throws IOException {
        ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
        ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");

        STBTTFontinfo font = STBTTFontinfo.create();
        stbtt_InitFont(font, data);

        IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
        IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
        ByteBuffer bitmap = stbtt_GetCodepointBitmap(font, 0, 1, 'a', bufWidth, bufHeight, null, null);

        System.out.println(bitmap);
    }
}


Код 2 (не работает)

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL;
import org.lwjgl.stb.STBTTFontinfo;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;

import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.stb.STBTruetype.stbtt_GetCodepointBitmap;
import static org.lwjgl.stb.STBTruetype.stbtt_InitFont;


public class STBTTExample {
    private static final Map<Integer, STBTTFontinfo> fontMap = new HashMap<>();

    private static ByteBuffer loadByteBufferFromResource(String resource) throws IOException {
        try(InputStream stream = STBTTExample.class.getResourceAsStream(resource)) {
            byte[] bytes = stream.readAllBytes();

            ByteBuffer buffer = BufferUtils.createByteBuffer(bytes.length);
            buffer.put(bytes);
            buffer.flip();

            return buffer;
        }
    }

    private static void initFont() throws IOException {
        ByteBuffer data = loadByteBufferFromResource("/fonts/arial.ttf");
        ByteBuffer data2 = loadByteBufferFromResource("/fonts/arial.ttf");

        STBTTFontinfo font = STBTTFontinfo.create();
        stbtt_InitFont(font, data);

        fontMap.put(0, font);
    }

    public static void main(String[] args) throws IOException {
        initFont();

        glfwInit();
        glfwDefaultWindowHints();
        long windowHandle = glfwCreateWindow(800, 600, "Test", 0, 0);
        glfwMakeContextCurrent(windowHandle);
        GL.createCapabilities();

        IntBuffer bufWidth = BufferUtils.createIntBuffer(1);
        IntBuffer bufHeight = BufferUtils.createIntBuffer(1);
        ByteBuffer bitmap = stbtt_GetCodepointBitmap(fontMap.get(0), 0, 1, 'a', bufWidth, bufHeight, null, null);

        System.out.println(bitmap);
    }
}


Как можно решить проблему невозможности запуска программы из IntelliJ при работе с визуализацией текста?

Возможно, я неправильно понимаю библиотеку STBTT и на самом деле не могу работать со шрифтами таким образом?

Любая помощь будет признательна, чтобы понять, что не так и исправить это.

1 Ответ

0 голосов
/ 02 июля 2019

Я задал вопрос на форуме LWJGL и получил его решение.

Объект STBTTFontinfo содержит только метаданные. Фактические данные шрифта НЕ копируются из ByteBuffer, который вы передаете в stbtt_InitFont. Только его адрес памяти копируется, и данные шрифта доступны через этот указатель при необходимости. Сегфоут, который вы видите, происходит потому, что вы нигде не храните ссылку на ByteBuffer, он GCed / освобождается к моменту, когда вы пытаетесь использовать шрифт. Легким решением было бы изменить класс Font, чтобы он также сохранял ByteBuffer.

Вы можете посмотреть пост здесь .

...