osgText::Glyph* ScaledAltFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode) { { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_glyphMapMutex); FontSizeGlyphMap::iterator itr = _sizeGlyphMap.find(fontRes); if (itr != _sizeGlyphMap.end()) { GlyphMap& glyphmap = itr->second; GlyphMap::iterator gitr = glyphmap.find(charcode); if (gitr!=glyphmap.end()) return gitr->second.get(); } } if (_implementation.valid()) { if (charcode >= 128) { unsigned int normal_code = charcode % 128; // Reload a scaled version of the glyph osgText::Glyph *normal_glyph = getGlyph(fontRes, normal_code); const osgText::FontResolution new_fontRes(fontRes.first * m_Scale, fontRes.second * m_Scale); osgText::Glyph *scaled_glyph = _implementation->getGlyph(new_fontRes, normal_code); if (m_VCenter) { osg::Vec2 hbearing = scaled_glyph->getHorizontalBearing(); hbearing.y() += 0.5f * (normal_glyph->t() - scaled_glyph->t()); scaled_glyph->setHorizontalBearing(hbearing); } addGlyph (fontRes, charcode, scaled_glyph); return scaled_glyph; } else { osgText::Glyph* g = _implementation->getGlyph(fontRes, charcode); addGlyph (fontRes, charcode, g); return g; } } return 0; }
void ULLineEditor::pushFirstGlyphAtLastOfPrevLine() { PageBuffer *PB = PageBuffer::getInstance(); if ( PB->maxId() == 0 ) return; uint prevlineId; uint curId; if ( reedit ) { prevlineId = reedit_id - 1; curId = reedit_id; } else { prevlineId = PB->maxId(); curId = prevlineId + 1; } ULGlyphItem *it=takeFirst(); qDebug() << it->key; slotEditGroup(m_mainScene->groupById(prevlineId)); addGlyph(it); slotEditGroup(m_mainScene->groupById(curId)); }
void ULLineEditor::insertAtFirstLastGlyphFromPrevLine() { PageBuffer *PB = PageBuffer::getInstance(); if ( PB->maxId() == 0 ) //The line we are editing is the first one return; uint prevlineId; int curLineId; if ( reedit ) { curLineId = reedit_id; prevlineId = reedit_id - 1; } else { prevlineId = PB->maxId(); curLineId = prevlineId + 1; } slotEditGroup(m_mainScene->groupById(prevlineId)); ULGlyphItem *it= takeLast(); slotEditGroup(m_mainScene->groupById(curLineId)); addGlyph(it, false); }
int32_t ewol::resource::TexturedFont::getIndex(char32_t _charcode, const enum ewol::font::mode _displayMode) { std::unique_lock<std::recursive_mutex> lock(m_mutex); if (_charcode < 0x20) { return 0; } else if (_charcode < 0x80) { return _charcode - 0x1F; } else { for (size_t iii=0x80-0x20; iii < m_listElement[_displayMode].size(); iii++) { //EWOL_DEBUG("search : '" << charcode << "' =?= '" << (m_listElement[displayMode])[iii].m_UVal << "'"); if (_charcode == (m_listElement[_displayMode])[iii].m_UVal) { //EWOL_DEBUG("search : '" << charcode << "'"); if ((m_listElement[_displayMode])[iii].exist()) { //EWOL_DEBUG("return " << iii); return iii; } else { return 0; } } } } if (addGlyph(_charcode) == true) { // TODO : This does not work due to the fact that the update of open GL is not done in the context main cycle !!! ewol::getContext().forceRedrawAll(); } return 0; }
void ActivityDiagram::paste() { //map<sample, clone> map<Glyph*, Glyph*> glyphMap; // 新增 for (unsigned int i = 0; i < _copyGlyphs.size(); i++) { int id = _idCount; _idCount++; Glyph *glyphClone = addGlyph(id, _copyGlyphs[i]->getType(), _copyGlyphs[i]->getText()); glyphClone->setWidth(_copyGlyphs[i]->getWidth()); glyphClone->setHeight(_copyGlyphs[i]->getHeight()); if (glyphClone->getType() == EDGE) { glyphClone->setWidth(glyphClone->getWidth() + DELTA_X); glyphClone->setHeight(glyphClone->getHeight() + DELTA_Y); } glyphClone->setX(_copyGlyphs[i]->getX() + DELTA_X); glyphClone->setY(_copyGlyphs[i]->getY() + DELTA_Y); glyphMap.insert(pair<Glyph*, Glyph*>(_copyGlyphs[i], glyphClone)); } connectCopyGlyph(_copyGlyphs, glyphMap); notify(); }
bool loadGlyphIfPossible (const juce_wchar character) { if (faceWrapper != nullptr) { FT_Face face = faceWrapper->face; const unsigned int glyphIndex = FT_Get_Char_Index (face, character); if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING) == 0 && face->glyph->format == ft_glyph_format_outline) { const float scale = 1.0f / (float) (face->ascender - face->descender); Path destShape; if (getGlyphShape (destShape, face->glyph->outline, scale)) { addGlyph (character, destShape, face->glyph->metrics.horiAdvance * scale); if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) addKerning (face, character, glyphIndex); return true; } } } return false; }
const Font::Glyph* Font::findGlyph(uint32 codepoint) { auto glyph = std::find(m_glyphs.begin(), m_glyphs.end(), codepoint); if (glyph == m_glyphs.end()) return addGlyph(codepoint); return &(*glyph); }
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const { char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); if (iter != mCharGlyphInfoMap.end()) { return iter->second; } else { // this glyph doesn't yet exist, so render it and return the result return addGlyph(wch); } }
void ResourceManualFont::addRange(VectorPairCodeCoord& _info, size_t _first, size_t _last, int _width, int _height, float _aspect) { RangeInfo range = RangeInfo(_info[_first].code, _info[_last].code); for (size_t pos = _first; pos <= _last; ++pos) { GlyphInfo* info = range.getInfo(_info[pos].code); const IntCoord& coord = _info[pos].coord; addGlyph(info, _info[pos].code, coord.left, coord.top, coord.right(), coord.bottom(), _width, _height, _aspect); if (_info[pos].code == FontCodeType::Space) mSpaceGlyphInfo = *info; } mVectorRangeInfo.push_back(range); }
void LLFont::resetBitmapCache() { // Iterate through glyphs and clear the mIsRendered flag for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); iter != mCharGlyphInfoMap.end(); ++iter) { iter->second->mIsRendered = FALSE; //FIXME: this is only strictly necessary when resetting the entire font, //not just flushing the bitmap iter->second->mMetricsValid = FALSE; } mFontBitmapCachep->reset(); // Add the empty glyph`5 addGlyph(0, 0); }
void FontReader::read(std::istream *source, Font *target) { enum { keyState, glyphState } state = keyState; std::string line; while (std::getline(*source, line)) { strip(&line); switch (state) { case keyState: if (!line.empty()) { keyLine_ = line; state = glyphState; glyphWidth_ = 0; glyphHeight_ = 0; } break; case glyphState: if (line.empty()) { if (glyphHeight_) { addGlyph(target); state = keyState; } } else { if (glyphWidth_ == 0) { glyphWidth_ = line.size(); } else { if (line.size() != glyphWidth_) { std::stringstream message; message << "Glyph width mismatch: " << line; throw Error(message.str()); } } if (glyphHeight_ == glyphLines_.size()) { glyphLines_.resize(glyphLines_.size() + 1); } glyphLines_[glyphHeight_] = line; ++glyphHeight_; } break; } } }
void ULLineEditor::insertAtLastFirstGlyphOfNextLine() { PageBuffer *PB = PageBuffer::getInstance(); if ( !reedit ) //Last line is current return; if(reedit_id == PB->maxId())//We are the last return; uint nextlineId = reedit_id + 1; uint curId = reedit_id; slotEditGroup(m_mainScene->groupById(nextlineId)); ULGlyphItem *it = takeFirst(); slotEditGroup(m_mainScene->groupById(curId)); addGlyph(it); }
void ULLineEditor::pushLastGlyphAtFirstOfNextLine() { PageBuffer *PB = PageBuffer::getInstance(); if ( !reedit ) //Last line is current return; if(reedit_id == PB->maxId())//We are the last return; uint nextlineId = reedit_id + 1; uint curId = reedit_id; ULGlyphItem *LaGlFrLi = takeLast(); slotEditGroup(m_mainScene->groupById(nextlineId)); addGlyph(LaGlFrLi, false); slotEditGroup(m_mainScene->groupById(curId)); }
ImageFont::ImageFont(const std::string& filename, unsigned char glyphsFrom, unsigned char glyphsTo) { mFilename = filename; mImage = Image::load(filename, false); Color separator = mImage->getPixel(0, 0); int i = 0; for (i=0; separator == mImage->getPixel(i, 0) && i < mImage->getWidth(); ++i) { } if (i >= mImage->getWidth()) { throw GCN_EXCEPTION("Corrupt image."); } int j = 0; for (j = 0; j < mImage->getHeight(); ++j) { if (separator == mImage->getPixel(i, j)) { break; } } mHeight = j; int x = 0, y = 0; for (i=glyphsFrom; i<glyphsTo+1; i++) { addGlyph(i, x, y, separator); } int w = mImage->getWidth(); int h = mImage->getHeight(); mImage->convertToDisplayFormat(); mRowSpacing = 0; mGlyphSpacing = 0; }
void CPetRooms::load(SimpleFile *file, int param) { if (!param) { int count = file->readNumber(); for (int idx = 0; idx < count; ++idx) { CPetRoomsGlyph *glyph = addGlyph(file->readNumber(), false); glyph->setMode((RoomGlyphMode)file->readNumber()); } _glyphItem.setMode((RoomGlyphMode)file->readNumber()); file->readNumber(); _floorNum = file->readNumber(); _elevatorNum = file->readNumber(); _roomNum = file->readNumber(); _field1CC = file->readNumber(); _wellEntry = file->readNumber(); _field1D4 = file->readNumber(); } }
void ResourceManualFont::deserialization(xml::ElementPtr _node, Version _version) { Base::deserialization(_node, _version); xml::ElementEnumerator node = _node->getElementEnumerator(); while (node.next()) { if (node->getName() == "Property") { const std::string& key = node->findAttribute("key"); const std::string& value = node->findAttribute("value"); if (key == "Source") mSource = value; else if (key == "DefaultHeight") mDefaultHeight = utility::parseInt(value); } else if (node->getName() == "Codes") { xml::ElementEnumerator range = node->getElementEnumerator(); while (range.next("Code")) { std::string range_value; std::vector<std::string> parse_range; // описане глифов if (range->findAttribute("index", range_value)) { Char id = 0; if (range_value == "cursor") id = FontCodeType::Cursor; else if (range_value == "selected") id = FontCodeType::Selected; else if (range_value == "selected_back") id = FontCodeType::SelectedBack; else id = utility::parseUInt(range_value); addGlyph(id, utility::parseValue<IntCoord>(range->findAttribute("coord"))); } } } } // инициализируем initialise(); }
CPetRoomsGlyph *CPetRooms::addRoom(uint roomFlags, bool highlight_) { // Ensure that we don't add room if the room is already present if (_glyphs.hasFlags(roomFlags)) return nullptr; if (_glyphs.size() >= 32) { // Too many room glyphs present. Scan for and remove the first // glyph that isn't for an assigned bedroom for (CPetRoomsGlyphs::iterator i = _glyphs.begin(); i != _glyphs.end(); ++i) { CPetRoomsGlyph *glyph = dynamic_cast<CPetRoomsGlyph *>(*i); if (!glyph->isAssigned()) { _glyphs.erase(i); break; } } } // Add the glyph return addGlyph(roomFlags, highlight_); }
BOOL LLFont::addChar(const llwchar wch) const { if (mFTFace == NULL) return FALSE; llassert(!mIsFallback); //lldebugs << "Adding new glyph for " << wch << " to font" << llendl; FT_UInt glyph_index; // Initialize char to glyph map glyph_index = FT_Get_Char_Index(mFTFace, wch); if (glyph_index == 0) { // Try looking it up in the backup Unicode font if (mFallbackFontp) { //llinfos << "Trying to add glyph from fallback font!" << llendl LLFontList::iterator iter; for(iter = mFallbackFontp->begin(); iter != mFallbackFontp->end(); iter++) { glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); if (glyph_index) { addGlyphFromFont(*iter, wch, glyph_index); return TRUE; } } } } char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) { BOOL result = addGlyph(wch, glyph_index); return result; } return FALSE; }
CPetRoomsGlyph *CPetRooms::addRoom(uint roomFlags, bool highlight_) { // Ensure that we don't add room if the room is already present if (_glyphs.hasFlags(roomFlags)) return nullptr; if (_glyphs.size() >= 32) // Too many rooms already return nullptr; // Do a preliminary scan of the glyph list for any glyph that is // no longer valid, and thus can be removed for (CPetRoomsGlyphs::iterator i = _glyphs.begin(); i != _glyphs.end(); ++i) { CPetRoomsGlyph *glyph = dynamic_cast<CPetRoomsGlyph *>(*i); if (!glyph->isAssigned()) { _glyphs.erase(i); break; } } // Add the glyph return addGlyph(roomFlags, highlight_); }
bool loadGlyphIfPossible (juce_wchar character) { HDC dc = FontDCHolder::getInstance()->loadFont (name, isBold, isItalic, 0); GLYPHMETRICS gm; // if this is the fallback font, skip checking for the glyph's existence. This is because // with fonts like Tahoma, GetGlyphIndices can say that a glyph doesn't exist, but it still // gets correctly created later on. if (! isFallbackFont) { const WCHAR charToTest[] = { (WCHAR) character, 0 }; WORD index = 0; if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR && index == 0xffff) { return false; } } Path glyphPath; TEXTMETRIC tm; if (! GetTextMetrics (dc, &tm)) { addGlyph (character, glyphPath, 0); return true; } const float height = (float) tm.tmHeight; static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; const int bufSize = GetGlyphOutline (dc, character, GGO_NATIVE, &gm, 0, 0, &identityMatrix); if (bufSize > 0) { HeapBlock<char> data (bufSize); GetGlyphOutline (dc, character, GGO_NATIVE, &gm, bufSize, data, &identityMatrix); const TTPOLYGONHEADER* pheader = reinterpret_cast<TTPOLYGONHEADER*> (data.getData()); const float scaleX = 1.0f / height; const float scaleY = -1.0f / height; while ((char*) pheader < data + bufSize) { float x = scaleX * pheader->pfxStart.x.value; float y = scaleY * pheader->pfxStart.y.value; glyphPath.startNewSubPath (x, y); const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER)); const char* const curveEnd = ((const char*) pheader) + pheader->cb; while ((const char*) curve < curveEnd) { if (curve->wType == TT_PRIM_LINE) { for (int i = 0; i < curve->cpfx; ++i) { x = scaleX * curve->apfx[i].x.value; y = scaleY * curve->apfx[i].y.value; glyphPath.lineTo (x, y); } } else if (curve->wType == TT_PRIM_QSPLINE) { for (int i = 0; i < curve->cpfx - 1; ++i) { const float x2 = scaleX * curve->apfx[i].x.value; const float y2 = scaleY * curve->apfx[i].y.value; float x3, y3; if (i < curve->cpfx - 2) { x3 = 0.5f * (x2 + scaleX * curve->apfx[i + 1].x.value); y3 = 0.5f * (y2 + scaleY * curve->apfx[i + 1].y.value); } else { x3 = scaleX * curve->apfx[i + 1].x.value; y3 = scaleY * curve->apfx[i + 1].y.value; } glyphPath.quadraticTo (x2, y2, x3, y3); x = x3; y = y3; } } curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]); } pheader = (const TTPOLYGONHEADER*) curve; glyphPath.closeSubPath(); } } addGlyph (character, glyphPath, gm.gmCellIncX / height); int numKPs; const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs); for (int i = 0; i < numKPs; ++i) { if (kps[i].wFirst == character) addKerningPair (kps[i].wFirst, kps[i].wSecond, kps[i].iKernAmount / height); } return true; }
void ewol::resource::DistanceFieldFont::init(const std::string& _fontName) { std11::unique_lock<std11::recursive_mutex> lock(m_mutex); ewol::resource::Texture::init(_fontName); std::string localName = _fontName; std::vector<std::string> folderList; if (true == ewol::getContext().getFontDefault().getUseExternal()) { #if defined(__TARGET_OS__Android) folderList.push_back("ROOT:system/fonts"); #elif defined(__TARGET_OS__Linux) folderList.push_back("ROOT:usr/share/fonts/truetype"); #endif } std::string applicationBaseFont = ewol::getContext().getFontDefault().getFolder(); std::vector<std::string> applicationBaseFontList = etk::FSNodeExplodeMultiplePath(applicationBaseFont); for (auto &it : applicationBaseFontList) { folderList.push_back(it); } for (size_t folderID = 0; folderID < folderList.size() ; folderID++) { etk::FSNode myFolder(folderList[folderID]); // find the real Font name : std::vector<std::string> output; myFolder.folderGetRecursiveFiles(output); std::vector<std::string> split = etk::split(localName, ';'); EWOL_INFO("try to find font named : " << split << " in: " << myFolder); //EWOL_CRITICAL("parse string : " << split); bool hasFindAFont = false; for (size_t jjj=0; jjj<split.size(); jjj++) { EWOL_INFO(" try with : '" << split[jjj] << "'"); for (size_t iii=0; iii<output.size(); iii++) { //EWOL_DEBUG(" file : " << output[iii]); if( true == etk::end_with(output[iii], split[jjj]+"-"+"regular"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"r"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"regular"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"r"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+".ttf", false)) { EWOL_INFO(" find Font [Regular] : " << output[iii]); m_fileName = output[iii]; hasFindAFont=true; break; } } if (hasFindAFont == true) { EWOL_INFO(" find this font : '" << split[jjj] << "'"); break; } else if (jjj == split.size()-1) { EWOL_ERROR("Find NO font in the LIST ... " << split); } } if (hasFindAFont == true) { EWOL_INFO(" find this font : '" << folderList[folderID] << "'"); break; } else if (folderID == folderList.size()-1) { EWOL_ERROR("Find NO font in the LIST ... " << folderList); } } if (m_fileName.size() == 0) { EWOL_ERROR("can not load FONT name : '" << m_fileName << "'" ); m_font = nullptr; return; } EWOL_INFO("Load FONT name : '" << m_fileName << "'"); m_font = ewol::resource::FontFreeType::create(m_fileName); if (m_font == nullptr) { EWOL_ERROR("Pb Loading FONT name : '" << m_fileName << "'" ); } // set the bassic charset: m_listElement.clear(); if (m_font == nullptr) { return; } if (importFromFile() == true) { EWOL_INFO("GET distance field from previous file"); flush(); return; } m_sizeRatio = ((float)SIZE_GENERATION) / ((float)m_font->getHeight(SIZE_GENERATION)); // TODO : basic font use 512 is better ... == > maybe estimate it with the dpi ??? setImageSize(ivec2(256,32)); // now we can acces directly on the image m_data.clear(etk::Color<>(0x00000000)); // add error glyph addGlyph(0); // by default we set only the first AINSI char availlable for (int32_t iii=0x20; iii<0x7F; iii++) { addGlyph(iii); } flush(); //exportOnFile(); }
IPXdevLFont XdevLFontSystemRAI::createFontFromTexture(IPXdevLFile& file, IPXdevLTexture texture) { assert(m_rai && " XdevLFontImpl::createFontFromTexture: XdevLFontSystem not initialized."); auto font = std::shared_ptr<XdevLFontRAI>(new XdevLFontRAI()); IPXdevLTexture tx = texture; font->addFontTexture(texture); tx->lock(); tx->setTextureFilter(XDEVL_TEXTURE_MIN_FILTER, XDEVL_NEAREST); tx->setTextureFilter(XDEVL_TEXTURE_MAG_FILTER, XDEVL_NEAREST); tx->setTextureWrap(XDEVL_TEXTURE_WRAP_S, XDEVL_CLAMP_TO_EDGE); tx->setTextureWrap(XDEVL_TEXTURE_WRAP_T, XDEVL_CLAMP_TO_EDGE); tx->unlock(); // One unit on the screen for x,y [-1 , 1] font->setUnitX(2.0f/(xdl_float)screenWidth); font->setUnitY(2.0f/(xdl_float)screenHeight); xdl_uint numberOfTextures = 1; xdl_uint fontSize = 0; XdevLString tmp; file->readString(tmp); file->readString(tmp); file->readString(tmp); std::stringstream ss(tmp.toString()); ss >> numberOfTextures; ss.str(""); ss.clear(); // Get font size. file->readString(tmp); ss << tmp; ss >> fontSize; font->setFontSize(fontSize); xdl_float numCols = (xdl_float)tx->getWidth()/(xdl_float)fontSize; // TODO Using maps to handle id of the glyphs? At the moment it is just a hack. while(file->tell() != file->length()) { XdevLGlyphMetric gp; readLine(file, gp); // // TODO This part to find the position of the glyph in the texture is some sort of hack. // Make it so that all of the information is the the fontInfo.txt file. // xdl_uint idx = gp.character_code - 32; xdl_float pos_x = idx % (xdl_int)numCols; xdl_float pos_y = idx / (xdl_int)numCols; xdl_float ds = 1.0/(xdl_float)tx->getWidth()*gp.width; xdl_float dt = 1.0/(xdl_float)tx->getWidth()*gp.height; xdl_float s = 1.0/numCols*pos_x ; xdl_float t = 1.0 - 1.0/numCols*pos_y - (1.0/(xdl_float)tx->getHeight())*((fontSize - gp.height - gp.top)); // // Add an offset of x,y pixel offset to the s,t coordinates. // xdl_float offset_x = 0.0/(xdl_float)tx->getWidth(); xdl_float offset_y = 0.0/(xdl_float)tx->getHeight(); gp.vertices[0].x = gp.brearing_x; gp.vertices[0].y = (gp.height - gp.brearing_y); gp.vertices[0].s = s - offset_x; gp.vertices[0].t = t - dt - offset_y; gp.vertices[1].x = gp.brearing_x; gp.vertices[1].y = gp.brearing_y; gp.vertices[1].s = s - offset_x; gp.vertices[1].t = t + offset_y; gp.vertices[2].x = gp.brearing_x + gp.width; gp.vertices[2].y = gp.brearing_y; gp.vertices[2].s = s + ds + offset_x; gp.vertices[2].t = t + offset_y; gp.vertices[3].x = gp.brearing_x + gp.width; gp.vertices[3].y = (gp.height - gp.brearing_y); gp.vertices[3].s = s + ds + offset_x; gp.vertices[3].t = t - dt - offset_y; // // Find maximum value for the new line. // font->setNewLineSize(std::max(font->getNewLineSize(), gp.height)); font->addGlyph(gp); } return font; }
osgText::Glyph* ReverseAltFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode) { { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_glyphMapMutex); FontSizeGlyphMap::iterator itr = _sizeGlyphMap.find(fontRes); if (itr != _sizeGlyphMap.end()) { GlyphMap& glyphmap = itr->second; GlyphMap::iterator gitr = glyphmap.find(charcode); if (gitr!=glyphmap.end()) return gitr->second.get(); } } if (_implementation.valid()) { if (charcode >= 128) { // use '0' as the reference glyph for sizing and centering the new glyph. 'M' would // probably be a better choice, but i haven't made that glyph yet in my test font ;-) osgText::Glyph *reference = getGlyph(fontRes, '0'); osgText::Glyph *normal = getGlyph(fontRes, charcode % 128); osgText::Glyph *reverse = new osgText::Glyph(this, 0); int reference_width = reference->s(); int reference_height = reference->t(); int source_width = normal->s(); int source_height = normal->t(); // the new glyph should fit the full character cell. we expand the horizontal dimensions slightly // to compensate for texture blending at the edges of the glyph that might otherwise cause a gap // between adjacent reverse video characters. int cell_height = static_cast<int>(reference->getVerticalAdvance() + 0.5); int cell_width = static_cast<int>(reference->getHorizontalAdvance() + 0.5) + 2 * getGlyphImageMargin(); // sanity checking cell_width = std::max(cell_width, source_width); cell_height = std::max(cell_height, source_height); unsigned int cell_data_size = cell_height * cell_width; unsigned int data_size = normal->getImageSizeInBytes(); unsigned int bits_per_pixel = normal->getPixelSizeInBits(); assert(bits_per_pixel == 8); assert(normal->r() == 1); assert(cell_height >= source_height); assert(cell_width >= source_width); assert(data_size = source_width * source_height); // create and initialize the image array for the new glyph unsigned char const *image = normal->data(); unsigned char *data = new unsigned char[cell_data_size]; for (unsigned char *init = data; init < data + cell_data_size; ) { *init++ = 0xff; // opaque } // the new glyph cell is position based on the reference character. this ensures that // the edges line up correctly for different characters. the actual glyph needs to be // offset relative to the reference character based on the character metrics. this // offset is hard-coded into the new image, since the metrics for the new glyph will // be based entirely on the reference glyph. osg::Vec2 glyph_offset = reference->getHorizontalBearing() - normal->getHorizontalBearing(); unsigned int offset_top = static_cast<unsigned int>(std::max(0.0f, (cell_height - reference_height) / 2 - glyph_offset.y())); unsigned int offset_left = static_cast<unsigned int>(std::max(0.0f, (cell_width - reference_width) / 2 - glyph_offset.x())); unsigned char const *source = image; unsigned char *copy = data + offset_top * cell_width + offset_left; for (int j = 0; j < source_height; j++) { for (int i = 0; i < source_width; i++) { *copy++ = *source++ ^ 0xff; } copy += cell_width - source_width; } reverse->setImage(cell_width, cell_height, 1, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); // finally set the metrics such that the reference glyph would be centered in the // cell. offsets for this specific glyph have already been accounted for when // generating the new glyph image. osg::Vec2 horizontal_bearing = reference->getHorizontalBearing(); horizontal_bearing.x() -= (cell_width - reference_width) / 2; horizontal_bearing.y() -= (cell_height - reference_height) / 2; reverse->setHorizontalBearing(horizontal_bearing); // force uniform spacing, even if the font has variable width characters reverse->setHorizontalAdvance(reference->getHorizontalAdvance()); // no adjustments to the vertical metrics for now; ReverseAltFont is intended for // horizontal text only. reverse->setVerticalBearing(reference->getVerticalBearing()); reverse->setVerticalAdvance(reference->getVerticalAdvance()); // finally add the new glyph so we don't repeat all this work! addGlyph(fontRes, charcode, reverse); return reverse; } else { osgText::Glyph *g = _implementation->getGlyph(fontRes,charcode); addGlyph (fontRes, charcode, g); return g; } } return 0; }
std::pair<FontData*, FontAtlas*> FontManager::fetchFontDataAndAtlas(InputSourceRef source) { auto in = source->loadDataSource()->createStream(); // CAN THROW string version; in->readFixedString(&version, 10); if (version != "XFONT.003") { throw runtime_error("Font: WRONG FORMAT"); } // --- int glyphCount; in->readLittle(&glyphCount); auto data = new FontData(glyphCount); in->readLittle(&data->baseSize); in->readLittle(&data->height); in->readLittle(&data->ascent); in->readLittle(&data->descent); in->readLittle(&data->spaceAdvance); in->readLittle(&data->strikethroughFactor); in->readLittle(&data->underlineOffset); in->readLittle(&data->lineThickness); int atlasWidth; int atlasHeight; int atlasPadding; int unitMargin; int unitPadding; in->readLittle(&atlasWidth); in->readLittle(&atlasHeight); in->readLittle(&atlasPadding); in->readLittle(&unitMargin); in->readLittle(&unitPadding); auto atlas = new FontAtlas(atlasWidth, atlasHeight); for (int i = 0; i < glyphCount; i++) { int glyphChar; int glyphWidth; int glyphHeight; int glyphLeftExtent; int glyphTopExtent; int glyphAtlasX; int glyphAtlasY; in->readLittle(&glyphChar); data->glyphs[(wchar_t)glyphChar] = i; in->readLittle(&data->advance[i]); in->readLittle(&glyphWidth); in->readLittle(&glyphHeight); in->readLittle(&glyphLeftExtent); in->readLittle(&glyphTopExtent); in->readLittle(&glyphAtlasX); in->readLittle(&glyphAtlasY); auto glyphData = new unsigned char[glyphWidth * glyphHeight]; in->readData(glyphData, glyphWidth * glyphHeight); atlas->addGlyph(glyphData, glyphAtlasX + atlasPadding + unitMargin, glyphAtlasY + atlasPadding + unitMargin, glyphWidth, glyphHeight); delete[] glyphData; data->w[i] = glyphWidth + unitPadding * 2; data->h[i] = glyphHeight + unitPadding * 2; data->le[i] = glyphLeftExtent - unitPadding; data->te[i] = glyphTopExtent + unitPadding; int x = glyphAtlasX + atlasPadding + unitMargin - unitPadding; int y = glyphAtlasY + atlasPadding + unitMargin - unitPadding; data->u1[i] = x / (float)atlasWidth; data->v1[i] = y / (float)atlasHeight; data->u2[i] = (x + data->w[i]) / (float)atlasWidth; data->v2[i] = (y + data->h[i]) / (float)atlasHeight; } return make_pair(data, atlas); }
void ewol::resource::TexturedFont::init(const std::string& _fontName) { std::unique_lock<std::recursive_mutex> lock(m_mutex); ewol::resource::Texture::init(_fontName); EWOL_DEBUG("Load font : '" << _fontName << "'" ); m_font[0] = nullptr; m_font[1] = nullptr; m_font[2] = nullptr; m_font[3] = nullptr; m_modeWraping[0] = ewol::font::Regular; m_modeWraping[1] = ewol::font::Regular; m_modeWraping[2] = ewol::font::Regular; m_modeWraping[3] = ewol::font::Regular; m_lastGlyphPos[0].setValue(1,1); m_lastGlyphPos[1].setValue(1,1); m_lastGlyphPos[2].setValue(1,1); m_lastGlyphPos[3].setValue(1,1); m_lastRawHeigh[0] = 0; m_lastRawHeigh[1] = 0; m_lastRawHeigh[2] = 0; m_lastRawHeigh[3] = 0; int32_t tmpSize = 0; // extarct name and size : const char * tmpData = _fontName.c_str(); const char * tmpPos = strchr(tmpData, ':'); if (tmpPos == nullptr) { m_size = 1; EWOL_CRITICAL("Can not parse the font name : \"" << _fontName << "\" ??? ':' " ); return; } else { if (sscanf(tmpPos+1, "%d", &tmpSize)!=1) { m_size = 1; EWOL_CRITICAL("Can not parse the font name : \"" << _fontName << "\" == > size ???"); return; } } std::string localName(_fontName, 0, (tmpPos - tmpData)); if (tmpSize>400) { EWOL_ERROR("Font size too big ==> limit at 400 when exxeed ==> error : " << tmpSize << "==>30"); tmpSize = 30; } m_size = tmpSize; std::vector<std::string> folderList; if (true == ewol::getContext().getFontDefault().getUseExternal()) { #if defined(__TARGET_OS__Android) folderList.push_back("ROOT:system/fonts"); #elif defined(__TARGET_OS__Linux) folderList.push_back("ROOT:usr/share/fonts"); #endif } std::string applicationBaseFont = ewol::getContext().getFontDefault().getFolder(); std::vector<std::string> applicationBaseFontList = etk::FSNodeExplodeMultiplePath(applicationBaseFont); for (auto &it : applicationBaseFontList) { folderList.push_back(it); } for (size_t folderID=0; folderID<folderList.size() ; folderID++) { etk::FSNode myFolder(folderList[folderID]); // find the real Font name : std::vector<std::string> output; myFolder.folderGetRecursiveFiles(output); std::vector<std::string> split = etk::split(localName, ';'); EWOL_INFO("try to find font named : " << split << " in: " << myFolder); //EWOL_CRITICAL("parse string : " << split); bool hasFindAFont = false; for (size_t jjj=0; jjj<split.size(); jjj++) { EWOL_INFO(" try with : '" << split[jjj] << "'"); for (size_t iii=0; iii<output.size(); iii++) { //EWOL_DEBUG(" file : " << output[iii]); if( true == etk::end_with(output[iii], split[jjj]+"-"+"bold"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"b"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"bd"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"bold"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"bd"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"b"+".ttf", false)) { EWOL_INFO(" find Font [Bold] : " << output[iii]); m_fileName[ewol::font::Bold] = output[iii]; hasFindAFont=true; } else if( true == etk::end_with(output[iii], split[jjj]+"-"+"oblique"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"italic"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"Light"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"i"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"oblique"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"italic"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"light"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"i"+".ttf", false)) { EWOL_INFO(" find Font [Italic] : " << output[iii]); m_fileName[ewol::font::Italic] = output[iii]; hasFindAFont=true; } else if( true == etk::end_with(output[iii], split[jjj]+"-"+"bolditalic"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"boldoblique"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"bi"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"z"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"bolditalic"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"boldoblique"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"bi"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"z"+".ttf", false)) { EWOL_INFO(" find Font [Bold-Italic] : " << output[iii]); m_fileName[ewol::font::BoldItalic] = output[iii]; hasFindAFont=true; } else if( true == etk::end_with(output[iii], split[jjj]+"-"+"regular"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"-"+"r"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"regular"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+"r"+".ttf", false) || true == etk::end_with(output[iii], split[jjj]+".ttf", false)) { EWOL_INFO(" find Font [Regular] : " << output[iii]); m_fileName[ewol::font::Regular] = output[iii]; hasFindAFont=true; } } if (hasFindAFont == true) { EWOL_INFO(" find this font : '" << split[jjj] << "'"); break; } else if (jjj == split.size()-1) { EWOL_ERROR("Find NO font in the LIST ... " << split); } } if (hasFindAFont == true) { EWOL_INFO(" find this font : '" << folderList[folderID] << "'"); break; } else if (folderID == folderList.size()-1) { EWOL_ERROR("Find NO font in the LIST ... " << folderList); } } // try to find the reference mode : enum ewol::font::mode refMode = ewol::font::Regular; for(int32_t iii=3; iii >= 0; iii--) { if (m_fileName[iii].size() != 0) { refMode = (enum ewol::font::mode)iii; } } EWOL_DEBUG(" set reference mode : " << refMode); // generate the wrapping on the preventing error for(int32_t iii=3; iii >= 0; iii--) { if (m_fileName[iii].size() != 0) { m_modeWraping[iii] = (enum ewol::font::mode)iii; } else { m_modeWraping[iii] = refMode; } } for (int32_t iiiFontId=0; iiiFontId<4 ; iiiFontId++) { if (m_fileName[iiiFontId].size() == 0) { EWOL_DEBUG("can not load FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size ); m_font[iiiFontId] = nullptr; continue; } EWOL_INFO("Load FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size); m_font[iiiFontId] = ewol::resource::FontFreeType::create(m_fileName[iiiFontId]); if (m_font[iiiFontId] == nullptr) { EWOL_DEBUG("error in loading FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" == > size=" << m_size ); } } for (int32_t iiiFontId=0; iiiFontId<4 ; iiiFontId++) { // set the bassic charset: m_listElement[iiiFontId].clear(); if (m_font[iiiFontId] == nullptr) { continue; } m_height[iiiFontId] = m_font[iiiFontId]->getHeight(m_size); // TODO : basic font use 512 is better ... == > maybe estimate it with the dpi ??? setImageSize(ivec2(256,32)); // now we can acces directly on the image m_data.clear(etk::Color<>(0x00000000)); } // add error glyph addGlyph(0); // by default we set only the first AINSI char availlable for (int32_t iii=0x20; iii<0x7F; iii++) { EWOL_VERBOSE("Add clyph :" << iii); addGlyph(iii); } flush(); EWOL_DEBUG("Wrapping properties : "); EWOL_DEBUG(" " << ewol::font::Regular << " == >" << getWrappingMode(ewol::font::Regular)); EWOL_DEBUG(" " << ewol::font::Italic << " == >" << getWrappingMode(ewol::font::Italic)); EWOL_DEBUG(" " << ewol::font::Bold << " == >" << getWrappingMode(ewol::font::Bold)); EWOL_DEBUG(" " << ewol::font::BoldItalic << " == >" << getWrappingMode(ewol::font::BoldItalic)); }
BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback) { // Don't leak face objects. This is also needed to deal with // changed font file names. if (mFTFace) { FT_Done_Face(mFTFace); mFTFace = NULL; } int error; error = FT_New_Face( gFTLibrary, filename.c_str(), 0, &mFTFace ); if (error) { return FALSE; } mIsFallback = is_fallback; F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi error = FT_Set_Char_Size(mFTFace, /* handle to face object */ 0, /* char_width in 1/64th of points */ (S32)(point_size*64), /* char_height in 1/64th of points */ (U32)horz_dpi, /* horizontal device resolution */ (U32)vert_dpi); /* vertical device resolution */ if (error) { // Clean up freetype libs. FT_Done_Face(mFTFace); mFTFace = NULL; return FALSE; } F32 y_max, y_min, x_max, x_min; F32 ems_per_unit = 1.f/ mFTFace->units_per_EM; F32 pixels_per_unit = pixels_per_em * ems_per_unit; // Get size of bbox in pixels y_max = mFTFace->bbox.yMax * pixels_per_unit; y_min = mFTFace->bbox.yMin * pixels_per_unit; x_max = mFTFace->bbox.xMax * pixels_per_unit; x_min = mFTFace->bbox.xMin * pixels_per_unit; mAscender = mFTFace->ascender * pixels_per_unit; mDescender = -mFTFace->descender * pixels_per_unit; mLineHeight = mFTFace->height * pixels_per_unit; S32 max_char_width = llround(0.5f + (x_max - x_min)); S32 max_char_height = llround(0.5f + (y_max - y_min)); mFontBitmapCachep->init(components, max_char_width, max_char_height); if (!mFTFace->charmap) { //llinfos << " no unicode encoding, set whatever encoding there is..." << llendl; FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); } if (!mIsFallback) { // Add the default glyph addGlyph(0, 0); } mName = filename; mPointSize = point_size; return TRUE; }
void DatasetIsoline::initGeometry() { int nx = m_properties["maingl"].get( Fn::Property::D_NX ).toInt(); int ny = m_properties["maingl"].get( Fn::Property::D_NY ).toInt(); int nz = m_properties["maingl"].get( Fn::Property::D_NZ ).toInt(); float dx = m_properties["maingl"].get( Fn::Property::D_DX ).toFloat(); float dy = m_properties["maingl"].get( Fn::Property::D_DY ).toFloat(); float dz = m_properties["maingl"].get( Fn::Property::D_DZ ).toFloat(); float ax = m_properties["maingl"].get( Fn::Property::D_ADJUST_X ).toFloat(); float ay = m_properties["maingl"].get( Fn::Property::D_ADJUST_Y ).toFloat(); float az = m_properties["maingl"].get( Fn::Property::D_ADJUST_Z ).toFloat(); m_x = Models::getGlobal( Fn::Property::G_SAGITTAL ).toFloat(); m_y = Models::getGlobal( Fn::Property::G_CORONAL ).toFloat(); m_z = Models::getGlobal( Fn::Property::G_AXIAL ).toFloat(); int xi = qMax( 0.0f, qMin( ( m_x - ax ) / dx, (float)nx - 1 ) ); int yi = qMax( 0.0f, qMin( ( m_y - ay ) / dy, (float)ny - 1 ) ); int zi = qMax( 0.0f, qMin( ( m_z - az ) / dz, (float)nz - 1 ) ); float isoValue = m_properties["maingl"].get( Fn::Property::D_ISO_VALUE ).toFloat(); bool interpolation = m_properties["maingl"].get( Fn::Property::D_INTERPOLATION ).toBool(); m_color = m_properties["maingl"].get( Fn::Property::D_COLOR ).value<QColor>(); int stripeType = m_properties["maingl"].get( Fn::Property::D_ISOLINE_STRIPES ).toInt(); std::vector<float>verts; std::vector<float>stripeVerts; std::vector<float>colors; std::vector<float>stripeColors; m_vertCountAxial = 0; m_vertCountCoronal = 0; m_vertCountSagittal = 0; if ( m_properties["maingl"].get( Fn::Property::D_RENDER_AXIAL ).toBool() ) { std::vector<float>sliceData; std::vector<float>tmpVerts; std::vector<float>tmpVerts2; sliceData = extractAnatomyAxial( zi ); MarchingSquares ms1( &sliceData, isoValue, nx, ny, dx, dy, interpolation ); tmpVerts = ms1.run(); if ( stripeType > 0 ) { tmpVerts2 = ms1.runStripes( stripeType, 2 ); } if ( tmpVerts.size() > 0 ) { for ( unsigned int i = 0; i < tmpVerts.size() / 4; ++i ) { addGlyph( verts, colors, tmpVerts[4*i] + ax, tmpVerts[4*i+1] + ay, m_z, tmpVerts[4*i+2] + ax, tmpVerts[4*i+3] + ay, m_z ); } if ( stripeType > 0 ) { for ( unsigned int i = 0; i < tmpVerts2.size() / 4; ++i ) { addGlyph( stripeVerts, stripeColors, tmpVerts2[4*i] + ax, tmpVerts2[4*i+1] + ay, m_z, tmpVerts2[4*i+2] + ax, tmpVerts2[4*i+3] + ay, m_z ); } } m_vertCountAxial = verts.size() / 8; m_stripeVertCountAxial = stripeVerts.size() / 8; } } if ( m_properties["maingl"].get( Fn::Property::D_RENDER_CORONAL ).toBool() ) { std::vector<float>sliceData; std::vector<float>tmpVerts; std::vector<float>tmpVerts2; sliceData = extractAnatomyCoronal( yi ); MarchingSquares ms1( &sliceData, isoValue, nx, nz, dx, dz, interpolation ); tmpVerts = ms1.run(); if ( stripeType > 0 ) { tmpVerts2 = ms1.runStripes( stripeType, 2 ); } if ( tmpVerts.size() > 0 ) { for ( unsigned int i = 0; i < tmpVerts.size() / 4; ++i ) { addGlyph( verts, colors, tmpVerts[4*i] + ax, m_y, tmpVerts[4*i+1] + az, tmpVerts[4*i+2] + ax, m_y, tmpVerts[4*i+3] + az ); } if ( stripeType > 0 ) { for ( unsigned int i = 0; i < tmpVerts2.size() / 4; ++i ) { addGlyph( stripeVerts, stripeColors, tmpVerts2[4*i] + ax, m_y, tmpVerts2[4*i+1] + az, tmpVerts2[4*i+2] + ax, m_y, tmpVerts2[4*i+3] + az ); } } m_vertCountCoronal = verts.size() / 8 - m_vertCountAxial; m_stripeVertCountCoronal = stripeVerts.size() / 8 - m_stripeVertCountAxial; } } if ( m_properties["maingl"].get( Fn::Property::D_RENDER_SAGITTAL ).toBool() ) { std::vector<float>sliceData; std::vector<float>tmpVerts; std::vector<float>tmpVerts2; sliceData = extractAnatomySagittal( xi ); MarchingSquares ms1( &sliceData, isoValue, ny, nz, dy, dz, interpolation ); tmpVerts = ms1.run(); if ( stripeType > 0 ) { tmpVerts2 = ms1.runStripes( stripeType, 2 ); } if ( tmpVerts.size() > 0 ) { for ( unsigned int i = 0; i < tmpVerts.size() / 4; ++i ) { addGlyph( verts, colors, m_x, tmpVerts[4*i] + ay, tmpVerts[4*i+1] + az, m_x, tmpVerts[4*i+2] + ay, tmpVerts[4*i+3] + az ); } if ( stripeType > 0 ) { for ( unsigned int i = 0; i < tmpVerts2.size() / 4; ++i ) { addGlyph( stripeVerts, stripeColors, m_x, tmpVerts2[4*i] + ay, tmpVerts2[4*i+1] + az, m_x, tmpVerts2[4*i+2] + ay, tmpVerts2[4*i+3] + az ); } } m_vertCountSagittal = verts.size() / 8 - ( m_vertCountCoronal + m_vertCountAxial ); m_stripeVertCountSagittal = stripeVerts.size() / 8 - ( m_stripeVertCountCoronal + m_stripeVertCountAxial ); } } if ( verts.size() > 0 ) { if( vbo0 ) { GLFunctions::f->glDeleteBuffers( 1, &vbo0 ); } GLFunctions::f->glGenBuffers( 1, &vbo0 ); if( vbo1 ) { GLFunctions::f->glDeleteBuffers( 1, &vbo1 ); } GLFunctions::f->glGenBuffers( 1, &vbo1 ); if( vbo2 ) { GLFunctions::f->glDeleteBuffers( 1, &vbo2 ); } GLFunctions::f->glGenBuffers( 1, &vbo2 ); if( vbo3 ) { GLFunctions::f->glDeleteBuffers( 1, &vbo3 ); } GLFunctions::f->glGenBuffers( 1, &vbo3 ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, vbo0 ); GLFunctions::f->glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof( float ), verts.data(), GL_DYNAMIC_DRAW ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, 0 ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, vbo1 ); GLFunctions::f->glBufferData( GL_ARRAY_BUFFER, colors.size() * sizeof( float ), colors.data(), GL_DYNAMIC_DRAW ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, 0 ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, vbo2 ); GLFunctions::f->glBufferData( GL_ARRAY_BUFFER, stripeVerts.size() * sizeof( float ), stripeVerts.data(), GL_DYNAMIC_DRAW ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, 0 ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, vbo3 ); GLFunctions::f->glBufferData( GL_ARRAY_BUFFER, stripeColors.size() * sizeof( float ), stripeColors.data(), GL_DYNAMIC_DRAW ); GLFunctions::f->glBindBuffer( GL_ARRAY_BUFFER, 0 ); } m_dirty = false; }
osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex()); setFontResolution(fontRes); // // GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being // returned, for symbol fonts in windows (FT_ENCONDING_MS_SYMBOL in freetype) the correct // values are from 0xF000 to 0xF0FF not from 0x000 to 0x00FF (0 to 255) as you would expect. // Microsoft uses a private field for its symbol fonts // unsigned int charindex = charcode; if (_face->charmap != NULL) { if (_face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { charindex |= 0xF000; } } FT_Error error = FT_Load_Char( _face, charindex, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP|_flags ); if (error) { osg::notify(osg::WARN) << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl; return 0; } FT_GlyphSlot glyphslot = _face->glyph; int pitch = glyphslot->bitmap.pitch; unsigned char* buffer = glyphslot->bitmap.buffer; unsigned int sourceWidth = glyphslot->bitmap.width;; unsigned int sourceHeight = glyphslot->bitmap.rows; unsigned int width = sourceWidth; unsigned int height = sourceHeight; osg::ref_ptr<osgText::Font::Glyph> glyph = new osgText::Font::Glyph; unsigned int dataSize = width*height; unsigned char* data = new unsigned char[dataSize]; // clear the image to zeros. for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; } glyph->setImage(width,height,1, GL_ALPHA, GL_ALPHA,GL_UNSIGNED_BYTE, data, osg::Image::USE_NEW_DELETE, 1); glyph->setInternalTextureFormat(GL_ALPHA); // copy image across to osgText::Glyph image. switch(glyphslot->bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: for(int r=sourceHeight-1;r>=0;--r) { unsigned char* ptr = buffer+r*pitch; for(unsigned int c=0;c<sourceWidth;++c) { (*data++)= (ptr[c >> 3] & (1 << (~c & 7))) ? 255 : 0; } } break; case FT_PIXEL_MODE_GRAY: for(int r=sourceHeight-1;r>=0;--r) { unsigned char* ptr = buffer+r*pitch; for(unsigned int c=0;c<sourceWidth;++c,++ptr) { (*data++)=*ptr; } } break; default: osg::notify(osg::WARN) << "FT_Load_Char(...) returned bitmap with unknown pixel_mode " << glyphslot->bitmap.pixel_mode << std::endl; } FT_Glyph_Metrics* metrics = &(glyphslot->metrics); glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX/64.0f,(float)(metrics->horiBearingY-metrics->height)/64.0f)); // bottom left. glyph->setHorizontalAdvance((float)metrics->horiAdvance/64.0f); glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX/64.0f,(float)(metrics->vertBearingY-metrics->height)/64.0f)); // top middle. glyph->setVerticalAdvance((float)metrics->vertAdvance/64.0f); addGlyph(fontRes,charcode,glyph.get()); // cout << " in getGlyph() implementation="<<this<<" "<<_filename<<" facade="<<_facade<<endl; return glyph.get(); }