| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- #include "ResFontFT.h"
- #include "oxygine/res/Resources.h"
- #include "oxygine/Font.h"
- #include "oxygine/res/CreateResourceContext.h"
- #include "oxygine/core/NativeTexture.h"
- #include "oxygine/Image.h"
- #include "oxygine/core/ImageDataOperations.h"
- #include "oxygine/core/VideoDriver.h"
- #include "ft2build.h"
- #include FT_FREETYPE_H
- #ifdef _MSC_VER
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int32 uint32_t;
- #else
- #include <stdint.h>
- #endif
- #define ASCII_IN_TABLE 1
- static const uint8_t utf8d[] =
- {
- #if ASCII_IN_TABLE
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- #endif
- 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070, 070,
- 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050, 050,
- 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030,
- 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030, 030,
- 204, 204, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188,
- 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188,
- 174, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 142, 126, 126,
- 111, 95, 95, 95, 79, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
- 0, 1, 1, 1, 8, 7, 6, 4, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 8, 7, 6, 4, 5, 4, 3, 2, 1, 1, 1, 1,
- };
- uint32_t decodeSymbol(int sym)
- {
- int symArr[] = { sym, 0 };
- uint8_t* s = (uint8_t*)symArr;
- uint8_t data, byte, stat = 9;
- uint32_t unic = 0;
- while ((byte = *s++))
- {
- // Each byte is associated with a character class and a mask;
- // The character class is used to advance a finite automaton;
- // The mask is used to strip off leading bits from the byte;
- // The remaining bits are combined into a Unicode code point;
- // A code point is complete if the DFA enters the final state.
- #if ASCII_IN_TABLE
- data = utf8d[byte];
- stat = utf8d[256 + (stat << 4) + (data >> 4)];
- byte = (byte ^ (uint8_t)(data << 4));
- #else
- if (byte < 0x80)
- {
- stat = utf8d[128 + (stat << 4)];
- }
- else
- {
- data = utf8d[byte - 0x80];
- stat = utf8d[128 + (stat << 4) + (data >> 4)];
- byte = (byte ^ (uint8_t)(data << 4));
- }
- #endif
- unic = (unic << 6) | byte;
- if (!stat)
- {
- // unic is now a proper code point, we just print it out.
- //printf("U+%04X\n", unic);
- return unic;
- }
- if (stat == 1)
- {
- // the byte is not allowed here; the state would have to
- // be reset to continue meaningful reading of the string
- }
- }
- return 0;
- }
- namespace oxygine
- {
- FT_Library _library = 0;
- static int FT_SNAP_SIZE = 1000;
- static int FT_MAX_SNAP_SIZE = 200;
- static float FT_GLOBAL_WORLD_SCALE = 0.0f;
- static oxygine::Point FT_ATLAS_SIZE(512, 512);
- void ftGenDefault(ResFontFT::postProcessData& data)
- {
- Image& dest = *data.dest;
- const ImageData& src = *data.src;
- dest.init(src.w, src.h, TF_R8G8B8A8);
- ImageData rc = dest.lock();
- operations::blitPremultiply(src, rc);
- }
- static ResFontFT::postProcessHook _ftGen = ftGenDefault;
- void ResFontFT::setGlyphPostProcessor(postProcessHook f)
- {
- _ftGen = f;
- }
- Image tempImage;
- class FontFT : public Font
- {
- public:
- FontFT(ResFontFT* rs, int size) : _rs(rs), _size(size)
- {
- OX_ASSERT(size > 0);
- if (size <= 0)
- size = 10;
- _ignoreOptions = false;
- FT_Face face = _rs->_face;
- FT_Set_Pixel_Sizes(_rs->_face, 0, size);
- int dist = (int)(face->size->metrics.height / 64);
- int mxadv = dist;// face->size->metrics.max_advance / 64;
- init("abc", size, dist, mxadv);
- #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
- _glyphs.reserve(100);
- #endif
- }
- protected:
- ResFontFT* _rs;
- int _size;
- bool loadGlyph(int code, glyph& g, const glyphOptions& opt) override
- {
- FT_Face face = _rs->_face;
- FT_Set_Pixel_Sizes(_rs->_face, 0, _size);
- /* load glyph image into the slot (erase previous one) */
- int sm = decodeSymbol(code);
- int error = FT_Load_Char(face, sm, FT_LOAD_RENDER);
- if (error)
- return false;
- FT_GlyphSlot slot = face->glyph;
- FT_Bitmap bitmap = slot->bitmap;
- ImageData src(bitmap.width, bitmap.rows, bitmap.pitch, TF_A8, bitmap.buffer);
- Rect srcRect;
- spTexture t;
- g.advance_x = static_cast<short>(slot->advance.x >> 6);
- g.advance_y = static_cast<short>(slot->advance.y >> 6);
- g.offset_x = slot->bitmap_left;
- g.offset_y = -slot->bitmap_top;
- g.ch = code;
- g.opt = opt;
- //if (src.w && src.h)
- {
- ResFontFT::postProcessData gd;
- gd.src = &src;
- gd.dest = &tempImage;
- gd.gl = &g;
- gd.opt = opt;
- gd.font = this;
- if (src.w && src.h)
- _ftGen(gd);
- else
- {
- tempImage.init(0, 0, TF_R8G8B8A8);
- }
- _rs->_atlas.add(tempImage.lock(), srcRect, t);
- OX_ASSERT(t);
- g.src = srcRect.cast<RectF>();
- Vector2 sz((float)t->getWidth(), (float)t->getHeight());
- g.src.pos = g.src.pos.div(sz);
- g.src.size = g.src.size.div(sz);
- g.texture = safeSpCast<NativeTexture>(t);
- }
- g.sw = tempImage.getWidth();
- g.sh = tempImage.getHeight();
- return true;
- }
- };
- Resource* ResFontFT::createResource(CreateResourceContext& context)
- {
- ResFontFT* res = new ResFontFT;
- pugi::xml_node node = context.walker.getNode();
- setNode(res, node);
- std::string file = context.walker.getPath("file");
- res->setName(Resource::extractID(node, file, ""));
- res->init(file);
- context.resources->add(res);
- return res;
- }
- void ResFontFT::initLibrary()
- {
- Resources::registerResourceType(&ResFontFT::createResource, "ftfont");
- FT_Init_FreeType(&_library);
- }
- void ResFontFT::freeLibrary()
- {
- FT_Done_FreeType(_library);
- Resources::unregisterResourceType("ftfont");
- }
- int ResFontFT::getSnapSize()
- {
- return FT_SNAP_SIZE;
- }
- void ResFontFT::setSnapSize(int size)
- {
- FT_SNAP_SIZE = size;
- }
- void ResFontFT::setMaxSnapSize(int size)
- {
- FT_MAX_SNAP_SIZE = size;
- }
- void ResFontFT::setAtlasSize(int w, int h)
- {
- FT_ATLAS_SIZE = Point(w, h);
- }
- void ResFontFT::setGlobalWorldScale(float s)
- {
- FT_GLOBAL_WORLD_SCALE = s;
- }
- ResFontFT::ResFontFT() : _atlas(CLOSURE(this, &ResFontFT::createTexture)), _face(0)
- {
- _atlas.init();
- }
- ResFontFT::~ResFontFT()
- {
- }
- spTexture ResFontFT::createTexture(int w, int h)
- {
- Image mt;
- mt.init(FT_ATLAS_SIZE.x, FT_ATLAS_SIZE.y, TF_R8G8B8A8);
- mt.fillZero();
- spNativeTexture texture = IVideoDriver::instance->createTexture();
- texture->init(mt.lock());
- return texture;
- }
- void ResFontFT::init(const std::string& fnt)
- {
- file::read(fnt.c_str(), _fdata);
- int error = FT_New_Memory_Face(_library,
- reinterpret_cast<const unsigned char*>(_fdata.getData()), _fdata.getSize(), 0, &_face);
- OX_ASSERT(!error);
- //_fonts.push_back(FontFT(this, 32));
- }
- Font* ResFontFT::getFont(int size)
- {
- OX_ASSERT(size >= 0);
- if (size <= 0)
- size = 10;
- for (fonts::iterator i = _fonts.begin(); i != _fonts.end(); ++i)
- {
- FontFT& f = *i;
- if (f.getSize() == size)
- return &f;
- }
- _fonts.push_back(FontFT(this, size));
- return &_fonts.back();
- }
- const Font* ResFontFT::getFont(const char* name, int size) const
- {
- //OX_ASSERT(size > 0);
- ResFontFT* r = const_cast<ResFontFT*>(this);
- return r->getFont(size);
- }
- const oxygine::Font* ResFontFT::getClosestFont(float worldScale, int styleFontSize, float& resScale) const
- {
- if (FT_GLOBAL_WORLD_SCALE != 0.0f)
- worldScale = FT_GLOBAL_WORLD_SCALE;
- int fontSize = (int)(styleFontSize * worldScale);
- if (!fontSize)
- return 0;
- if (fontSize > FT_SNAP_SIZE)
- {
- int x = fontSize + FT_SNAP_SIZE - 1;
- fontSize = x - (x % FT_SNAP_SIZE);
- fontSize = std::min(fontSize, FT_MAX_SNAP_SIZE);
- }
- resScale = (float)fontSize / styleFontSize;
- return getFont(0, fontSize);
- }
- void ResFontFT::_load(LoadResourcesContext* context)
- {
- }
- void ResFontFT::_unload()
- {
- }
- }
|