CWS-TOOLING: integrate CWS graphite03_OOO330

This commit is contained in:
Jens-Heiner Rechtien 2010-07-22 13:49:22 +02:00
commit 06d8dc602f
9 changed files with 138 additions and 62 deletions

View file

@ -86,8 +86,8 @@ namespace grutils
//
class VCL_DLLPUBLIC GraphiteFontAdaptor : public gr::Font
{
typedef std::map<const gr::gid16, std::pair<gr::Rect, gr::Point> > GlyphMetricMap;
typedef std::map<const gr::gid16, std::pair<gr::Rect, gr::Point> > GlyphMetricMap;
friend class GrFontHasher;
public:
static bool IsGraphiteEnabledFont(ServerFont &) throw();

View file

@ -105,15 +105,16 @@ typedef std::pair<GraphiteRopeMap::iterator, GraphiteRopeMap::iterator> GrRMEntr
*/
class GraphiteSegmentCache
{
public:
enum {
// not really sure what good values are here,
// bucket size should be >> cache size
SEG_BUCKET_SIZE = 4096,
SEG_CACHE_SIZE = 255
SEG_BUCKET_FACTOR = 4,
SEG_DEFAULT_CACHE_SIZE = 2047
};
public:
GraphiteSegmentCache()
: m_segMap(SEG_BUCKET_SIZE),
GraphiteSegmentCache(sal_uInt32 nSegCacheSize)
: m_segMap(nSegCacheSize * SEG_BUCKET_FACTOR),
m_nSegCacheSize(nSegCacheSize),
m_oldestKey(NULL) {};
~GraphiteSegmentCache()
{
@ -224,6 +225,7 @@ public:
private:
GraphiteSegMap m_segMap;
GraphiteRopeMap m_ropeMap;
sal_uInt32 m_nSegCacheSize;
const xub_Unicode * m_oldestKey;
const xub_Unicode * m_prevKey;
};
@ -236,7 +238,24 @@ typedef std::hash_map<int, GraphiteSegmentCache *, std::hash<int> > GraphiteCach
class GraphiteCacheHandler
{
public:
GraphiteCacheHandler() : m_cacheMap(255) {};
GraphiteCacheHandler() : m_cacheMap(255)
{
const char * pEnvCache = getenv( "SAL_GRAPHITE_CACHE_SIZE" );
if (pEnvCache != NULL)
{
int envCacheSize = atoi(pEnvCache);
if (envCacheSize <= 0)
m_nSegCacheSize = GraphiteSegmentCache::SEG_DEFAULT_CACHE_SIZE;
else
{
m_nSegCacheSize = envCacheSize;
}
}
else
{
m_nSegCacheSize = GraphiteSegmentCache::SEG_DEFAULT_CACHE_SIZE;
}
};
~GraphiteCacheHandler()
{
GraphiteCacheMap::iterator i = m_cacheMap.begin();
@ -257,12 +276,13 @@ public:
{
return m_cacheMap.find(fontHash)->second;
}
GraphiteSegmentCache *pCache = new GraphiteSegmentCache();
GraphiteSegmentCache *pCache = new GraphiteSegmentCache(m_nSegCacheSize);
m_cacheMap[fontHash] = pCache;
return pCache;
}
private:
GraphiteCacheMap m_cacheMap;
sal_uInt32 m_nSegCacheSize;
};
#endif

View file

@ -65,6 +65,19 @@ class GraphiteFontAdaptor;
class GrSegRecord;
// SAL/VCL types
class ServerFont;
#ifdef WNT
// The GraphiteWinFont is just a wrapper to enable GrFontHasher to be a friend
// so that UniqueCacheInfo can be called.
#include <graphite/WinFont.h>
class GraphiteWinFont : public gr::WinFont
{
friend class GrFontHasher;
public:
GraphiteWinFont(HDC hdc) : gr::WinFont(hdc) {};
virtual ~GraphiteWinFont() {};
};
#endif
// Graphite types
namespace gr { class Segment; class GlyphIterator; }
namespace grutils { class GrFeatureParser; }
@ -98,7 +111,7 @@ public:
iterator_pair_t neighbour_clusters(const_iterator) const;
private:
std::pair<float,float> appendCluster(gr::Segment & rSeg, ImplLayoutArgs & rArgs,
bool bRtl, int nFirstCharInCluster, int nNextChar,
bool bRtl, float fSegmentAdvance, int nFirstCharInCluster, int nNextChar,
int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
std::vector<int> & rCharDxs, long & rDXOffset);

View file

@ -99,12 +99,18 @@ FontProperties::FontProperties(const FreetypeServerFont &font) throw()
fItalic = false;
}
// Get the font name.
// Get the font name, but prefix with file name hash in case
// there are 2 fonts on the system with the same face name
sal_Int32 nHashCode = font.GetFontFileName()->hashCode();
::rtl::OUStringBuffer nHashFaceName;
nHashFaceName.append(nHashCode, 16);
const sal_Unicode * name = font.GetFontSelData().maName.GetBuffer();
const size_t name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1,
size_t(font.GetFontSelData().maName.Len()));
nHashFaceName.append(name);
std::copy(name, name + name_sz, szFaceName);
const size_t name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1,
static_cast<size_t>(nHashFaceName.getLength()));
std::copy(nHashFaceName.getStr(), nHashFaceName.getStr() + name_sz, szFaceName);
szFaceName[name_sz] = '\0';
}
@ -120,13 +126,13 @@ GraphiteFontAdaptor::GraphiteFontAdaptor(ServerFont & sfont, const sal_Int32 dpi
mfEmUnits(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().y_ppem),
mpFeatures(NULL)
{
//std::wstring face_name(maFontProperties.szFaceName);
const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( sfont.GetFontSelData().meLanguage );
#ifdef DEBUG
printf("GraphiteFontAdaptor %lx\n", (long)this);
#endif
rtl::OString name = rtl::OUStringToOString(
sfont.GetFontSelData().maTargetName, RTL_TEXTENCODING_UTF8 );
#ifdef DEBUG
printf("GraphiteFontAdaptor %lx %s italic=%u bold=%u\n", (long)this, name.getStr(),
maFontProperties.fItalic, maFontProperties.fBold);
#endif
sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
if (nFeat > 0)
{
@ -259,21 +265,24 @@ const void * GraphiteFontAdaptor::getTable(gr::fontTableId32 table_id, size_t *
// Return the glyph's metrics in pixels.
void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBounding, gr::Point & advances)
{
// Graphite gets really confused if the glyphs have been transformed, so
// if orientation has been set we can't use the font's glyph cache
// unfortunately the font selection data, doesn't always have the orientation
// set, even if it was when the glyphs were cached, so we use our own cache.
// There used to be problems when orientation was set however, this no
// longer seems to be the case and the Glyph Metric cache in
// FreetypeServerFont is more efficient since it lasts between calls to VCL
#if 1
const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId);
// const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId);
//
// aBounding.right = aBounding.left = metric.GetOffset().X();
// aBounding.bottom = aBounding.top = -metric.GetOffset().Y();
// aBounding.right += metric.GetSize().Width();
// aBounding.bottom -= metric.GetSize().Height();
//
// advances.x = metric.GetDelta().X();
// advances.y = -metric.GetDelta().Y();
aBounding.right = aBounding.left = metric.GetOffset().X();
aBounding.bottom = aBounding.top = -metric.GetOffset().Y();
aBounding.right += metric.GetSize().Width();
aBounding.bottom -= metric.GetSize().Height();
advances.x = metric.GetDelta().X();
advances.y = -metric.GetDelta().Y();
#else
// The problem with the code below is that the cache only lasts
// as long as the life time of the GraphiteFontAdaptor, which
// is created once per call to X11SalGraphics::GetTextLayout
GlyphMetricMap::const_iterator gm_itr = maGlyphMetricMap.find(nGlyphId);
if (gm_itr != maGlyphMetricMap.end())
{
@ -321,6 +330,7 @@ void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBoundi
// Now add an entry to our metrics map.
maGlyphMetricMap[nGlyphId] = std::make_pair(aBounding, advances);
}
#endif
}
#endif

View file

@ -105,7 +105,7 @@ GrSegRecord * GraphiteSegmentCache::cacheSegment(TextSourceAdaptor * adapter, gr
// when the next key is added, the record for the prevKey's m_nextKey field
// is updated to the newest key so that m_oldestKey can be updated to the
// next oldest key when the record for m_oldestKey is deleted
if (m_segMap.size() > SEG_CACHE_SIZE)
if (m_segMap.size() > m_nSegCacheSize)
{
GraphiteSegMap::iterator oldestPair = m_segMap.find(reinterpret_cast<long>(m_oldestKey));
// oldest record may no longer exist if a buffer was changed

View file

@ -56,6 +56,10 @@
#include <svsys.h>
#endif
#ifdef UNX
#include <vcl/graphite_adaptors.hxx>
#endif
#include <vcl/salgdi.hxx>
#include <unicode/uchar.h>
@ -175,7 +179,8 @@ GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
glyph_range_t iGlyphs = rSegment.glyphs();
int nGlyphs = iGlyphs.second - iGlyphs.first;
gr::GlyphIterator prevBase = iGlyphs.second;
float fMinX = rSegment.advanceWidth();
float fSegmentAdvance = rSegment.advanceWidth();
float fMinX = fSegmentAdvance;
float fMaxX = 0.0f;
rGlyph2Char.assign(nGlyphs, -1);
long nDxOffset = 0;
@ -222,7 +227,8 @@ GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
nFirstGlyphInCluster != nGlyphIndex)
{
std::pair <float,float> aBounds =
appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster,
appendCluster(rSegment, rArgs, bRtl,
fSegmentAdvance, nFirstCharInCluster,
nNextChar, nFirstGlyphInCluster, nGlyphIndex, fScaling,
rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
fMinX = std::min(aBounds.first, fMinX);
@ -285,7 +291,8 @@ GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
nFirstGlyphInCluster != nGlyphIndex)
{
std::pair <float,float> aBounds =
appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster, nNextChar,
appendCluster(rSegment, rArgs, bRtl, fSegmentAdvance,
nFirstCharInCluster, nNextChar,
nFirstGlyphInCluster, nGlyphIndex, fScaling,
rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
fMinX = std::min(aBounds.first, fMinX);
@ -334,11 +341,11 @@ GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
}
}
std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
ImplLayoutArgs & rArgs, bool bRtl, int nFirstCharInCluster, int nNextChar,
int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
std::vector<int> & rCharDxs, long & rDXOffset)
std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment& rSeg,
ImplLayoutArgs & rArgs, bool bRtl,float fSegmentAdvance,
int nFirstCharInCluster, int nNextChar, int nFirstGlyphInCluster,
int nNextGlyph, float fScaling, std::vector<int> & rChar2Base,
std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs, long & rDXOffset)
{
glyph_range_t iGlyphs = rSeg.glyphs();
int nGlyphs = iGlyphs.second - iGlyphs.first;
@ -402,9 +409,9 @@ std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
gr::GlyphInfo aGlyph = *(iGlyphs.first + j);
if (j + nDelta >= nGlyphs || j + nDelta < 0) // at rhs ltr,rtl
{
fNextOrigin = rSeg.advanceWidth();
nNextOrigin = round(rSeg.advanceWidth() * fScaling + rDXOffset);
aBounds.second = std::max(rSeg.advanceWidth(), aBounds.second);
fNextOrigin = fSegmentAdvance;
nNextOrigin = round(fSegmentAdvance * fScaling + rDXOffset);
aBounds.second = std::max(fSegmentAdvance, aBounds.second);
}
else
{
@ -546,7 +553,7 @@ GraphiteLayout::GraphiteLayout(const gr::Font & font, const grutils::GrFeaturePa
// If true, it can cause end of line spaces to be hidden e.g. Doulos SIL
maLayout.setStartOfLine(false);
maLayout.setEndOfLine(false);
// maLayout.setDumbFallback(false);
maLayout.setDumbFallback(true);
// trailing ws doesn't seem to always take affect if end of line is true
maLayout.setTrailingWs(gr::ktwshAll);
#ifdef GRLAYOUT_DEBUG
@ -598,6 +605,8 @@ bool GraphiteLayout::LayoutText(ImplLayoutArgs & rArgs)
else delete pSegment;
#else
gr::Segment * pSegment = CreateSegment(rArgs);
if (!pSegment)
return false;
bool success = LayoutGlyphs(rArgs, pSegment);
delete pSegment;
#endif
@ -649,7 +658,19 @@ public:
#endif
return hash;
};
protected:
virtual void UniqueCacheInfo(std::wstring & stuFace, bool & fBold, bool & fItalic)
{
#ifdef WIN32
dynamic_cast<GraphiteWinFont&>(mrRealFont).UniqueCacheInfo(stuFace, fBold, fItalic);
#else
#ifdef UNX
dynamic_cast<GraphiteFontAdaptor&>(mrRealFont).UniqueCacheInfo(stuFace, fBold, fItalic);
#else
#error Unknown base type for gr::Font::UniqueCacheInfo
#endif
#endif
}
private:
gr::Font & mrRealFont;
};
@ -738,6 +759,14 @@ gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
}
else
{
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(), "Gr::LayoutText failed: ");
for (int i = mnMinCharPos; i < limit; i++)
{
fprintf(grLog(), "%04x ", rArgs.mpStr[i]);
}
fprintf(grLog(), "\n");
#endif
clear();
return NULL;
}
@ -897,7 +926,7 @@ long GraphiteLayout::FillDXArray( sal_Int32* pDXArray ) const
if (i > 0) pDXArray[i] -= mvCharDxs[i-1];
}
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(),"%d,%d,%ld ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
fprintf(grLog(),"%d,%d,%d ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
#endif
}
//std::adjacent_difference(mvCharDxs.begin(), mvCharDxs.end(), pDXArray);
@ -1020,7 +1049,7 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
#ifdef GRLAYOUT_DEBUG
for (size_t iDx = 0; iDx < mvCharDxs.size(); iDx++)
fprintf(grLog(),"%d,%d,%ld ", (int)iDx, (int)mvCharDxs[iDx], args.mpDXArray[iDx]);
fprintf(grLog(),"%d,%d,%d ", (int)iDx, (int)mvCharDxs[iDx], args.mpDXArray[iDx]);
fprintf(grLog(),"ApplyDx\n");
#endif
bool bRtl = mnLayoutFlags & SAL_LAYOUT_BIDI_RTL;
@ -1090,7 +1119,7 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
}
long nDWidth = nNewClusterWidth - nOrigClusterWidth;
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(), "c%d last glyph %d/%d\n", i, nLastGlyph, mvGlyphs.size());
fprintf(grLog(), "c%lu last glyph %d/%lu\n", i, nLastGlyph, mvGlyphs.size());
#endif
assert((nLastGlyph > -1) && (nLastGlyph < (signed)mvGlyphs.size()));
mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
@ -1128,7 +1157,7 @@ void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDelt
std::copy(args.mpDXArray, args.mpDXArray + nChars,
mvCharDxs.begin() + (args.mnMinCharPos - mnMinCharPos));
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(),"ApplyDx %ld(%ld)\n", args.mpDXArray[nChars - 1], mnWidth);
fprintf(grLog(),"ApplyDx %d(%ld)\n", args.mpDXArray[nChars - 1], mnWidth);
#endif
mnWidth = args.mpDXArray[nChars - 1];
}
@ -1170,7 +1199,7 @@ void GraphiteLayout::kashidaJustify(std::vector<int>& rDeltaWidths, sal_GlyphId
}
nKashidaCount = 1 + (nGapWidth / nKashidaWidth);
#ifdef GRLAYOUT_DEBUG
printf("inserting %d kashidas at %ld\n", nKashidaCount, (*i).mnGlyphIndex);
printf("inserting %d kashidas at %u\n", nKashidaCount, (*i).mnGlyphIndex);
#endif
GlyphItem glyphItem = *i;
Point aPos(0, 0);
@ -1309,7 +1338,7 @@ void GraphiteLayout::GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray
pCaretXArray[i] = pCaretXArray[i+1] = 0;
}
#ifdef GRLAYOUT_DEBUG
fprintf(grLog(),"%d,%ld-%ld\t", nCharSlot, pCaretXArray[i], pCaretXArray[i+1]);
fprintf(grLog(),"%d,%d-%d\t", nCharSlot, pCaretXArray[i], pCaretXArray[i+1]);
#endif
}
#ifdef GRLAYOUT_DEBUG

View file

@ -93,6 +93,7 @@ public:
virtual ext_std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich);
virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset);
virtual bool sameSegment(gr::toffset ich1, gr::toffset ich2);
virtual bool featureVariations() { return false; }
operator ImplLayoutArgs & () throw();
void setFeatures(const grutils::GrFeatureParser * pFeatures);

View file

@ -854,19 +854,22 @@ bool PrintFontManager::addFontconfigDir( const rtl::OString& rDirName )
fprintf( stderr, "FcConfigAppFontAddDir( \"%s\") => %d\n", pDirName, bDirOk );
#endif
if( bDirOk )
{
const rtl::OString aConfFileName = rDirName + "/fc_local.conf";
bool bCfgOk = rWrapper.FcConfigParseAndLoad( rWrapper.FcConfigGetCurrent(),
(FcChar8*)aConfFileName.getStr(), FcTrue );
(void)bCfgOk; // silence compiler warning
if( !bDirOk )
return false;
#if OSL_DEBUG_LEVEL > 1
fprintf( stderr, "FcConfigParseAndLoad( \"%s\") => %d\n", aConfFileName.getStr(), bCfgOk );
#endif
// load dir-specific fc-config file too if available
const rtl::OString aConfFileName = rDirName + "/fc_local.conf";
FILE* pCfgFile = fopen( aConfFileName.getStr(), "rb" );
if( pCfgFile )
{
fclose( pCfgFile);
bool bCfgOk = rWrapper.FcConfigParseAndLoad( rWrapper.FcConfigGetCurrent(),
(FcChar8*)aConfFileName.getStr(), FcTrue );
if( !bCfgOk )
fprintf( stderr, "FcConfigParseAndLoad( \"%s\") => %d\n", aConfFileName.getStr(), bCfgOk );
}
return bDirOk;
return true;
}
static void addtopattern(FontCfgWrapper& rWrapper, FcPattern *pPattern,

2
vcl/win/source/gdi/winlayout.cxx Normal file → Executable file
View file

@ -2821,7 +2821,7 @@ sal_GlyphId GraphiteLayoutWinImpl::getKashidaGlyph(int & rWidth)
class GraphiteWinLayout : public WinLayout
{
private:
mutable gr::WinFont mpFont;
mutable GraphiteWinFont mpFont;
grutils::GrFeatureParser * mpFeatures;
mutable GraphiteLayoutWinImpl maImpl;
public: