mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
0030782: Visualization, Font_FTFont - use predefined fallback fonts for extended Unicode subsets
Font_FTFont now uses fallback fonts for characters from unsupported Unicode subsets, managed by Font_FTFont::ToUseUnicodeSubsetFallback() and Font_FontMgr::ToUseUnicodeSubsetFallback() option, enabled by default. The fallback list includes common font families for Chinese, Korean and Japanese languages. Font_FTFont::RenderGlyph() now supports FT_PIXEL_MODE_MONO input format used by some CJK fonts. OpenGl_Font::createTexture() now limits single texture size to circa 4096 glyphs. test/testgrid now expects test scripts being in UTF-8 encoding in sync with "DRAWEXE -f script.tcl". AIS::InitFaceLength() - fixed usage of uninitialized result.
This commit is contained in:
parent
1bb67d3844
commit
912761ea17
@ -783,6 +783,7 @@ Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face& aFace,
|
||||
BRepAdaptor_Surface surf1( aFace );
|
||||
Handle( Adaptor3d_HSurface ) surf2;
|
||||
Standard_Boolean isOffset = Standard_False;
|
||||
Offset = 0.0;
|
||||
|
||||
if (surf1.GetType() == GeomAbs_OffsetSurface)
|
||||
{
|
||||
@ -801,7 +802,6 @@ Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face& aFace,
|
||||
{
|
||||
aPlane = surf2->Plane();
|
||||
aSurfType = AIS_KOS_Plane;
|
||||
Offset = 0.;
|
||||
Result = Standard_True;
|
||||
}
|
||||
|
||||
@ -817,7 +817,6 @@ Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face& aFace,
|
||||
gp_Pln thePlane( LinePos, LineDir ^ ExtrusionDir);
|
||||
aPlane = thePlane;
|
||||
aSurfType = AIS_KOS_Plane;
|
||||
Offset = 0.;
|
||||
Result = Standard_True;
|
||||
}
|
||||
}
|
||||
@ -826,7 +825,6 @@ Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face& aFace,
|
||||
{
|
||||
aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
|
||||
aPlane = (Handle( Geom_Plane )::DownCast( aSurf ))->Pln();
|
||||
Offset = 0.0e0;
|
||||
}
|
||||
if (Result == Standard_False)
|
||||
{
|
||||
@ -839,7 +837,6 @@ Standard_Boolean AIS::GetPlaneFromFace(const TopoDS_Face& aFace,
|
||||
TheType == STANDARD_TYPE(Geom_ToroidalSurface))
|
||||
{
|
||||
aSurf = (Handle( Geom_OffsetSurface )::DownCast( aSurf ))->Surface();
|
||||
Offset = 0.0e0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -899,20 +896,18 @@ gp_Pnt AIS::ProjectPointOnLine( const gp_Pnt & aPoint, const gp_Lin & aLine )
|
||||
//function : InitFaceLength
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void AIS::InitFaceLength (const TopoDS_Face& aFace,
|
||||
gp_Pln & aPlane,
|
||||
Handle(Geom_Surface) & aSurface,
|
||||
AIS_KindOfSurface & aSurfaceType,
|
||||
Standard_Real & anOffset)
|
||||
void AIS::InitFaceLength (const TopoDS_Face& theFace,
|
||||
gp_Pln& thePlane,
|
||||
Handle(Geom_Surface)& theSurface,
|
||||
AIS_KindOfSurface& theSurfaceType,
|
||||
Standard_Real& theOffset)
|
||||
{
|
||||
AIS::GetPlaneFromFace( aFace, aPlane, aSurface, aSurfaceType, anOffset );
|
||||
|
||||
if (Abs( anOffset ) > Precision::Confusion())
|
||||
{
|
||||
aSurface = new Geom_OffsetSurface( aSurface, anOffset );
|
||||
anOffset = 0.0e0;
|
||||
}
|
||||
|
||||
if (AIS::GetPlaneFromFace (theFace, thePlane, theSurface, theSurfaceType, theOffset)
|
||||
&& Abs (theOffset) > Precision::Confusion())
|
||||
{
|
||||
theSurface = new Geom_OffsetSurface (theSurface, theOffset);
|
||||
theOffset = 0.0e0;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@ -1298,23 +1298,23 @@ proc _run_test {scriptsdir group gridname casefile echo} {
|
||||
# execute test scripts
|
||||
if { [file exists $scriptsdir/$group/begin] } {
|
||||
puts "Executing $scriptsdir/$group/begin..."; flush stdout
|
||||
uplevel source $scriptsdir/$group/begin
|
||||
uplevel source -encoding utf-8 $scriptsdir/$group/begin
|
||||
}
|
||||
if { [file exists $scriptsdir/$group/$gridname/begin] } {
|
||||
puts "Executing $scriptsdir/$group/$gridname/begin..."; flush stdout
|
||||
uplevel source $scriptsdir/$group/$gridname/begin
|
||||
uplevel source -encoding utf-8 $scriptsdir/$group/$gridname/begin
|
||||
}
|
||||
|
||||
puts "Executing $casefile..."; flush stdout
|
||||
uplevel source $casefile
|
||||
uplevel source -encoding utf-8 $casefile
|
||||
|
||||
if { [file exists $scriptsdir/$group/$gridname/end] } {
|
||||
puts "Executing $scriptsdir/$group/$gridname/end..."; flush stdout
|
||||
uplevel source $scriptsdir/$group/$gridname/end
|
||||
uplevel source -encoding utf-8 $scriptsdir/$group/$gridname/end
|
||||
}
|
||||
if { [file exists $scriptsdir/$group/end] } {
|
||||
puts "Executing $scriptsdir/$group/end..."; flush stdout
|
||||
uplevel source $scriptsdir/$group/end
|
||||
uplevel source -encoding utf-8 $scriptsdir/$group/end
|
||||
}
|
||||
} res] {
|
||||
puts "Tcl Exception: $res"
|
||||
|
@ -17,3 +17,4 @@ Font_SystemFont.cxx
|
||||
Font_SystemFont.hxx
|
||||
Font_TextFormatter.hxx
|
||||
Font_TextFormatter.cxx
|
||||
Font_UnicodeSubset.hxx
|
||||
|
@ -407,7 +407,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
{
|
||||
theShape.Nullify();
|
||||
if (!loadGlyph (theChar)
|
||||
|| myFTFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
|| myActiveFTFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
@ -416,8 +416,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
|
||||
return !theShape.IsNull();
|
||||
}
|
||||
|
||||
FT_Outline& anOutline = myFTFace->glyph->outline;
|
||||
|
||||
const FT_Outline& anOutline = myActiveFTFace->glyph->outline;
|
||||
if (!anOutline.n_contours)
|
||||
return Standard_False;
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
@ -33,9 +35,12 @@ IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
|
||||
Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
|
||||
: myFTLib (theFTLib),
|
||||
myFTFace (NULL),
|
||||
myActiveFTFace(NULL),
|
||||
myFontAspect (Font_FontAspect_Regular),
|
||||
myWidthScaling(1.0),
|
||||
myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
|
||||
myUChar (0U)
|
||||
myUChar (0U),
|
||||
myToUseUnicodeSubsetFallback (Font_FontMgr::ToUseUnicodeSubsetFallback())
|
||||
{
|
||||
if (myFTLib.IsNull())
|
||||
{
|
||||
@ -66,6 +71,7 @@ void Font_FTFont::Release()
|
||||
FT_Done_Face (myFTFace);
|
||||
myFTFace = NULL;
|
||||
}
|
||||
myActiveFTFace = NULL;
|
||||
myBuffer.Nullify();
|
||||
}
|
||||
|
||||
@ -135,6 +141,7 @@ bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
|
||||
|
||||
FT_Set_Transform (myFTFace, &aMat, 0);
|
||||
}
|
||||
myActiveFTFace = myFTFace;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -161,6 +168,7 @@ Handle(Font_FTFont) Font_FTFont::FindAndCreate (const TCollection_AsciiString& t
|
||||
Handle(Font_FTFont) aFont = new Font_FTFont();
|
||||
if (aFont->Init (aPath, aParams))
|
||||
{
|
||||
aFont->myFontAspect = aFontAspect;
|
||||
return aFont;
|
||||
}
|
||||
}
|
||||
@ -177,22 +185,61 @@ bool Font_FTFont::FindAndInit (const TCollection_AsciiString& theFontName,
|
||||
Font_StrictLevel theStrictLevel)
|
||||
{
|
||||
Font_FTFontParams aParams = theParams;
|
||||
Font_FontAspect aFontAspect = theFontAspect;
|
||||
myFontAspect = theFontAspect;
|
||||
Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
|
||||
if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName.ToCString(), theStrictLevel, aFontAspect))
|
||||
if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName.ToCString(), theStrictLevel, myFontAspect))
|
||||
{
|
||||
if (aRequestedFont->IsSingleStrokeFont())
|
||||
{
|
||||
aParams.IsSingleStrokeFont = true;
|
||||
}
|
||||
|
||||
const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
|
||||
const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic);
|
||||
return Init (aPath, aParams);
|
||||
}
|
||||
Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : findAndInitFallback
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Font_FTFont::findAndInitFallback (Font_UnicodeSubset theSubset)
|
||||
{
|
||||
if (!myFallbackFaces[theSubset].IsNull())
|
||||
{
|
||||
return myFallbackFaces[theSubset]->IsValid();
|
||||
}
|
||||
|
||||
myFallbackFaces[theSubset] = new Font_FTFont (myFTLib);
|
||||
myFallbackFaces[theSubset]->myToUseUnicodeSubsetFallback = false; // no recursion
|
||||
|
||||
Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
|
||||
if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFallbackFont (theSubset, myFontAspect))
|
||||
{
|
||||
Font_FTFontParams aParams = myFontParams;
|
||||
aParams.IsSingleStrokeFont = aRequestedFont->IsSingleStrokeFont();
|
||||
|
||||
const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic);
|
||||
if (myFallbackFaces[theSubset]->Init (aPath, aParams))
|
||||
{
|
||||
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Font_FTFont, using fallback font '") + aRequestedFont->FontName() + "'"
|
||||
+ " for symbols unsupported by '" + myFTFace->family_name + "'", Message_Trace);
|
||||
}
|
||||
}
|
||||
return myFallbackFaces[theSubset]->IsValid();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : HasSymbol
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Font_FTFont::HasSymbol (Standard_Utf32Char theUChar) const
|
||||
{
|
||||
return FT_Get_Char_Index (myFTFace, theUChar) != 0;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : loadGlyph
|
||||
// purpose :
|
||||
@ -206,9 +253,26 @@ bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
|
||||
|
||||
myGlyphImg.Clear();
|
||||
myUChar = 0;
|
||||
if (theUChar == 0
|
||||
|| FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
|
||||
|| myFTFace->glyph == NULL)
|
||||
myActiveFTFace = myFTFace;
|
||||
if (theUChar == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myToUseUnicodeSubsetFallback
|
||||
&& !HasSymbol (theUChar))
|
||||
{
|
||||
// try using fallback
|
||||
const Font_UnicodeSubset aSubset = CharSubset (theUChar);
|
||||
if (findAndInitFallback (aSubset)
|
||||
&& myFallbackFaces[aSubset]->HasSymbol (theUChar))
|
||||
{
|
||||
myActiveFTFace = myFallbackFaces[aSubset]->myFTFace;
|
||||
}
|
||||
}
|
||||
|
||||
if (FT_Load_Char (myActiveFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
|
||||
|| myActiveFTFace->glyph == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -225,26 +289,67 @@ bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
|
||||
{
|
||||
myGlyphImg.Clear();
|
||||
myUChar = 0;
|
||||
myActiveFTFace = myFTFace;
|
||||
|
||||
if (theUChar != 0
|
||||
&& myToUseUnicodeSubsetFallback
|
||||
&& !HasSymbol (theUChar))
|
||||
{
|
||||
// try using fallback
|
||||
const Font_UnicodeSubset aSubset = CharSubset (theUChar);
|
||||
if (findAndInitFallback (aSubset)
|
||||
&& myFallbackFaces[aSubset]->HasSymbol (theUChar))
|
||||
{
|
||||
myActiveFTFace = myFallbackFaces[aSubset]->myFTFace;
|
||||
}
|
||||
}
|
||||
|
||||
if (theUChar == 0
|
||||
|| FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
|
||||
|| myFTFace->glyph == NULL
|
||||
|| myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
||||
|| FT_Load_Char (myActiveFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
|
||||
|| myActiveFTFace->glyph == NULL
|
||||
|| myActiveFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
|
||||
if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
|
||||
|| aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
|
||||
FT_Bitmap aBitmap = myActiveFTFace->glyph->bitmap;
|
||||
if (aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
|
||||
aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
|
||||
|
||||
if (aBitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
|
||||
{
|
||||
if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
|
||||
aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
myGlyphImg.SetTopDown (aBitmap.pitch > 0);
|
||||
}
|
||||
else if (aBitmap.pixel_mode == FT_PIXEL_MODE_MONO)
|
||||
{
|
||||
if (!myGlyphImg.InitTrash (Image_Format_Gray, aBitmap.width, aBitmap.rows))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
myGlyphImg.SetTopDown (aBitmap.pitch > 0);
|
||||
const int aNumOfBytesInRow = aBitmap.width / 8 + (aBitmap.width % 8 ? 1 : 0);
|
||||
for (int aRow = 0; aRow < (int )aBitmap.rows; ++aRow)
|
||||
{
|
||||
for (int aCol = 0; aCol < (int )aBitmap.width; ++aCol)
|
||||
{
|
||||
const int aBitOn = aBitmap.buffer[aNumOfBytesInRow * aRow + aCol / 8] & (0x80 >> (aCol % 8));
|
||||
*myGlyphImg.ChangeRawValue (aRow, aCol) = aBitOn ? 255 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
myGlyphImg.SetTopDown (aBitmap.pitch > 0);
|
||||
|
||||
myUChar = theUChar;
|
||||
return true;
|
||||
}
|
||||
@ -253,24 +358,58 @@ bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
|
||||
// function : GlyphMaxSizeX
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
unsigned int Font_FTFont::GlyphMaxSizeX() const
|
||||
unsigned int Font_FTFont::GlyphMaxSizeX (bool theToIncludeFallback) const
|
||||
{
|
||||
float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
|
||||
? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
|
||||
: fromFTPoints<float> (myFTFace->size->metrics.max_advance);
|
||||
return (unsigned int)(aWidth + 0.5f);
|
||||
if (!theToIncludeFallback)
|
||||
{
|
||||
float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
|
||||
? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
|
||||
: fromFTPoints<float> (myFTFace->size->metrics.max_advance);
|
||||
return (unsigned int)(aWidth + 0.5f);
|
||||
}
|
||||
|
||||
unsigned int aWidth = GlyphMaxSizeX (false);
|
||||
if (theToIncludeFallback)
|
||||
{
|
||||
for (Standard_Integer aFontIter = 0; aFontIter < Font_UnicodeSubset_NB; ++aFontIter)
|
||||
{
|
||||
if (!myFallbackFaces[aFontIter].IsNull()
|
||||
&& myFallbackFaces[aFontIter]->IsValid())
|
||||
{
|
||||
aWidth = std::max (aWidth, myFallbackFaces[aFontIter]->GlyphMaxSizeX (false));
|
||||
}
|
||||
}
|
||||
}
|
||||
return aWidth;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : GlyphMaxSizeY
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
unsigned int Font_FTFont::GlyphMaxSizeY() const
|
||||
unsigned int Font_FTFont::GlyphMaxSizeY (bool theToIncludeFallback) const
|
||||
{
|
||||
float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
|
||||
? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
|
||||
: fromFTPoints<float> (myFTFace->size->metrics.height);
|
||||
return (unsigned int)(aHeight + 0.5f);
|
||||
if (!theToIncludeFallback)
|
||||
{
|
||||
float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
|
||||
? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
|
||||
: fromFTPoints<float> (myFTFace->size->metrics.height);
|
||||
return (unsigned int)(aHeight + 0.5f);
|
||||
}
|
||||
|
||||
unsigned int aHeight = GlyphMaxSizeY (false);
|
||||
if (theToIncludeFallback)
|
||||
{
|
||||
for (Standard_Integer aFontIter = 0; aFontIter < Font_UnicodeSubset_NB; ++aFontIter)
|
||||
{
|
||||
if (!myFallbackFaces[aFontIter].IsNull()
|
||||
&& myFallbackFaces[aFontIter]->IsValid())
|
||||
{
|
||||
aHeight = std::max (aHeight, myFallbackFaces[aFontIter]->GlyphMaxSizeY (false));
|
||||
}
|
||||
}
|
||||
}
|
||||
return aHeight;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -322,18 +461,22 @@ float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar,
|
||||
return AdvanceY (theUCharNext);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getKerning
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Font_FTFont::getKerning (FT_Vector& theKern,
|
||||
Standard_Utf32Char theUCharCurr,
|
||||
Standard_Utf32Char theUCharNext) const
|
||||
{
|
||||
theKern.x = 0;
|
||||
theKern.y = 0;
|
||||
if (theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0)
|
||||
if (theUCharNext != 0 && FT_HAS_KERNING(myActiveFTFace) != 0)
|
||||
{
|
||||
const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, theUCharCurr);
|
||||
const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
|
||||
const FT_UInt aCharCurr = FT_Get_Char_Index (myActiveFTFace, theUCharCurr);
|
||||
const FT_UInt aCharNext = FT_Get_Char_Index (myActiveFTFace, theUCharNext);
|
||||
if (aCharCurr == 0 || aCharNext == 0
|
||||
|| FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
|
||||
|| FT_Get_Kerning (myActiveFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
|
||||
{
|
||||
theKern.x = 0;
|
||||
theKern.y = 0;
|
||||
@ -357,7 +500,7 @@ float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const
|
||||
|
||||
FT_Vector aKern;
|
||||
getKerning (aKern, myUChar, theUCharNext);
|
||||
return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x);
|
||||
return myWidthScaling * fromFTPoints<float> (myActiveFTFace->glyph->advance.x + aKern.x);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@ -373,29 +516,41 @@ float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const
|
||||
|
||||
FT_Vector aKern;
|
||||
getKerning (aKern, myUChar, theUCharNext);
|
||||
return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y);
|
||||
return fromFTPoints<float> (myActiveFTFace->glyph->advance.y + aKern.y);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : GlyphsNumber
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Integer Font_FTFont::GlyphsNumber() const
|
||||
Standard_Integer Font_FTFont::GlyphsNumber (bool theToIncludeFallback) const
|
||||
{
|
||||
return myFTFace->num_glyphs;
|
||||
Standard_Integer aNbGlyphs = myFTFace->num_glyphs;
|
||||
if (theToIncludeFallback)
|
||||
{
|
||||
for (Standard_Integer aFontIter = 0; aFontIter < Font_UnicodeSubset_NB; ++aFontIter)
|
||||
{
|
||||
if (!myFallbackFaces[aFontIter].IsNull()
|
||||
&& myFallbackFaces[aFontIter]->IsValid())
|
||||
{
|
||||
aNbGlyphs += myFallbackFaces[aFontIter]->GlyphsNumber (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return aNbGlyphs;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : theRect
|
||||
// function : GlyphRect
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Font_FTFont::GlyphRect (Font_Rect& theRect) const
|
||||
{
|
||||
const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
|
||||
theRect.Left = float(myFTFace->glyph->bitmap_left);
|
||||
theRect.Top = float(myFTFace->glyph->bitmap_top);
|
||||
theRect.Right = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
|
||||
theRect.Bottom = float(myFTFace->glyph->bitmap_top - (int )aBitmap.rows);
|
||||
const FT_Bitmap& aBitmap = myActiveFTFace->glyph->bitmap;
|
||||
theRect.Left = float(myActiveFTFace->glyph->bitmap_left);
|
||||
theRect.Top = float(myActiveFTFace->glyph->bitmap_top);
|
||||
theRect.Right = float(myActiveFTFace->glyph->bitmap_left + (int )aBitmap.width);
|
||||
theRect.Bottom = float(myActiveFTFace->glyph->bitmap_top - (int )aBitmap.rows);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <Font_FontAspect.hxx>
|
||||
#include <Font_Rect.hxx>
|
||||
#include <Font_StrictLevel.hxx>
|
||||
#include <Font_UnicodeSubset.hxx>
|
||||
#include <Graphic3d_HorizontalTextAlignment.hxx>
|
||||
#include <Graphic3d_VerticalTextAlignment.hxx>
|
||||
#include <Image_PixMap.hxx>
|
||||
@ -33,10 +34,10 @@ class Font_FTLibrary;
|
||||
//! Font initialization parameters.
|
||||
struct Font_FTFontParams
|
||||
{
|
||||
unsigned int PointSize; //!< face size in points (1/72 inch)
|
||||
unsigned int Resolution; //!< resolution of the target device in dpi for FT_Set_Char_Size()
|
||||
bool ToSynthesizeItalic; //!< generate italic style (e.g. for font family having no italic style); FALSE by default
|
||||
bool IsSingleStrokeFont; //!< single-stroke (one-line) font, FALSE by default
|
||||
unsigned int PointSize; //!< face size in points (1/72 inch)
|
||||
unsigned int Resolution; //!< resolution of the target device in dpi for FT_Set_Char_Size()
|
||||
bool ToSynthesizeItalic; //!< generate italic style (e.g. for font family having no italic style); FALSE by default
|
||||
bool IsSingleStrokeFont; //!< single-stroke (one-line) font, FALSE by default
|
||||
|
||||
//! Empty constructor.
|
||||
Font_FTFontParams() : PointSize (0), Resolution (72u), ToSynthesizeItalic (false), IsSingleStrokeFont (false) {}
|
||||
@ -68,6 +69,69 @@ public:
|
||||
const Font_FTFontParams& theParams,
|
||||
const Font_StrictLevel theStrictLevel = Font_StrictLevel_Any);
|
||||
|
||||
//! Return TRUE if specified character is within subset of modern CJK characters.
|
||||
static bool IsCharFromCJK (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return (theUChar >= 0x03400 && theUChar <= 0x04DFF)
|
||||
|| (theUChar >= 0x04E00 && theUChar <= 0x09FFF)
|
||||
|| (theUChar >= 0x0F900 && theUChar <= 0x0FAFF)
|
||||
|| (theUChar >= 0x20000 && theUChar <= 0x2A6DF)
|
||||
|| (theUChar >= 0x2F800 && theUChar <= 0x2FA1F)
|
||||
// Hiragana and Katakana (Japanese) are NOT part of CJK, but CJK fonts usually include these symbols
|
||||
|| IsCharFromHiragana (theUChar)
|
||||
|| IsCharFromKatakana (theUChar);
|
||||
}
|
||||
|
||||
//! Return TRUE if specified character is within subset of Hiragana (Japanese).
|
||||
static bool IsCharFromHiragana (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return (theUChar >= 0x03040 && theUChar <= 0x0309F);
|
||||
}
|
||||
|
||||
//! Return TRUE if specified character is within subset of Katakana (Japanese).
|
||||
static bool IsCharFromKatakana (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return (theUChar >= 0x030A0 && theUChar <= 0x030FF);
|
||||
}
|
||||
|
||||
//! Return TRUE if specified character is within subset of modern Korean characters (Hangul).
|
||||
static bool IsCharFromKorean (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return (theUChar >= 0x01100 && theUChar <= 0x011FF)
|
||||
|| (theUChar >= 0x03130 && theUChar <= 0x0318F)
|
||||
|| (theUChar >= 0x0AC00 && theUChar <= 0x0D7A3);
|
||||
}
|
||||
|
||||
//! Return TRUE if specified character is within subset of Arabic characters.
|
||||
static bool IsCharFromArabic (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return (theUChar >= 0x00600 && theUChar <= 0x006FF);
|
||||
}
|
||||
|
||||
//! Return TRUE if specified character should be displayed in Right-to-Left order.
|
||||
static bool IsCharRightToLeft (Standard_Utf32Char theUChar)
|
||||
{
|
||||
return IsCharFromArabic(theUChar);
|
||||
}
|
||||
|
||||
//! Determine Unicode subset for specified character
|
||||
static Font_UnicodeSubset CharSubset (Standard_Utf32Char theUChar)
|
||||
{
|
||||
if (IsCharFromCJK (theUChar))
|
||||
{
|
||||
return Font_UnicodeSubset_CJK;
|
||||
}
|
||||
else if (IsCharFromKorean (theUChar))
|
||||
{
|
||||
return Font_UnicodeSubset_Korean;
|
||||
}
|
||||
else if (IsCharFromArabic (theUChar))
|
||||
{
|
||||
return Font_UnicodeSubset_Arabic;
|
||||
}
|
||||
return Font_UnicodeSubset_Western;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//! Create uninitialized instance.
|
||||
@ -119,6 +183,13 @@ public:
|
||||
const Font_FTFontParams& theParams,
|
||||
Font_StrictLevel theStrictLevel = Font_StrictLevel_Any);
|
||||
|
||||
//! Return flag to use fallback fonts in case if used font does not include symbols from specific Unicode subset; TRUE by default.
|
||||
//! @sa Font_FontMgr::ToUseUnicodeSubsetFallback()
|
||||
Standard_Boolean ToUseUnicodeSubsetFallback() const { return myToUseUnicodeSubsetFallback; }
|
||||
|
||||
//! Set if fallback fonts should be used in case if used font does not include symbols from specific Unicode subset.
|
||||
void SetUseUnicodeSubsetFallback (Standard_Boolean theToFallback) { myToUseUnicodeSubsetFallback = theToFallback; }
|
||||
|
||||
//! Return TRUE if this is single-stroke (one-line) font, FALSE by default.
|
||||
//! Such fonts define single-line glyphs instead of closed contours, so that they are rendered incorrectly by normal software.
|
||||
bool IsSingleStrokeFont() const { return myFontParams.IsSingleStrokeFont; }
|
||||
@ -136,10 +207,10 @@ public:
|
||||
Standard_EXPORT bool RenderGlyph (const Standard_Utf32Char theChar);
|
||||
|
||||
//! @return maximal glyph width in pixels (rendered to bitmap).
|
||||
Standard_EXPORT unsigned int GlyphMaxSizeX() const;
|
||||
Standard_EXPORT unsigned int GlyphMaxSizeX (bool theToIncludeFallback = false) const;
|
||||
|
||||
//! @return maximal glyph height in pixels (rendered to bitmap).
|
||||
Standard_EXPORT unsigned int GlyphMaxSizeY() const;
|
||||
Standard_EXPORT unsigned int GlyphMaxSizeY (bool theToIncludeFallback = false) const;
|
||||
|
||||
//! @return vertical distance from the horizontal baseline to the highest character coordinate.
|
||||
Standard_EXPORT float Ascender() const;
|
||||
@ -163,6 +234,9 @@ public:
|
||||
myWidthScaling = theScaleFactor;
|
||||
}
|
||||
|
||||
//! Return TRUE if font contains specified symbol (excluding fallback list).
|
||||
Standard_EXPORT bool HasSymbol (Standard_Utf32Char theUChar) const;
|
||||
|
||||
//! Compute horizontal advance to the next character with kerning applied when applicable.
|
||||
//! Assuming text rendered horizontally.
|
||||
//! @param theUCharNext the next character to compute advance from current one
|
||||
@ -187,8 +261,9 @@ public:
|
||||
Standard_EXPORT float AdvanceY (Standard_Utf32Char theUChar,
|
||||
Standard_Utf32Char theUCharNext);
|
||||
|
||||
//! @return glyphs number in this font.
|
||||
Standard_EXPORT Standard_Integer GlyphsNumber() const;
|
||||
//! Return glyphs number in this font.
|
||||
//! @param theToIncludeFallback if TRUE then the number will include fallback list
|
||||
Standard_EXPORT Standard_Integer GlyphsNumber (bool theToIncludeFallback = false) const;
|
||||
|
||||
//! Retrieve glyph bitmap rectangle
|
||||
Standard_EXPORT void GlyphRect (Font_Rect& theRect) const;
|
||||
@ -262,18 +337,25 @@ protected:
|
||||
Standard_Utf32Char theUCharCurr,
|
||||
Standard_Utf32Char theUCharNext) const;
|
||||
|
||||
//! Initialize fallback font.
|
||||
Standard_EXPORT bool findAndInitFallback (Font_UnicodeSubset theSubset);
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Font_FTLibrary) myFTLib; //!< handle to the FT library object
|
||||
Handle(NCollection_Buffer) myBuffer; //!< memory buffer
|
||||
Handle(Font_FTFont) myFallbackFaces[Font_UnicodeSubset_NB]; //!< fallback fonts
|
||||
FT_Face myFTFace; //!< FT face object
|
||||
FT_Face myActiveFTFace; //!< active FT face object (the main of fallback)
|
||||
TCollection_AsciiString myFontPath; //!< font path
|
||||
Font_FTFontParams myFontParams; //!< font initialization parameters
|
||||
Font_FontAspect myFontAspect; //!< font initialization aspect
|
||||
float myWidthScaling; //!< scale glyphs along X-axis
|
||||
int32_t myLoadFlags; //!< default load flags
|
||||
|
||||
Image_PixMap myGlyphImg; //!< cached glyph plane
|
||||
Standard_Utf32Char myUChar; //!< currently loaded unicode character
|
||||
Standard_Boolean myToUseUnicodeSubsetFallback; //!< use default fallback fonts for extended Unicode sub-sets (Korean, CJK, etc.)
|
||||
|
||||
};
|
||||
|
||||
|
@ -193,6 +193,16 @@ Handle(Font_FontMgr) Font_FontMgr::GetInstance()
|
||||
return _mgr;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ToUseUnicodeSubsetFallback
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Standard_Boolean& Font_FontMgr::ToUseUnicodeSubsetFallback()
|
||||
{
|
||||
static Standard_Boolean TheToUseUnicodeSubsetFallback = true;
|
||||
return TheToUseUnicodeSubsetFallback;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : addFontAlias
|
||||
// purpose :
|
||||
@ -239,6 +249,7 @@ Font_FontMgr::Font_FontMgr()
|
||||
Handle(Font_FontAliasSequence) anIris = new Font_FontAliasSequence();
|
||||
Handle(Font_FontAliasSequence) aCJK = new Font_FontAliasSequence();
|
||||
Handle(Font_FontAliasSequence) aKorean = new Font_FontAliasSequence();
|
||||
Handle(Font_FontAliasSequence) anArab = new Font_FontAliasSequence();
|
||||
|
||||
// best matches - pre-installed on Windows, some of them are pre-installed on macOS,
|
||||
// and sometimes them can be found installed on other systems (by user)
|
||||
@ -289,6 +300,15 @@ Font_FontMgr::Font_FontMgr()
|
||||
aKorean->Append (Font_FontAlias ("noto serif cjk jp")); // Linux
|
||||
aKorean->Append (Font_FontAlias ("noto sans cjk jp")); // Linux
|
||||
|
||||
#if defined(_WIN32)
|
||||
anArab->Append (Font_FontAlias ("times new roman"));
|
||||
#elif defined(__APPLE__)
|
||||
anArab->Append (Font_FontAlias ("decotype naskh"));
|
||||
#elif defined(__ANDROID__)
|
||||
anArab->Append (Font_FontAlias ("droid arabic naskh"));
|
||||
anArab->Append (Font_FontAlias ("noto naskh arabic"));
|
||||
#endif
|
||||
|
||||
addFontAlias ("mono", aMono);
|
||||
addFontAlias ("courier", aMono); // Font_NOF_ASCII_MONO
|
||||
addFontAlias ("monospace", aMono); // Font_NOF_MONOSPACE
|
||||
@ -308,6 +328,7 @@ Font_FontMgr::Font_FontMgr()
|
||||
addFontAlias ("korean", aKorean); // Font_NOF_KOREAN
|
||||
addFontAlias ("cjk", aCJK); // Font_NOF_CJK
|
||||
addFontAlias ("nsimsun", aCJK);
|
||||
addFontAlias ("arabic", anArab); // Font_NOF_ARABIC
|
||||
addFontAlias (Font_NOF_SYMBOL_MONO, aWinDin);
|
||||
addFontAlias (Font_NOF_ASCII_SCRIPT_SIMPLEX, aScript);
|
||||
|
||||
@ -686,6 +707,24 @@ Handle(Font_SystemFont) Font_FontMgr::GetFont (const TCollection_AsciiString& th
|
||||
return myFontMap.Find (theFontName);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FindFallbackFont
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Handle(Font_SystemFont) Font_FontMgr::FindFallbackFont (Font_UnicodeSubset theSubset,
|
||||
Font_FontAspect theFontAspect) const
|
||||
{
|
||||
Font_FontAspect aFontAspect = theFontAspect;
|
||||
switch (theSubset)
|
||||
{
|
||||
case Font_UnicodeSubset_Western: return FindFont (Font_NOF_SANS_SERIF, Font_StrictLevel_Aliases, aFontAspect);
|
||||
case Font_UnicodeSubset_Korean: return FindFont (Font_NOF_KOREAN, Font_StrictLevel_Aliases, aFontAspect);
|
||||
case Font_UnicodeSubset_CJK: return FindFont (Font_NOF_CJK, Font_StrictLevel_Aliases, aFontAspect);
|
||||
case Font_UnicodeSubset_Arabic: return FindFont (Font_NOF_ARABIC, Font_StrictLevel_Aliases, aFontAspect);
|
||||
}
|
||||
return Handle(Font_SystemFont)();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FindFont
|
||||
// purpose :
|
||||
@ -770,7 +809,8 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& t
|
||||
}
|
||||
}
|
||||
|
||||
if (aFont.IsNull())
|
||||
if (aFont.IsNull()
|
||||
&& theStrictLevel == Font_StrictLevel_Any)
|
||||
{
|
||||
// try finding ANY font in case if even default fallback alias myFallbackAlias cannot be found
|
||||
aFont = myFontMap.Find (TCollection_AsciiString());
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <Font_FontAspect.hxx>
|
||||
#include <Font_NListOfSystemFont.hxx>
|
||||
#include <Font_StrictLevel.hxx>
|
||||
#include <Font_UnicodeSubset.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_IndexedMap.hxx>
|
||||
#include <NCollection_Shared.hxx>
|
||||
@ -55,6 +56,9 @@ public:
|
||||
return "invalid";
|
||||
}
|
||||
|
||||
//! Return flag to use fallback fonts in case if used font does not include symbols from specific Unicode subset; TRUE by default.
|
||||
Standard_EXPORT static Standard_Boolean& ToUseUnicodeSubsetFallback();
|
||||
|
||||
public:
|
||||
|
||||
//! Return the list of available fonts.
|
||||
@ -106,7 +110,14 @@ public:
|
||||
{
|
||||
return FindFont (theFontName, Font_StrictLevel_Any, theFontAspect);
|
||||
}
|
||||
|
||||
|
||||
//! Tries to find fallback font for specified Unicode subset.
|
||||
//! Returns NULL in case when fallback font is not found in the system.
|
||||
//! @param theSubset [in] Unicode subset
|
||||
//! @param theFontAspect [in] font aspect to find
|
||||
Standard_EXPORT Handle(Font_SystemFont) FindFallbackFont (Font_UnicodeSubset theSubset,
|
||||
Font_FontAspect theFontAspect) const;
|
||||
|
||||
//! Read font file and retrieve information from it.
|
||||
Standard_EXPORT Handle(Font_SystemFont) CheckFont (const Standard_CString theFontPath) const;
|
||||
|
||||
|
@ -16,8 +16,9 @@
|
||||
#define Font_NOF_MONOSPACE "monospace"
|
||||
#define Font_NOF_SERIF "serif"
|
||||
#define Font_NOF_SANS_SERIF "sans-serif"
|
||||
#define Font_NOF_CJK "cjk"
|
||||
#define Font_NOF_KOREAN "korean"
|
||||
#define Font_NOF_CJK "cjk" // Font_UnicodeSubset_CJK
|
||||
#define Font_NOF_KOREAN "korean" // Font_UnicodeSubset_Korean
|
||||
#define Font_NOF_ARABIC "arabic" // Font_UnicodeSubset_Arabic
|
||||
|
||||
#define Font_NOF_ASCII_MONO "Courier"
|
||||
#define Font_NOF_ASCII_SIMPLEX "Times-Roman"
|
||||
|
28
src/Font/Font_UnicodeSubset.hxx
Normal file
28
src/Font/Font_UnicodeSubset.hxx
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2019 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Font_UnicodeSubset_HeaderFile
|
||||
#define _Font_UnicodeSubset_HeaderFile
|
||||
|
||||
//! Enumeration defining Unicode subsets.
|
||||
enum Font_UnicodeSubset
|
||||
{
|
||||
Font_UnicodeSubset_Western, //!< western letters
|
||||
Font_UnicodeSubset_Korean, //!< modern Korean letters
|
||||
Font_UnicodeSubset_CJK, //!< Chinese characters (Chinese, Japanese, Korean and Vietnam)
|
||||
Font_UnicodeSubset_Arabic, //!< Arabic characters
|
||||
};
|
||||
|
||||
enum { Font_UnicodeSubset_NB = Font_UnicodeSubset_Arabic };
|
||||
|
||||
#endif // _Font_UnicodeSubset_HeaderFile
|
@ -21,7 +21,6 @@
|
||||
#include <Standard_Assert.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Font,OpenGl_Resource)
|
||||
|
||||
// =======================================================================
|
||||
@ -34,8 +33,6 @@ OpenGl_Font::OpenGl_Font (const Handle(Font_FTFont)& theFont,
|
||||
myFont (theFont),
|
||||
myAscender (0.0f),
|
||||
myDescender (0.0f),
|
||||
myLineSpacing (0.0f),
|
||||
myTileSizeX (0),
|
||||
myTileSizeY (0),
|
||||
myLastTileId (-1),
|
||||
myTextureFormat (GL_ALPHA)
|
||||
@ -105,11 +102,9 @@ bool OpenGl_Font::Init (const Handle(OpenGl_Context)& theCtx)
|
||||
return false;
|
||||
}
|
||||
|
||||
myAscender = myFont->Ascender();
|
||||
myDescender = myFont->Descender();
|
||||
myLineSpacing = myFont->LineSpacing();
|
||||
myTileSizeX = myFont->GlyphMaxSizeX();
|
||||
myTileSizeY = myFont->GlyphMaxSizeY();
|
||||
myAscender = myFont->Ascender();
|
||||
myDescender = myFont->Descender();
|
||||
myTileSizeY = myFont->GlyphMaxSizeY (true);
|
||||
|
||||
myLastTileId = -1;
|
||||
if (!createTexture (theCtx))
|
||||
@ -126,12 +121,16 @@ bool OpenGl_Font::Init (const Handle(OpenGl_Context)& theCtx)
|
||||
// =======================================================================
|
||||
bool OpenGl_Font::createTexture (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
const Standard_Integer aMaxSize = theCtx->MaxTextureSize();
|
||||
// Single font might define very wide range of symbols, with very few of them actually used in text.
|
||||
// Limit single texture with circa 4096 glyphs.
|
||||
static const Standard_Integer THE_MAX_GLYPHS_PER_TEXTURE = 4096;
|
||||
|
||||
Standard_Integer aGlyphsNb = myFont->GlyphsNumber() - myLastTileId + 1;
|
||||
|
||||
const Standard_Integer aTextureSizeX = OpenGl_Context::GetPowerOfTwo (aGlyphsNb * myTileSizeX, aMaxSize);
|
||||
const Standard_Integer aTilesPerRow = aTextureSizeX / myTileSizeX;
|
||||
myTileSizeY = myFont->GlyphMaxSizeY (true);
|
||||
const Standard_Integer aGlyphsNb = Min (THE_MAX_GLYPHS_PER_TEXTURE, myFont->GlyphsNumber (true) - myLastTileId + 1);
|
||||
const Standard_Integer aMaxTileSizeX = myFont->GlyphMaxSizeX (true);
|
||||
const Standard_Integer aMaxSize = theCtx->MaxTextureSize();
|
||||
const Standard_Integer aTextureSizeX = OpenGl_Context::GetPowerOfTwo (aGlyphsNb * aMaxTileSizeX, aMaxSize);
|
||||
const Standard_Integer aTilesPerRow = aTextureSizeX / aMaxTileSizeX;
|
||||
const Standard_Integer aTextureSizeY = OpenGl_Context::GetPowerOfTwo (GLint((aGlyphsNb / aTilesPerRow) + 1) * myTileSizeY, aMaxSize);
|
||||
|
||||
memset (&myLastTilePx, 0, sizeof(myLastTilePx));
|
||||
@ -186,14 +185,18 @@ bool OpenGl_Font::renderGlyph (const Handle(OpenGl_Context)& theCtx,
|
||||
const Standard_Integer aTileId = myLastTileId + 1;
|
||||
myLastTilePx.Left = myLastTilePx.Right + 3;
|
||||
myLastTilePx.Right = myLastTilePx.Left + (Standard_Integer )anImg.SizeX();
|
||||
if (myLastTilePx.Right >= aTexture->SizeX())
|
||||
if (myLastTilePx.Right > aTexture->SizeX()
|
||||
|| (Standard_Integer )anImg.SizeY() > myTileSizeY)
|
||||
{
|
||||
myTileSizeY = myFont->GlyphMaxSizeY (true);
|
||||
|
||||
myLastTilePx.Left = 0;
|
||||
myLastTilePx.Right = (Standard_Integer )anImg.SizeX();
|
||||
myLastTilePx.Top += myTileSizeY;
|
||||
myLastTilePx.Bottom += myTileSizeY;
|
||||
|
||||
if (myLastTilePx.Bottom >= aTexture->SizeY())
|
||||
if (myLastTilePx.Bottom > aTexture->SizeY()
|
||||
|| myLastTilePx.Right > aTexture->SizeX())
|
||||
{
|
||||
if (!createTexture (theCtx))
|
||||
{
|
||||
|
@ -106,12 +106,6 @@ public:
|
||||
return myDescender;
|
||||
}
|
||||
|
||||
//! @return default line spacing (the baseline-to-baseline distance)
|
||||
inline float LineSpacing() const
|
||||
{
|
||||
return myLineSpacing;
|
||||
}
|
||||
|
||||
//! Render glyph to texture if not already.
|
||||
//! @param theCtx active context
|
||||
//! @param theUChar unicode symbol to render
|
||||
@ -135,8 +129,6 @@ protected:
|
||||
Handle(Font_FTFont) myFont; //!< FreeType font instance
|
||||
Standard_ShortReal myAscender; //!< ascender provided my FT font
|
||||
Standard_ShortReal myDescender; //!< descender provided my FT font
|
||||
Standard_ShortReal myLineSpacing; //!< line spacing provided my FT font
|
||||
Standard_Integer myTileSizeX; //!< tile width
|
||||
Standard_Integer myTileSizeY; //!< tile height
|
||||
Standard_Integer myLastTileId; //!< id of last tile
|
||||
RectI myLastTilePx;
|
||||
|
@ -5598,6 +5598,18 @@ static int VFont (Draw_Interpretor& theDI,
|
||||
}
|
||||
aMgr->SetTraceAliases (toEnable);
|
||||
}
|
||||
else if (anArgCase == "-unicodefallback"
|
||||
|| anArgCase == "-fallback"
|
||||
|| anArgCase == "-touseunicodesubsetfallback")
|
||||
{
|
||||
bool toEnable = true;
|
||||
if (anArgIter + 1 < theArgNb
|
||||
&& ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
|
||||
{
|
||||
++anArgIter;
|
||||
}
|
||||
Font_FontMgr::ToUseUnicodeSubsetFallback() = toEnable;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Warning! Unknown argument '" << anArg << "'\n";
|
||||
@ -6541,7 +6553,8 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
|
||||
__FILE__, TextToBRep, group);
|
||||
theCommands.Add ("vfont",
|
||||
"vfont [-add pathToFont [fontName] [regular,bold,italic,boldItalic=undefined] [singleStroke]]"
|
||||
"\n\t\t: [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]",
|
||||
"\n\t\t: [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]"
|
||||
"\n\t\t: [-unicodeFallback {on|off}]",
|
||||
__FILE__, VFont, group);
|
||||
|
||||
theCommands.Add ("vvertexmode",
|
||||
|
37
tests/3rdparty/fonts/C2
vendored
Normal file
37
tests/3rdparty/fonts/C2
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
puts "================"
|
||||
puts "0022149: Strings with Japanese characters can not be displayed in 3D viewer"
|
||||
puts "================"
|
||||
puts ""
|
||||
|
||||
pload MODELING VISUALIZATION
|
||||
|
||||
dtracelevel trace
|
||||
vfont -verbose 1
|
||||
vclear
|
||||
vinit View1
|
||||
vaxo
|
||||
vpoint p0 0 0 0
|
||||
|
||||
pload MODELING VISUALIZATION
|
||||
dtracelevel trace
|
||||
vfont -verbose 1
|
||||
vclear
|
||||
vinit View1
|
||||
vtop
|
||||
vpoint p00 0 0 0
|
||||
vpoint p01 0 10 0
|
||||
vpoint p11 10 10 0
|
||||
vpoint p10 10 0 0
|
||||
vfit
|
||||
vzoom 0.8
|
||||
vdrawtext t0 "한국어 (Korean) Čeština" -pos 0 0 0 -halign left -font korean
|
||||
vdrawtext t1 "한국어 (Korean) Čeština" -pos 10 1 0 -halign right -font sans
|
||||
vdrawtext t2 "简体中文 (Chinese)" -pos 0 2 0 -halign left -font cjk
|
||||
vdrawtext t3 "简体中文 (Chinese)" -pos 10 3 0 -halign right -font sans
|
||||
vdrawtext t4 "あ (Japanese)" -pos 0 4 0 -halign left -font cjk
|
||||
vdrawtext t5 "あ (Japanese)" -pos 10 5 0 -halign right -font sans
|
||||
|
||||
vdump $imagedir/${casename}.png
|
||||
|
||||
# just print font list
|
||||
vfont
|
Loading…
x
Reference in New Issue
Block a user