add Atlas class
This commit is contained in:
parent
bb60924822
commit
e73f97b326
6 changed files with 275 additions and 29 deletions
87
src/Atlas.cpp
Normal file
87
src/Atlas.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include "Atlas.h"
|
||||||
|
#include "BitmapRef.hpp"
|
||||||
|
|
||||||
|
void ofxMsdfgen::Atlas::setup(string _fontPath){
|
||||||
|
fontPath = _fontPath;
|
||||||
|
if(generate()){
|
||||||
|
ofLogNotice("ofxMsdfgen::Atlas::setup()") << "generated Atlas";
|
||||||
|
}else{
|
||||||
|
ofLogError("ofxMsdfgen::Atlas::setup()") << "whoops, could not generate Atlas";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ofxMsdfgen::Atlas::setup(string _fontPath,
|
||||||
|
AtlasSettings _settings){
|
||||||
|
settings = _settings;
|
||||||
|
setup(_fontPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ofxMsdfgen::Atlas::generate(){
|
||||||
|
bool success = false;
|
||||||
|
// Initialize instance of FreeType library
|
||||||
|
if(msdfgen::FreetypeHandle * ft = msdfgen::initializeFreetype()){
|
||||||
|
// Load font file
|
||||||
|
if(msdfgen::FontHandle * font = msdfgen::loadFont(ft, fontPath.c_str())){
|
||||||
|
// Storage for glyph geometry and their coordinates in the atlas
|
||||||
|
std::vector <msdf_atlas::GlyphGeometry> glyphs;
|
||||||
|
// FontGeometry is a helper class that loads a set of glyphs from a single font.
|
||||||
|
// It can also be used to get additional font metrics, kerning information, etc.
|
||||||
|
msdf_atlas::FontGeometry fontGeometry(&glyphs);
|
||||||
|
// Load a set of character glyphs:
|
||||||
|
// The second argument can be ignored unless you mix different font sizes in one atlas.
|
||||||
|
// In the last argument, you can specify a charset other than ASCII.
|
||||||
|
// To load specific glyph indices, use loadGlyphs instead.
|
||||||
|
fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII);
|
||||||
|
// Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies.
|
||||||
|
for(msdf_atlas::GlyphGeometry & glyph : glyphs){
|
||||||
|
glyph.edgeColoring(&msdfgen::edgeColoringInkTrap,
|
||||||
|
settings.maxCornerAngle,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
// TightAtlasPacker class computes the layout of the atlas.
|
||||||
|
msdf_atlas::TightAtlasPacker packer;
|
||||||
|
// Set atlas parameters:
|
||||||
|
// setDimensions or setDimensionsConstraint to find the best value
|
||||||
|
packer.setDimensionsConstraint(msdf_atlas::TightAtlasPacker::DimensionsConstraint::SQUARE);
|
||||||
|
// setScale for a fixed size or setMinimumScale to use the largest that fits
|
||||||
|
packer.setMinimumScale(settings.minimumScale);
|
||||||
|
// setPixelRange or setUnitRange
|
||||||
|
packer.setPixelRange(settings.pixelRange);
|
||||||
|
packer.setMiterLimit(settings.miterLimit);
|
||||||
|
// Compute atlas layout - pack glyphs
|
||||||
|
packer.pack(glyphs.data(), glyphs.size());
|
||||||
|
// Get final atlas dimensions
|
||||||
|
int width = 0, height = 0;
|
||||||
|
packer.getDimensions(width, height);
|
||||||
|
// The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap.
|
||||||
|
msdf_atlas::ImmediateAtlasGenerator <
|
||||||
|
float, // pixel type of buffer for individual glyphs depends on generator function
|
||||||
|
3, // number of atlas color channels
|
||||||
|
& msdf_atlas::msdfGenerator, // function to generate bitmaps for individual glyphs
|
||||||
|
msdf_atlas::BitmapAtlasStorage <float, 3> // class that stores the atlas bitmap
|
||||||
|
// For example, a custom atlas storage class that stores it in VRAM can be used.
|
||||||
|
> generator(width, height);
|
||||||
|
// GeneratorAttributes can be modified to change the generator's default settings.
|
||||||
|
msdf_atlas::GeneratorAttributes attributes;
|
||||||
|
generator.setAttributes(attributes);
|
||||||
|
generator.setThreadCount(settings.threadCount);
|
||||||
|
// Generate atlas bitmap
|
||||||
|
generator.generate(glyphs.data(), glyphs.size());
|
||||||
|
// The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef.
|
||||||
|
// The glyphs array (or fontGeometry) contains positioning data for typesetting text.
|
||||||
|
msdfgen::Bitmap <float, 3> bitmap(generator.atlasStorage());
|
||||||
|
ofxMsdfgen::toOfImage(bitmap, atlasImage);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
msdfgen::destroyFont(font);
|
||||||
|
|
||||||
|
success = true; // FIXME: always turns true, why do we have this
|
||||||
|
}
|
||||||
|
msdfgen::deinitializeFreetype(ft);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ofImage & ofxMsdfgen::Atlas::getAtlasImage(){
|
||||||
|
return atlasImage;
|
||||||
|
}
|
26
src/Atlas.h
Normal file
26
src/Atlas.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ofMain.h"
|
||||||
|
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||||
|
#include "conversion.h"
|
||||||
|
|
||||||
|
namespace ofxMsdfgen {
|
||||||
|
struct AtlasSettings {
|
||||||
|
float maxCornerAngle = 3.0;
|
||||||
|
float minimumScale = 24.0;
|
||||||
|
float pixelRange = 2.0;
|
||||||
|
float miterLimit = 1.0;
|
||||||
|
int threadCount = 4;
|
||||||
|
};
|
||||||
|
class Atlas {
|
||||||
|
public:
|
||||||
|
void setup(string _fontPath);
|
||||||
|
void setup(string _fontPath, AtlasSettings _settings);
|
||||||
|
bool generate();
|
||||||
|
const ofImage & getAtlasImage();
|
||||||
|
AtlasSettings settings;
|
||||||
|
private:
|
||||||
|
string fontPath;
|
||||||
|
ofImage atlasImage;
|
||||||
|
};
|
||||||
|
}
|
60
src/conversion.cpp
Normal file
60
src/conversion.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include "conversion.h"
|
||||||
|
|
||||||
|
void ofxMsdfgen::toOfImage(msdfgen::Bitmap <float, 3> bitmap,
|
||||||
|
ofFloatImage & image){
|
||||||
|
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
||||||
|
memcpy(image.getPixels().getData(), static_cast <float *>(bitmap), bitmap.width() * bitmap.height() * 3 * sizeof(float));
|
||||||
|
image.update(); // float is slow here
|
||||||
|
}
|
||||||
|
|
||||||
|
void ofxMsdfgen::toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
||||||
|
ofImage & image){
|
||||||
|
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
||||||
|
ofPixels & pixels = image.getPixels();
|
||||||
|
int w = bitmap.width();
|
||||||
|
int h = bitmap.height();
|
||||||
|
for(int y = 0; y < h; y++){
|
||||||
|
for(int x = 0; x < w; x++){
|
||||||
|
const float * rgb = bitmap(x, y);
|
||||||
|
int index = 3 * (x + y * w);
|
||||||
|
pixels.getData()[index] = (unsigned char)std::clamp(rgb[0] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
pixels.getData()[index + 1] = (unsigned char)std::clamp(rgb[1] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
pixels.getData()[index + 2] = (unsigned char)std::clamp(rgb[2] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ofxMsdfgen::toOfImage(const msdfgen::Bitmap <byte, 3> bitmap,
|
||||||
|
ofImage & image){
|
||||||
|
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
||||||
|
memcpy(image.getPixels().getData(), bitmap.getPixels(), bitmap.width() * bitmap.height() * 3 * sizeof(byte));
|
||||||
|
|
||||||
|
image.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
ofImage ofxMsdfgen::toOfImage(const msdfgen::Bitmap <float, 3> bitmap){
|
||||||
|
ofImage image;
|
||||||
|
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
||||||
|
ofPixels & pixels = image.getPixels();
|
||||||
|
int w = bitmap.width();
|
||||||
|
int h = bitmap.height();
|
||||||
|
for(int y = 0; y < h; y++){
|
||||||
|
for(int x = 0; x < w; x++){
|
||||||
|
const float * rgb = bitmap(x, y);
|
||||||
|
int index = 3 * (x + y * w);
|
||||||
|
pixels.getData()[index] = (unsigned char)std::clamp(rgb[0] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
pixels.getData()[index + 1] = (unsigned char)std::clamp(rgb[1] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
pixels.getData()[index + 2] = (unsigned char)std::clamp(rgb[2] * 256.0,
|
||||||
|
0.0, 255.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image.update();
|
||||||
|
return image;
|
||||||
|
}
|
16
src/conversion.h
Normal file
16
src/conversion.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ofMain.h"
|
||||||
|
#include "BitmapAtlasStorage.h"
|
||||||
|
#include "GlyphGeometry.h"
|
||||||
|
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||||
|
|
||||||
|
namespace ofxMsdfgen {
|
||||||
|
void toOfImage(msdfgen::Bitmap <float, 3> bitmap,
|
||||||
|
ofFloatImage & image);
|
||||||
|
void toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
||||||
|
ofImage & image);
|
||||||
|
void toOfImage(const msdfgen::Bitmap <byte, 3> bitmap,
|
||||||
|
ofImage & image);
|
||||||
|
ofImage toOfImage(const msdfgen::Bitmap <float, 3>);
|
||||||
|
}
|
|
@ -1,31 +1,80 @@
|
||||||
#include "ofxMsdfgen.h"
|
#include "ofxMsdfgen.h"
|
||||||
|
#include "BitmapRef.hpp"
|
||||||
|
#include "ofGraphicsConstants.h"
|
||||||
#include "ofPixels.h"
|
#include "ofPixels.h"
|
||||||
|
|
||||||
void ofxMsdfgen::toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
bool ofxMsdfgen::generateAtlas(const char * fontFilename){
|
||||||
ofFloatImage & image){
|
bool success = false;
|
||||||
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
// Initialize instance of FreeType library
|
||||||
memcpy(image.getPixels().getData(), bitmap.getPixels(), bitmap.width() * bitmap.height() * 3 * sizeof(float));
|
if(msdfgen::FreetypeHandle * ft = msdfgen::initializeFreetype()){
|
||||||
image.update(); // float is slow here
|
// Load font file
|
||||||
|
if(msdfgen::FontHandle * font = msdfgen::loadFont(ft, fontFilename)){
|
||||||
|
// Storage for glyph geometry and their coordinates in the atlas
|
||||||
|
std::vector <msdf_atlas::GlyphGeometry> glyphs;
|
||||||
|
// FontGeometry is a helper class that loads a set of glyphs from a single font.
|
||||||
|
// It can also be used to get additional font metrics, kerning information, etc.
|
||||||
|
msdf_atlas::FontGeometry fontGeometry(&glyphs);
|
||||||
|
// Load a set of character glyphs:
|
||||||
|
// The second argument can be ignored unless you mix different font sizes in one atlas.
|
||||||
|
// In the last argument, you can specify a charset other than ASCII.
|
||||||
|
// To load specific glyph indices, use loadGlyphs instead.
|
||||||
|
fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII);
|
||||||
|
// Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies.
|
||||||
|
const double maxCornerAngle = 3.0;
|
||||||
|
for(msdf_atlas::GlyphGeometry & glyph : glyphs){
|
||||||
|
glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0);
|
||||||
|
}
|
||||||
|
// TightAtlasPacker class computes the layout of the atlas.
|
||||||
|
msdf_atlas::TightAtlasPacker packer;
|
||||||
|
// Set atlas parameters:
|
||||||
|
// setDimensions or setDimensionsConstraint to find the best value
|
||||||
|
packer.setDimensionsConstraint(msdf_atlas::TightAtlasPacker::DimensionsConstraint::SQUARE);
|
||||||
|
// setScale for a fixed size or setMinimumScale to use the largest that fits
|
||||||
|
packer.setMinimumScale(24.0);
|
||||||
|
// setPixelRange or setUnitRange
|
||||||
|
packer.setPixelRange(2.0);
|
||||||
|
packer.setMiterLimit(1.0);
|
||||||
|
// Compute atlas layout - pack glyphs
|
||||||
|
packer.pack(glyphs.data(), glyphs.size());
|
||||||
|
// Get final atlas dimensions
|
||||||
|
int width = 0, height = 0;
|
||||||
|
packer.getDimensions(width, height);
|
||||||
|
// The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap.
|
||||||
|
msdf_atlas::ImmediateAtlasGenerator <
|
||||||
|
float, // pixel type of buffer for individual glyphs depends on generator function
|
||||||
|
3, // number of atlas color channels
|
||||||
|
& msdf_atlas::msdfGenerator, // function to generate bitmaps for individual glyphs
|
||||||
|
msdf_atlas::BitmapAtlasStorage <float, 3> // class that stores the atlas bitmap
|
||||||
|
// For example, a custom atlas storage class that stores it in VRAM can be used.
|
||||||
|
> generator(width, height);
|
||||||
|
// GeneratorAttributes can be modified to change the generator's default settings.
|
||||||
|
msdf_atlas::GeneratorAttributes attributes;
|
||||||
|
generator.setAttributes(attributes);
|
||||||
|
generator.setThreadCount(12);
|
||||||
|
// Generate atlas bitmap
|
||||||
|
generator.generate(glyphs.data(), glyphs.size());
|
||||||
|
// The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef.
|
||||||
|
// The glyphs array (or fontGeometry) contains positioning data for typesetting text.
|
||||||
|
success = submitAtlasBitmapAndLayout((msdfgen::BitmapConstRef <float, 3>)generator.atlasStorage(),
|
||||||
|
glyphs,
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
// Cleanup
|
||||||
|
msdfgen::destroyFont(font);
|
||||||
|
}
|
||||||
|
msdfgen::deinitializeFreetype(ft);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ofxMsdfgen::toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
bool ofxMsdfgen::submitAtlasBitmapAndLayout(const msdfgen::BitmapConstRef <float, 3> & storage,
|
||||||
ofImage & image){
|
const std::vector <msdf_atlas::GlyphGeometry> & glyphs,
|
||||||
image.allocate(bitmap.width(), bitmap.height(), OF_IMAGE_COLOR);
|
const int & width,
|
||||||
ofPixels & pixels = image.getPixels();
|
const int & height){
|
||||||
int w = bitmap.width();
|
const msdfgen::Bitmap <float, 3> bitmap(storage);
|
||||||
int h = bitmap.height();
|
ofImage image;
|
||||||
for(int y = 0; y < h; y++){
|
toOfImage(bitmap, image);
|
||||||
for(int x = 0; x < w; x++){
|
image.save("atlas.png");
|
||||||
const float * rgb = bitmap(x, y);
|
|
||||||
int index = 3 * (x + y * w);
|
|
||||||
pixels.getData()[index] = (unsigned char)std::clamp(rgb[0] * 256.0,
|
|
||||||
0.0, 255.0);
|
|
||||||
pixels.getData()[index + 1] = (unsigned char)std::clamp(rgb[1] * 256.0,
|
|
||||||
0.0, 255.0);
|
|
||||||
pixels.getData()[index + 2] = (unsigned char)std::clamp(rgb[2] * 256.0,
|
|
||||||
0.0, 255.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image.update();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BitmapAtlasStorage.h"
|
||||||
|
#include "GlyphGeometry.h"
|
||||||
#include "ofMain.h"
|
#include "ofMain.h"
|
||||||
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||||
|
#include "Atlas.h"
|
||||||
|
#include "conversion.h"
|
||||||
|
|
||||||
namespace ofxMsdfgen {
|
namespace ofxMsdfgen {
|
||||||
void toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
bool generateAtlas(const char * fontFilename);
|
||||||
ofFloatImage & image);
|
|
||||||
void toOfImage(const msdfgen::Bitmap <float, 3> bitmap,
|
// doesn't really do anything yet
|
||||||
ofImage & image);
|
// just saves the atlas as a png
|
||||||
|
bool submitAtlasBitmapAndLayout(const msdfgen::BitmapConstRef <float, 3> & storage,
|
||||||
|
const std::vector <msdf_atlas::GlyphGeometry> & glyphs,
|
||||||
|
const int & width,
|
||||||
|
const int & height);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue