<commit_before>#include "onair/okui/PNGTexture.h"

#include <png.h>

namespace onair {
namespace okui {

struct PNGInput {
    PNGInput(const void* data, size_t length) : data(data), length(length) {}

    const void* data;
    size_t length;
    size_t position = 0;
};

static void PNGRead(png_structp png, png_bytep data, png_size_t length) {
    PNGInput* input = reinterpret_cast<PNGInput*>(png_get_io_ptr(png));
    if (length > input->length - input->position) {
        png_error(png, "read error (not enough data)");
    } else {
        memcpy(data, reinterpret_cast<const char*>(input->data) + input->position, length);
        input->position += length;
    }
}

void PNGTexture::setData(std::shared_ptr<const std::string> data) {
    _data = data;
    _cacheEntry = nullptr;
    
    PNGInput input(_data->data(), _data->size());

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    png_infop info = png_create_info_struct(png);

    if (setjmp(png_jmpbuf(png))) {
        ONAIR_LOG_ERROR("error reading png data");
        png_destroy_read_struct(&png, &info, nullptr);
        return;
    }

    png_set_read_fn(png, &input, &PNGRead);

    png_read_info(png, info);

    _width = png_get_image_width(png, info);
    _height = png_get_image_height(png, info);

    png_destroy_read_struct(&png, &info, nullptr);
}

GLuint PNGTexture::load(opengl::TextureCache* textureCache) {
    PNGInput input(_data->data(), _data->size());

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    png_infop info = png_create_info_struct(png);

    if (setjmp(png_jmpbuf(png))) {
        ONAIR_LOG_ERROR("error reading png data");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }

    png_set_read_fn(png, &input, &PNGRead);

    png_read_info(png, info);

    auto colorType = png_get_color_type(png, info);
    auto glFormat =
#if GL_RED && GL_RG
        colorType == PNG_COLOR_TYPE_GRAY ? GL_RED :
        colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? GL_RG :
#else
        colorType == PNG_COLOR_TYPE_GRAY ? GL_LUMINANCE :
        colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? GL_LUMINANCE_ALPHA :
#endif
        colorType == PNG_COLOR_TYPE_RGB ? GL_RGB :
        colorType == PNG_COLOR_TYPE_RGB_ALPHA ? GL_RGBA :
    0;

    if (!glFormat) {
        ONAIR_LOG_ERROR("unsupported color type");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }
    
    int bytesPerRow = png_get_rowbytes(png, info);
    
    int bitDepth = png_get_bit_depth(png, info);
    if (bitDepth != 8 && bitDepth != 16) {
        ONAIR_LOG_ERROR("unsupported bit depth");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }

    const auto components = ((colorType & PNG_COLOR_MASK_COLOR) ? 3 : 1) + ((colorType & PNG_COLOR_MASK_ALPHA) ? 1 : 0);
    if (bytesPerRow != components * (bitDepth >> 3) * _width) {
        assert(false);
        ONAIR_LOG_ERROR("unknown error");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }
    <commit_msg>add info to png error log<commit_after>#include "onair/okui/PNGTexture.h"

#include <png.h>

namespace onair {
namespace okui {

struct PNGInput {
    PNGInput(const void* data, size_t length) : data(data), length(length) {}

    const void* data;
    size_t length;
    size_t position = 0;
};

static void PNGRead(png_structp png, png_bytep data, png_size_t length) {
    PNGInput* input = reinterpret_cast<PNGInput*>(png_get_io_ptr(png));
    if (length > input->length - input->position) {
        png_error(png, "read error (not enough data)");
    } else {
        memcpy(data, reinterpret_cast<const char*>(input->data) + input->position, length);
        input->position += length;
    }
}

void PNGTexture::setData(std::shared_ptr<const std::string> data) {
    _data = data;
    _cacheEntry = nullptr;
    
    PNGInput input(_data->data(), _data->size());

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    png_infop info = png_create_info_struct(png);

    if (setjmp(png_jmpbuf(png))) {
        ONAIR_LOG_ERROR("error reading png data");
        png_destroy_read_struct(&png, &info, nullptr);
        return;
    }

    png_set_read_fn(png, &input, &PNGRead);

    png_read_info(png, info);

    _width = png_get_image_width(png, info);
    _height = png_get_image_height(png, info);

    png_destroy_read_struct(&png, &info, nullptr);
}

GLuint PNGTexture::load(opengl::TextureCache* textureCache) {
    PNGInput input(_data->data(), _data->size());

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
    png_infop info = png_create_info_struct(png);

    if (setjmp(png_jmpbuf(png))) {
        ONAIR_LOG_ERROR("error reading png data");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }

    png_set_read_fn(png, &input, &PNGRead);

    png_read_info(png, info);

    auto colorType = png_get_color_type(png, info);
    auto glFormat =
#if GL_RED && GL_RG
        colorType == PNG_COLOR_TYPE_GRAY ? GL_RED :
        colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? GL_RG :
#else
        colorType == PNG_COLOR_TYPE_GRAY ? GL_LUMINANCE :
        colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? GL_LUMINANCE_ALPHA :
#endif
        colorType == PNG_COLOR_TYPE_RGB ? GL_RGB :
        colorType == PNG_COLOR_TYPE_RGB_ALPHA ? GL_RGBA :
    0;

    if (!glFormat) {
        ONAIR_LOG_ERROR("unsupported color type (%d)", static_cast<int>(colorType));
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }
    
    int bytesPerRow = png_get_rowbytes(png, info);
    
    int bitDepth = png_get_bit_depth(png, info);
    if (bitDepth != 8 && bitDepth != 16) {
        ONAIR_LOG_ERROR("unsupported bit depth");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }

    const auto components = ((colorType & PNG_COLOR_MASK_COLOR) ? 3 : 1) + ((colorType & PNG_COLOR_MASK_ALPHA) ? 1 : 0);
    if (bytesPerRow != components * (bitDepth >> 3) * _width) {
        assert(false);
        ONAIR_LOG_ERROR("unknown error");
        png_destroy_read_struct(&png, &info, nullptr);
        return 0;
    }
    
{'fraction_non_alphanumeric': 0.12034383954154727, 'fraction_numerical': 0.004457179242279528, 'mean_word_length': 3.456028368794326, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6114662', 'n_tokens_mistral': 2314, 'n_tokens_neox': 2154, 'n_words': 437}