#include "Atlas.h" #include "BitmapRef.hpp" #include "GlyphBox.h" #include "conversion.h" #include "edge-coloring.h" #include "import-font.h" #include "ofFileUtils.h" #include "ofTrueTypeFont.h" #include #include namespace ofxMsdfgen { Atlas::Atlas(){ } Atlas::~Atlas(){ } void Atlas::setup(string _fontPath){ fontPath = _fontPath; if(generate()){ ofLogNotice("Atlas::setup()") << "generated Atlas"; }else{ ofLogError("Atlas::setup()") << "whoops, could not generate Atlas"; } } void Atlas::setup(string _fontPath, AtlasSettings _settings){ settings = _settings; setup(_fontPath); } bool Atlas::generate(){ bool success = false; //{ msdfgen::FreetypeHandle * ft = msdfgen::initializeFreetype(); if(ft){ const char * fontPath_c_str = fontPath.c_str(); msdfgen::FontHandle * font = loadFont(ft, fontPath_c_str); if(font){ // Storage for glyph geometry and their coordinates in the atlas std::vector 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. if(settings.characters == "charset::ascii"){ fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII); }else if(settings.characters == ""){ msdfgen::GlyphIndex glyphIndex; }else{ msdf_atlas::Charset charset; for(const unsigned char c : settings.characters){ msdf_atlas::unicode_t ut(c); cout << "add char(" << c << " " << ofToString(ut) << ")" << endl; charset.add(ut); cout << "charset.size: " << charset.size() << endl; } fontGeometry.loadCharset(font, 1.0, charset); if(glyphs.size() != settings.characters.length()){ fontGeometry.getGlyphs().empty(); fontGeometry.loadCharset(font, 1.0, // fontScale charset, // charset false, // preprocess geometry true); // kerning } } // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies. for(msdf_atlas::GlyphGeometry & glyph : glyphs){ //FIXME: we do not need to inverse y axis, something else is wrong // msdfgen::Shape & shape = const_cast (glyph.getShape()); // shape.inverseYAxis = true; glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, // strategy settings.maxCornerAngle, // angleThreshold 0); // seed } // 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); packer.setScale(settings.scale); // 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 // 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 bitmap(generator.atlasStorage()); toOfImage(bitmap, atlasImage); atlasImage.update(); std::vector layout = generator.getLayout(); int i = 0; for(const msdf_atlas::GlyphBox & gb : layout){ msdf_atlas::GlyphGeometry gg = glyphs.data()[i]; i++; glyphGeometries.push_back(gg); } // Cleanup msdfgen::destroyFont(font); success = true; // FIXME: always turns true, why do we have this } msdfgen::deinitializeFreetype(ft); } return success; } const ofImage & Atlas::getAtlasImage(){ return atlasImage; } const vector & Atlas::getGlyphGeometries(){ return glyphGeometries; } const GlyphGeometry & Atlas::getGlyphGeometry(unsigned char character){ for(const GlyphGeometry & gg : glyphGeometries){ if(gg.getCodepoint() == static_cast (character)){ return gg; } } // not found! ofLogError("Atlas::getGlyphGeometry") << "glyph(" << character << ") not found!" << endl << "returning first glyph. this is bad." << endl; // FIXME: proper error handling return glyphGeometries[0]; } }