mirror of https://github.com/Chlumsky/msdfgen.git
Wrap the library into a single header + CPP file pair
This commit is contained in:
parent
ef8070786c
commit
321a7a9732
|
|
@ -0,0 +1,3 @@
|
||||||
|
msdfgen.h
|
||||||
|
msdfgen.cpp
|
||||||
|
build/
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
option(MSDFGEN_USE_VCPKG "Use vcpkg package manager to link project dependencies" ON)
|
||||||
|
option(MSDFGEN_USE_FREETYPE "Build with the FreeType library" ON)
|
||||||
|
|
||||||
|
if(MSDFGEN_USE_VCPKG AND MSDFGEN_USE_FREETYPE)
|
||||||
|
# Make sure that vcpkg toolchain file is set
|
||||||
|
if(NOT CMAKE_TOOLCHAIN_FILE)
|
||||||
|
if(DEFINED ENV{VCPKG_ROOT})
|
||||||
|
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
|
||||||
|
else()
|
||||||
|
message(SEND_ERROR "Vcpkg toolchain not configured. Either set VCPKG_ROOT environment variable or pass -DCMAKE_TOOLCHAIN_FILE=VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake to cmake")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
# Default to statically linked vcpkg triplet on Windows
|
||||||
|
if(WIN32 AND NOT VCPKG_TARGET_TRIPLET AND NOT MSDFGEN_DYNAMIC_RUNTIME)
|
||||||
|
if(CMAKE_GENERATOR_PLATFORM MATCHES "64$" AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
|
||||||
|
set(VCPKG_TARGET_TRIPLET "x64-windows-static")
|
||||||
|
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "32$" OR CMAKE_GENERATOR_PLATFORM STREQUAL "x86")
|
||||||
|
set(VCPKG_TARGET_TRIPLET "x86-windows-static")
|
||||||
|
else()
|
||||||
|
if(CMAKE_GENERATOR_PLATFORM)
|
||||||
|
message(WARNING "Vcpkg triplet not explicitly specified and could not be deduced. Recommend using -DVCPKG_TARGET_TRIPLET=x64-windows-static or similar")
|
||||||
|
else()
|
||||||
|
message(WARNING "Vcpkg triplet not explicitly specified and could not be deduced. Recommend using -A to explicitly select platform (Win32 or x64)")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(msdfgen LANGUAGES CXX)
|
||||||
|
|
||||||
|
if(MAX_WARNING_LEVEL)
|
||||||
|
if (MSVC)
|
||||||
|
add_compile_options(/W4)
|
||||||
|
else()
|
||||||
|
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||||
|
if(MSDFGEN_USE_FREETYPE AND NOT TARGET Freetype::Freetype)
|
||||||
|
find_package(Freetype REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/generate.py")
|
||||||
|
|
||||||
|
add_library(msdfgen "${CMAKE_CURRENT_SOURCE_DIR}/msdfgen.h" "${CMAKE_CURRENT_SOURCE_DIR}/msdfgen.cpp")
|
||||||
|
set_property(TARGET msdfgen PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
target_compile_features(msdfgen PUBLIC cxx_std_11)
|
||||||
|
if(MSDFGEN_USE_FREETYPE)
|
||||||
|
target_compile_definitions(msdfgen PUBLIC MSDFGEN_USE_FREETYPE)
|
||||||
|
target_link_libraries(msdfgen PRIVATE Freetype::Freetype)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(msdfgen-test "${CMAKE_CURRENT_SOURCE_DIR}/test.cpp")
|
||||||
|
set_property(TARGET msdfgen-test PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
target_link_libraries(msdfgen-test PRIVATE msdfgen)
|
||||||
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT msdfgen-test)
|
||||||
|
if(MSDFGEN_USE_FREETYPE)
|
||||||
|
target_link_libraries(msdfgen-test PRIVATE Freetype::Freetype)
|
||||||
|
endif()
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
rootDir = os.path.join(os.path.dirname(__file__), '..')
|
||||||
|
|
||||||
|
sourceList = [
|
||||||
|
'core/arithmetics.hpp',
|
||||||
|
'core/equation-solver.h',
|
||||||
|
'core/equation-solver.cpp',
|
||||||
|
'core/Vector2.h',
|
||||||
|
'core/Vector2.cpp',
|
||||||
|
'core/pixel-conversion.hpp',
|
||||||
|
'core/BitmapRef.hpp',
|
||||||
|
'core/Bitmap.h',
|
||||||
|
'core/Bitmap.hpp',
|
||||||
|
'core/Projection.h',
|
||||||
|
'core/Projection.cpp',
|
||||||
|
'core/SignedDistance.h',
|
||||||
|
'core/SignedDistance.cpp',
|
||||||
|
'core/Scanline.h',
|
||||||
|
'core/Scanline.cpp',
|
||||||
|
'core/EdgeColor.h',
|
||||||
|
'core/edge-segments.h',
|
||||||
|
'core/edge-segments.cpp',
|
||||||
|
'core/EdgeHolder.h',
|
||||||
|
'core/EdgeHolder.cpp',
|
||||||
|
'core/Contour.h',
|
||||||
|
'core/Contour.cpp',
|
||||||
|
'core/Shape.h',
|
||||||
|
'core/Shape.cpp',
|
||||||
|
'core/bitmap-interpolation.hpp',
|
||||||
|
'core/edge-coloring.h',
|
||||||
|
'core/edge-coloring.cpp',
|
||||||
|
'core/edge-selectors.h',
|
||||||
|
'core/edge-selectors.cpp',
|
||||||
|
'core/contour-combiners.h',
|
||||||
|
'core/contour-combiners.cpp',
|
||||||
|
'core/ShapeDistanceFinder.h',
|
||||||
|
'core/ShapeDistanceFinder.hpp',
|
||||||
|
'core/generator-config.h',
|
||||||
|
'core/msdf-error-correction.h',
|
||||||
|
'core/msdf-error-correction.cpp',
|
||||||
|
'core/MSDFErrorCorrection.h',
|
||||||
|
'core/MSDFErrorCorrection.cpp',
|
||||||
|
'core/msdfgen.cpp',
|
||||||
|
'ext/import-font.h',
|
||||||
|
'ext/import-font.cpp',
|
||||||
|
'ext/resolve-shape-geometry.h',
|
||||||
|
'ext/resolve-shape-geometry.cpp',
|
||||||
|
'msdfgen.h'
|
||||||
|
]
|
||||||
|
|
||||||
|
header = """
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef _USE_MATH_DEFINES
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
"""
|
||||||
|
|
||||||
|
source = """
|
||||||
|
#include "msdfgen.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#ifdef MSDFGEN_USE_FREETYPE
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
#ifndef MSDFGEN_DISABLE_VARIABLE_FONTS
|
||||||
|
#include FT_MULTIPLE_MASTERS_H
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(os.path.join(rootDir, 'LICENSE.txt'), 'r') as file:
|
||||||
|
license = file.read()
|
||||||
|
license = '\n'.join([' * '+line for line in license.strip().split('\n')])
|
||||||
|
|
||||||
|
for filename in sourceList:
|
||||||
|
with open(os.path.join(rootDir, *filename.split('/')), 'r') as file:
|
||||||
|
src = file.read()
|
||||||
|
src = '\n'.join([line for line in src.split('\n') if not re.match(r'^\s*#(include\s.*|pragma\s+once)\s*$', line)])
|
||||||
|
if filename.startswith('ext/import-font.'):
|
||||||
|
src = '#ifdef MSDFGEN_USE_FREETYPE\n\n'+src+'\n\n#endif\n\n'
|
||||||
|
if filename.endswith('.h') or filename.endswith('.hpp'):
|
||||||
|
header += '\n\n'+src
|
||||||
|
if filename.endswith('.cpp'):
|
||||||
|
source += '\n\n'+src
|
||||||
|
|
||||||
|
header = '\n'+re.sub(r'\n{3,}', '\n\n', re.sub(r'}\s*namespace\s+msdfgen\s*{', '', re.sub(r'\/\*[^\*].*?\*\/', '', header, flags=re.DOTALL))).strip()+'\n'
|
||||||
|
source = '\n'+re.sub(r'\n{3,}', '\n\n', re.sub(r'}\s*namespace\s+msdfgen\s*{', '', re.sub(r'\/\*[^\*].*?\*\/', '', source, flags=re.DOTALL))).strip()+'\n'
|
||||||
|
|
||||||
|
header = """
|
||||||
|
/*
|
||||||
|
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR
|
||||||
|
* ---------------------------------------------
|
||||||
|
* A utility by Viktor Chlumsky, (c) 2014 - 2023
|
||||||
|
* https://github.com/Chlumsky/msdfgen
|
||||||
|
* Published under the MIT license
|
||||||
|
*
|
||||||
|
* The technique used to generate multi-channel distance fields in this code
|
||||||
|
* was developed by Viktor Chlumsky in 2014 for his master's thesis,
|
||||||
|
* "Shape Decomposition for Multi-Channel Distance Fields". It provides improved
|
||||||
|
* quality of sharp corners in glyphs and other 2D shapes compared to monochrome
|
||||||
|
* distance fields. To reconstruct an image of the shape, apply the median of three
|
||||||
|
* operation on the triplet of sampled signed distance values.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
"""+header
|
||||||
|
|
||||||
|
source = """
|
||||||
|
/*
|
||||||
|
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR
|
||||||
|
* ---------------------------------------------
|
||||||
|
* https://github.com/Chlumsky/msdfgen
|
||||||
|
*
|
||||||
|
"""+license+"""
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
"""+source
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'msdfgen.h'), 'w') as file:
|
||||||
|
file.write(header)
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'msdfgen.cpp'), 'w') as file:
|
||||||
|
file.write(source)
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include "msdfgen.h"
|
||||||
|
|
||||||
|
using namespace msdfgen;
|
||||||
|
|
||||||
|
static bool saveRGBA(const char *filename, const BitmapConstRef<float, 4> &bitmap) {
|
||||||
|
if (FILE *f = fopen(filename, "wb")) {
|
||||||
|
char header[12];
|
||||||
|
header[0] = 'R', header[1] = 'G', header[2] = 'B', header[3] = 'A';
|
||||||
|
header[4] = char(bitmap.width>>24);
|
||||||
|
header[5] = char(bitmap.width>>16);
|
||||||
|
header[6] = char(bitmap.width>>8);
|
||||||
|
header[7] = char(bitmap.width);
|
||||||
|
header[8] = char(bitmap.height>>24);
|
||||||
|
header[9] = char(bitmap.height>>16);
|
||||||
|
header[10] = char(bitmap.height>>8);
|
||||||
|
header[11] = char(bitmap.height);
|
||||||
|
fwrite(header, 1, 12, f);
|
||||||
|
Bitmap<byte, 4> byteBitmap(bitmap.width, bitmap.height);
|
||||||
|
byte *d = (byte *) byteBitmap;
|
||||||
|
for (const float *s = bitmap.pixels, *end = bitmap.pixels+4*bitmap.width*bitmap.height; s < end; ++d, ++s)
|
||||||
|
*d = pixelFloatToByte(*s);
|
||||||
|
fwrite((const byte *) byteBitmap, 1, 4*bitmap.width*bitmap.height, f);
|
||||||
|
fclose(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#ifdef MSDFGEN_USE_FREETYPE
|
||||||
|
bool success = false;
|
||||||
|
if (FreetypeHandle *ft = initializeFreetype()) {
|
||||||
|
if (FontHandle *font = loadFont(ft, "C:\\Windows\\Fonts\\arialbd.ttf")) {
|
||||||
|
Shape shape;
|
||||||
|
if (loadGlyph(shape, font, 'A')) {
|
||||||
|
shape.normalize();
|
||||||
|
edgeColoringByDistance(shape, 3.0);
|
||||||
|
Bitmap<float, 4> msdf(32, 32);
|
||||||
|
generateMTSDF(msdf, shape, 4.0, 1.0, Vector2(4.0, 4.0));
|
||||||
|
success = saveRGBA("output.rgba", msdf);
|
||||||
|
}
|
||||||
|
destroyFont(font);
|
||||||
|
}
|
||||||
|
deinitializeFreetype(ft);
|
||||||
|
}
|
||||||
|
return success ? 0 : 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/master/docs/vcpkg.schema.json",
|
||||||
|
"name": "msdfgen-all-in-one",
|
||||||
|
"version": "1.10.0",
|
||||||
|
"dependencies": [
|
||||||
|
"freetype"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue