cmake_minimum_required(VERSION 3.7)

#
# Will "bake" fonts into a target by feeding the output of the fontrasterizer utility
# to gpcbin2c and adding the resulting files to the target.
# This will make the pre-rasterized fonts available in the form of constant, fixed-size
# C arrays of unsigned char, which can be deserialized by feeding them to the
# cppgui::fonts::load() function.
#
# Fixed parameters:
#
#   <target>                the target into which to "bake" the font
#   <font_file>             a font file in a format that FreeType can work with
#
# Keyword-introduced parameters:
#
#   SIZES size1 .. sizeN    MANDATORY: pixel sizes at which to rasterize the font
#   ALL                     tells fontrasterizer to rasterize all available code points
#   CODEPOINTS cp1 .. cpN   list of the code points to rasterize
#
# Either ALL or CODEPOINTS ... must be used, otherwise baking will either fail or result in
# empty or invalid data arrays.
#
# The names and paths of the generated source files can be considered implementation details.
# To access a constant data array, include the corresponding header with a statement like
# this one:
#
#   #include <MyFont-Regular-16.h>
#
# The data arrays will have the following signature:
#
#   unsigned char <identifier>_<size>[<bytecount>]
#
# where <identifier> is obtain by converting the font file name to all lowercase and
# replacing dashes with underscores. For the example above, the declaration would be 
# something like:
#
#   unsigned char myfont_regular_16[12424];
#
# Note that the declaration includes the size of the array, which is a requirement foreach
# reliable deserialization.
#

# TODO: option to make constant arrays private

function(target_bake_font target font_file)

    # Extract filename components
    get_filename_component(filename ${font_file} NAME_WE)
    get_filename_component(ext      ${font_file} EXT    )

    # Convert filename to ID (lowercase, underscores instead of dashes)
    string(TOLOWER ${filename} font_id)
    string(REPLACE "-" "_" font_id ${font_id})

    # TODO: support ranges (as soon as fontrasterizer properly supports them)
    cmake_parse_arguments(PARSE_ARGV 1 "" "ALL" "" "SIZES;CODEPOINTS")

    foreach(size ${_SIZES})

        set(args)
        if (_ALL)
            set(args ${args} "range=all")
        endif()
        if (_CODEPOINTS)
            foreach(cp ${_CODEPOINTS})
                set(args ${args} "cp=${cp}")
            endforeach()
        endif()
        #message("args: ${args}")

        set(raster_file "${CMAKE_CURRENT_BINARY_DIR}/generated/rastfont/${filename}-${size}.rastfont")

        add_custom_command(
            OUTPUT ${raster_file}
            DEPENDS ${font_file}
            COMMAND fontrasterizer ARGS
                input=${font_file}
                size=${size}
                output="${raster_file}"
                ${args}
        )

        set(header_file "${CMAKE_CURRENT_BINARY_DIR}/generated/headers/${filename}-${size}.h")
        set(source_file "${CMAKE_CURRENT_BINARY_DIR}/generated/sources/${filename}-${size}.c")

        add_custom_command(
            OUTPUT ${header_file}
            OUTPUT ${source_file}
            DEPENDS ${raster_file}
            # TODO: use "bin2c" instead of "gpcbin2c"
            COMMAND gpcbin2c ARGS
                -i ${raster_file}
                -c ${font_id}_${size}
                -h ${header_file}
                -s ${source_file}
        )

        target_sources(${target} PRIVATE ${source_file})

    endforeach()

    # TODO: parameter to make this PRIVATE instead of PUBLIC ?
    target_include_directories(${target} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/generated/headers")
    
endfunction()









#----------------------------------------------------------
# ARCHIVED CODE

if (0)

    # Reference all sizes of a given font from a single header file
    # TODO: derive filename from font_file variable
    file(WRITE ${GENERATED_HEADERS_DIR}/liberationsans_font.h "// liberationsans_font.h  - generated by CMake, DO NOT MODIFY\n")

    file(APPEND ${GENERATED_HEADERS_DIR}/liberationsans_font.h
    "template<std::size_t Size> struct ${font_name_as_id} { static constexpr auto get() -> std::pair<const uint8_t *, std::size_t> { return {nullptr, 0}; } };\n\n")

    file(APPEND ${GENERATED_HEADERS_DIR}/liberationsans_font.h "extern \"C\" {\n")
    
    #...
    
    file(APPEND ${GENERATED_HEADERS_DIR}/liberationsans_font.h "#include \"${font_file}-${size}.h\"\n")
    file(APPEND ${GENERATED_HEADERS_DIR}/liberationsans_font.h "}\n")

    list(APPEND FONT_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/generated/headers/${font_file}-${size}.h)
    list(APPEND FONT_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/generated/sources/${font_file}-${size}.c)

    # Generate a struct that gives compile-time access to specific sizes
    
    file(APPEND ${GENERATED_HEADERS_DIR}/liberationsans_font.h "
template<> struct ${font_name_as_id}<${size}> {
    static constexpr auto get() -> std::pair<const uint8_t *, std::size_t> {
        return { ${font_name_as_id}_${size}, sizeof(${font_name_as_id}_${size}) };
    }
};

")

endif(0) # ARCHIVE