osg::Vec2 FreeTypeFont::getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex()); setFontResolution(fontRes); if (!FT_HAS_KERNING(_face) || (kerningType == osgText::KERNING_NONE)) return osg::Vec2(0.0f,0.0f); FT_Kerning_Mode mode = (kerningType==osgText::KERNING_DEFAULT) ? ft_kerning_default : ft_kerning_unfitted; // convert character code to glyph index FT_UInt left = FT_Get_Char_Index( _face, leftcharcode ); FT_UInt right = FT_Get_Char_Index( _face, rightcharcode ); // get the kerning distances. FT_Vector kerning; FT_Error error = FT_Get_Kerning( _face, // handle to face object left, // left glyph index right, // right glyph index mode, // kerning mode &kerning ); // target vector if (error) { OSG_WARN << "FT_Get_Kerning(...) returned error code " <<std::hex<<error<<std::dec<< std::endl; return osg::Vec2(0.0f,0.0f); } float coord_scale = getCoordScale(); return osg::Vec2((float)kerning.x*coord_scale,(float)kerning.y*coord_scale); }
TextShape::TextShape(std::string command, std::string name) { // check for changed values createParameter("pos", new Vec3Type()); createParameter("color", new Vec4Type()); createParameter("bcolor", new Vec4Type()); createParameter("enableOutline", new BoolType()); createParameter("size", new FloatType()); createParameter("label", new StringType()); createParameter("font", new StringType()); _type = SimpleShape::TEXT; BasicShape::setName(name); // default color is white for font setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0)); // set a default background color setBackdropColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); setCharacterSize(10.0f); setFontResolution(40,40); osgText::Font* font = NULL; // check if fontMap has been constucted if ( _fontMap == NULL ) _fontMap = new ThreadMap< std::string, osgText::Font* >(); // check if font exists in map else load it and add it if( ! _fontMap->get(std::string("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"), font) ) { font = osgText::readFontFile("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"); _fontMap->add(std::string("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"), font); } setFont(font); if( Globals::G_ROTAXIS ) setAxisAlignment(osgText::TextBase::XY_PLANE); else setAxisAlignment(osgText::TextBase::XZ_PLANE); // off by default setBackdropType(osgText::Text::NONE); osg::StateSet* state = osgText::Text::getOrCreateStateSet(); state->setMode(GL_BLEND, osg::StateAttribute::ON); state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); //osg::Material* mat = new osg::Material(); //mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); //state->setAttributeAndModes(mat, osg::StateAttribute::ON); setUpdateCallback(new TextUpdateCallback()); update(command); }
TextShape::TextShape(std::string command, std::string name) { _type = SimpleShape::TEXT; BasicShape::setName(name); setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0)); setCharacterSize(10.0f); setFontResolution(40,40); setFont ("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"); setAxisAlignment(osgText::TextBase::XZ_PLANE); setBackdropType(osgText::Text::NONE); osg::StateSet* state = osgText::Text::getOrCreateStateSet(); state->setMode(GL_BLEND, osg::StateAttribute::ON); state->setMode(GL_LIGHTING, osg::StateAttribute::OFF); //osg::Material* mat = new osg::Material(); //mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); //state->setAttributeAndModes(mat, osg::StateAttribute::ON); setUpdateCallback(new TextUpdateCallback()); update(command); }
osgText::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_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::Glyph> glyph = new osgText::Glyph(_facade, charcode); 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_WARN << "FT_Load_Char(...) returned bitmap with unknown pixel_mode " << glyphslot->bitmap.pixel_mode << std::endl; } FT_Glyph_Metrics* metrics = &(_face->glyph->metrics); #if 0 float coord_scale = _freetype_scale/64.0f; #else float coord_scale = 1.0f/64.0f; #endif glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left. glyph->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale); glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle. glyph->setVerticalAdvance((float)metrics->vertAdvance * coord_scale); // cout << " in getGlyph() implementation="<<this<<" "<<_filename<<" facade="<<_facade<<endl; return glyph.release(); }
osgText::Glyph3D * FreeTypeFont::getGlyph3D(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_DEFAULT|_flags ); if (error) { OSG_WARN << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl; return 0; } if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) { OSG_WARN << "FreeTypeFont3D::getGlyph : not a vector font" << std::endl; return 0; } float coord_scale = getCoordScale(); // ** init FreeType to describe the glyph FreeType::Char3DInfo char3d(_facade->getNumberCurveSamples()); char3d._coord_scale = coord_scale; FT_Outline outline = _face->glyph->outline; FT_Outline_Funcs funcs; funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo; funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo; funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo; funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo; funcs.shift = 0; funcs.delta = 0; FT_Orientation orientation = FT_Outline_Get_Orientation(&outline); char3d._reverseFill = (orientation == FT_ORIENTATION_POSTSCRIPT); // ** record description FT_Error _error = FT_Outline_Decompose(&outline, &funcs, &char3d); if (_error) { OSG_WARN << "FreeTypeFont3D::getGlyph : - outline decompose failed ..." << std::endl; return 0; } // ** create geometry for each part of the glyph osg::ref_ptr<osg::Geometry> frontGeo(new osg::Geometry); osg::ref_ptr<osg::Vec3Array> rawVertices = new osg::Vec3Array(*(char3d._verts)); osg::Geometry::PrimitiveSetList rawPrimitives; for(osg::Geometry::PrimitiveSetList::iterator itr = char3d.get()->getPrimitiveSetList().begin(); itr != char3d.get()->getPrimitiveSetList().end(); ++itr) { rawPrimitives.push_back(dynamic_cast<osg::PrimitiveSet*>((*itr)->clone(osg::CopyOp::DEEP_COPY_ALL))); } // ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list osg::ref_ptr<osgText::Glyph3D> glyph = new osgText::Glyph3D(_facade, charcode); // copy the raw primitive set list before we tessellate it. glyph->getRawFacePrimitiveSetList() = rawPrimitives; glyph->setRawVertexArray(rawVertices.get()); FT_Glyph_Metrics* metrics = &(_face->glyph->metrics); glyph->setWidth((float)metrics->width * coord_scale); glyph->setHeight((float)metrics->height * coord_scale); glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left. glyph->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale); glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle. glyph->setVerticalAdvance((float)metrics->vertAdvance * coord_scale); #if 0 OSG_NOTICE<<"getGlyph3D("<<charcode<<", "<<char(charcode)<<")"<<std::endl; OSG_NOTICE<<" height="<<glyph->getHeight()<<std::endl; OSG_NOTICE<<" width="<<glyph->getWidth()<<std::endl; OSG_NOTICE<<" horizontalBearing="<<glyph->getHorizontalBearing()<<std::endl; OSG_NOTICE<<" horizontalAdvance="<<glyph->getHorizontalAdvance()<<std::endl; OSG_NOTICE<<" verticalBearing="<<glyph->getHorizontalBearing()<<std::endl; OSG_NOTICE<<" verticalAdvance="<<glyph->getVerticalAdvance()<<std::endl; #endif FT_BBox ftbb; FT_Outline_Get_BBox(&outline, &ftbb); osg::BoundingBox bb(float(ftbb.xMin) * coord_scale, float(ftbb.yMin) * coord_scale, 0.0f, float(ftbb.xMax) * coord_scale, float(ftbb.yMax) * coord_scale, 0.0f); glyph->setBoundingBox(bb); return glyph.release(); }