QString QtDistanceFieldFontTextureGenerator::generateFontTexture(CharacterRange characterRange) { // For each glyph short intsize = sizeof(int); // Starting from 1 (ommitting the null character) and going through a basic set. for (int c = characterRange.begin; c <= characterRange.end; ++c) { if (isprint(c)) { std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv1; std::string u8str = conv1.to_bytes(c); // Paint into QImage QImage characterImage; DistanceFieldGLFont::FontMetrics metrics; tie(characterImage, metrics) = generateCharacterImage(QString(StrCon(u8str))); // Process QImage to generate distance field QImage distanceField = generateDistanceField(characterImage); // Pack the distance field image into the font buffer image QRect cropRect = calculateAutocrop(distanceField); // Do the autocrop QImage cropped = crop(cropRect, metrics, distanceField); // Set the parameters in QDistanceFieldFontTexture } } // Pack the image // Save the image }
bool ewol::resource::DistanceFieldFont::addGlyph(const char32_t& _val) { std11::unique_lock<std11::recursive_mutex> lock(m_mutex); bool hasChange = false; if (m_font == nullptr) { return false; } // add the curent "char" GlyphProperty tmpchar; tmpchar.m_UVal = _val; egami::ImageMono imageGlyphRaw; egami::Image imageGlyphDistanceField; EWOL_DEBUG("Generate Glyph : " << _val); if (m_font->getGlyphProperty(SIZE_GENERATION, tmpchar) == true) { //EWOL_DEBUG("load char : '" << _val << "'=" << _val.get()); hasChange = true; // change line if needed ... if (m_lastGlyphPos.x() + tmpchar.m_sizeTexture.x()+m_borderSize*2.0 > m_data.getSize().x()) { m_lastGlyphPos.setX(1); m_lastGlyphPos += ivec2(0, m_lastRawHeigh); m_lastRawHeigh = 0; } while(m_lastGlyphPos.y()+tmpchar.m_sizeTexture.y()+m_borderSize*2.0 > m_data.getSize().y()) { ivec2 size = m_data.getSize(); size.setY(size.y()*2); m_data.resize(size, etk::Color<>(0)); // change the coordonate on the element in the texture for (size_t jjj = 0; jjj < m_listElement.size(); ++jjj) { m_listElement[jjj].m_texturePosStart *= vec2(1.0f, 0.5f); m_listElement[jjj].m_texturePosSize *= vec2(1.0f, 0.5f); } } m_textureBorderSize = vec2(m_borderSize/(float)m_data.getSize().x(), m_borderSize/(float)m_data.getSize().y() ); // draw the glyph m_font->drawGlyph(imageGlyphRaw, SIZE_GENERATION, tmpchar, m_borderSize); generateDistanceField(imageGlyphRaw, imageGlyphDistanceField); /* if (_val == 'Z') { for (int32_t yyy = 0; yyy < imageGlyphDistanceField.getSize().y(); ++yyy) { for (int32_t xxx = 0; xxx < imageGlyphDistanceField.getSize().x(); ++xxx) { std::cout << (int)(imageGlyphDistanceField.get(ivec2(xxx, yyy)).r()) << " "; } //std::cout << std::endl; } } */ m_data.insert(m_lastGlyphPos, imageGlyphDistanceField); // set image position tmpchar.m_texturePosStart.setValue( ((float)m_lastGlyphPos.x()+(m_borderSize*0.5f)) / (float)m_data.getSize().x(), ((float)m_lastGlyphPos.y()+(m_borderSize*0.5f)) / (float)m_data.getSize().y() ); tmpchar.m_texturePosSize.setValue( ((float)imageGlyphRaw.getSize().x()-m_borderSize) / (float)m_data.getSize().x(), ((float)imageGlyphRaw.getSize().y()-m_borderSize) / (float)m_data.getSize().y() ); // update the maximum of the line hight : if (m_lastRawHeigh < imageGlyphRaw.getSize().y()) { // note : +1 is for the overlapping of the glyph (Part 2) m_lastRawHeigh = imageGlyphRaw.getSize().y()+1; } // note : +1 is for the overlapping of the glyph (Part 3) // update the Bitmap position drawing : m_lastGlyphPos += ivec2(imageGlyphRaw.getSize().x()+1, 0); } else { EWOL_WARNING("Did not find char : '" << _val << "'=" << _val); tmpchar.setNotExist(); } m_listElement.push_back(tmpchar); //m_font[iii]->display(); // generate the kerning for all the characters : if (tmpchar.exist() == true) { // TODO : set the kerning back ... //m_font[iii]->generateKerning(m_size, m_listElement[iii]); } if (hasChange == true) { flush(); //egami::store(m_data, "fileFont.bmp"); // ==> for debug test only ... } return hasChange; }