void FreeTypeFont::init() { FT_Error _error; #if 0 _error = FT_Set_Pixel_Sizes(_face, 32, 32); if (_error) { OSG_NOTICE << "FreeTypeFont3D: set pixel sizes failed ..." << std::endl; return; } #endif FT_Set_Char_Size( _face, 64*64, 64*64, 600, 600); int glyphIndex = FT_Get_Char_Index( _face, 'M' ); _error = FT_Load_Glyph( _face, glyphIndex, FT_LOAD_DEFAULT ); if (_error) { OSG_NOTICE << "FreeTypeFont3D: initial glyph load failed ..." << std::endl; return; } if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) { OSG_NOTICE << "FreeTypeFont3D: not a vector font" << std::endl; return; } { FreeType::Char3DInfo char3d(10); 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; _error = FT_Outline_Decompose(&outline,&funcs,&char3d); if (_error) { OSG_NOTICE << "FreeTypeFont3D: - outline decompose failed ..." << std::endl; return; } FT_BBox bb; FT_Outline_Get_BBox(&outline,&bb); long ymin = ft_floor( bb.yMin ); long ymax = ft_ceiling( bb.yMax ); double height = double(ymax - ymin)/64.0; // long xmin = ft_floor( bb.xMin ); // long xmax = ft_ceiling( bb.xMax ); // double width = (xmax - xmin)/64.0; _freetype_scale = 1.0f/height; } }
osgText::Glyph3D * FreeTypeFont::getGlyph3D(unsigned int charcode) { OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex()); // // 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 = _freetype_scale/64.0f; // ** 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; // ** 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> glyph3D = new osgText::Glyph3D(_facade, charcode); // copy the raw primitive set list before we tessellate it. glyph3D->getRawFacePrimitiveSetList() = rawPrimitives; glyph3D->setRawVertexArray(rawVertices.get()); FT_Glyph_Metrics* metrics = &(_face->glyph->metrics); glyph3D->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX * coord_scale,(float)(metrics->horiBearingY-metrics->height) * coord_scale)); // bottom left. glyph3D->setHorizontalAdvance((float)metrics->horiAdvance * coord_scale); glyph3D->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX * coord_scale,(float)(metrics->vertBearingY-metrics->height) * coord_scale)); // top middle. glyph3D->setVerticalAdvance((float)metrics->vertAdvance * coord_scale); glyph3D->setWidth((float)metrics->width * coord_scale); glyph3D->setHeight((float)metrics->height * coord_scale); FT_BBox ftbb; FT_Outline_Get_BBox(&outline, &ftbb); long xmin = ft_floor( ftbb.xMin ); long xmax = ft_ceiling( ftbb.xMax ); long ymin = ft_floor( ftbb.yMin ); long ymax = ft_ceiling( ftbb.yMax ); osg::BoundingBox bb(xmin * coord_scale, ymin * coord_scale, 0.0f, xmax * coord_scale, ymax * coord_scale, 0.0f); glyph3D->setBoundingBox(bb); return glyph3D.release(); }