* qt_helpers.h:

- ucs4_to_qchar(): add a FIXME and an assertion

* GuiFontMetrics: replace the table based cache with two QHash based cache. With this change, the speed overhead is not negligible (exact same score with the UserGuide test) and the required additional memory is minimal (maybe one or two megabytes).


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@16132 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2006-12-02 15:54:49 +00:00
parent b2e5732971
commit 591d47a64b
3 changed files with 30 additions and 59 deletions

View File

@ -24,22 +24,9 @@ using std::string;
namespace lyx { namespace lyx {
namespace frontend { namespace frontend {
namespace {
// Used for checking initialisation state of the C-ish metrics table.
const short int BadMetrics = -1000;
}
GuiFontMetrics::GuiFontMetrics(QFont const & font) GuiFontMetrics::GuiFontMetrics(QFont const & font)
: metrics_(font), smallcaps_metrics_(font), smallcaps_shape_(false) : metrics_(font), smallcaps_metrics_(font), smallcaps_shape_(false)
{ {
#ifdef USE_LYX_FONTCACHE
for (size_t i = 0; i != MaxCharType; ++i) {
metrics_cache_[i].width = BadMetrics;
metrics_cache_[i].ascent = BadMetrics;
metrics_cache_[i].descent = BadMetrics;
}
#endif
} }
@ -185,61 +172,41 @@ int GuiFontMetrics::descent(char_type c) const
#else #else
void GuiFontMetrics::fillCache(unsigned short val) const void GuiFontMetrics::fillMetricsCache(char_type c) const
{ {
QRect const & r = metrics_.boundingRect(QChar(val)); QRect const & r = metrics_.boundingRect(ucs4_to_qchar(c));
metrics_cache_[val].descent = static_cast<short>(r.bottom() + 1); AscendDescend ad = { -r.top(), r.bottom() + 1};
metrics_cache_[val].ascent = static_cast<short>(-r.top());
// We could as well compute the width but this is not really // We could as well compute the width but this is not really
// needed for now as it is done directly in width() below. // needed for now as it is done directly in width() below.
//metrics_cache_[val].width = metrics_.width(QChar(val)); metrics_cache_.insert(c, ad);
} }
int GuiFontMetrics::width(char_type c) const int GuiFontMetrics::width(char_type c) const
{ {
// FIXME: The following cast is not a real conversion but it work if (!width_cache_.contains(c)) {
// for the ucs2 subrange of unicode. Instead of an assertion we should width_cache_.insert(c, metrics_.width(ucs4_to_qchar(c)));
// give the metrics of some special characters that indicates that
// its display is not supported.
BOOST_ASSERT(c < MaxCharType);
unsigned short val = static_cast<unsigned short>(c);
if (metrics_cache_[val].width == BadMetrics) {
metrics_cache_[val].width
= static_cast<short>(metrics_.width(QChar(val)));
} }
return metrics_cache_[val].width; return width_cache_.value(c);
} }
int GuiFontMetrics::ascent(char_type c) const int GuiFontMetrics::ascent(char_type c) const
{ {
// FIXME: The following cast is not a real conversion but it work if (!metrics_cache_.contains(c))
// for the ucs2 subrange of unicode. Instead of an assertion we should fillMetricsCache(c);
// give the metrics of some special characters that indicates that
// its display is not supported.
BOOST_ASSERT(c < MaxCharType);
unsigned short val = static_cast<unsigned short>(c);
if (metrics_cache_[val].ascent == BadMetrics)
fillCache(val);
return metrics_cache_[val].ascent; return metrics_cache_.value(c).ascent;
} }
int GuiFontMetrics::descent(char_type c) const int GuiFontMetrics::descent(char_type c) const
{ {
// FIXME: The following cast is not a real conversion but it work if (!metrics_cache_.contains(c))
// for the ucs2 subrange of unicode. Instead of an assertion we should fillMetricsCache(c);
// give the metrics of some special characters that indicates that
// its display is not supported.
BOOST_ASSERT(c < MaxCharType);
unsigned short val = static_cast<unsigned short>(c);
if (metrics_cache_[val].descent == BadMetrics)
fillCache(val);
return metrics_cache_[val].descent; return metrics_cache_.value(c).descent;
} }
#endif #endif

View File

@ -17,6 +17,7 @@
#include "support/docstring.h" #include "support/docstring.h"
#include <QFontMetrics> #include <QFontMetrics>
#include <QHash>
// Starting with version 3.1.0, Qt/X11 does its own caching of // Starting with version 3.1.0, Qt/X11 does its own caching of
// character width, so it is not necessary to provide ours. // character width, so it is not necessary to provide ours.
@ -27,16 +28,6 @@
namespace lyx { namespace lyx {
namespace frontend { namespace frontend {
size_t const MaxCharType = 65536;
struct CharMetrics
{
short int width;
short int ascent;
short int descent;
};
class GuiFontMetrics: public FontMetrics class GuiFontMetrics: public FontMetrics
{ {
public: public:
@ -82,15 +73,23 @@ private:
bool smallcaps_shape_; bool smallcaps_shape_;
#ifdef USE_LYX_FONTCACHE #ifdef USE_LYX_FONTCACHE
/// fill in \c metrics_cache_ at specified value.
void fillCache(unsigned short val) const;
/// Cache of char widths /// Cache of char widths
/** This cache adds 20Mo of memory to the LyX executable when /** This cache adds 20Mo of memory to the LyX executable when
* loading UserGuide.lyx which contains a good number of fonts. If * loading UserGuide.lyx which contains a good number of fonts. If
* this turns out to be too much, we can switch to a \c QHash based * this turns out to be too much, we can switch to a \c QHash based
* solution. * solution.
**/ **/
mutable CharMetrics metrics_cache_[MaxCharType]; mutable QHash<char_type, int> width_cache_;
struct AscendDescend {
short int ascent;
short int descent;
};
mutable QHash<char_type, AscendDescend> metrics_cache_;
/// fill in \c metrics_cache_ at specified value.
void fillMetricsCache(char_type) const;
#endif // USE_LYX_FONTCACHE #endif // USE_LYX_FONTCACHE
}; };

View File

@ -78,6 +78,11 @@ inline char_type const qchar_to_ucs4(QChar const & qchar) {
} }
inline QChar const ucs4_to_qchar(char_type const ucs4) { inline QChar const ucs4_to_qchar(char_type const ucs4) {
// FIXME: The following cast is not a real conversion but it work
// for the ucs2 subrange of unicode. Instead of an assertion we should
// return some special characters that indicates that its display is
// not supported.
BOOST_ASSERT(ucs4 < 65536);
return QChar(static_cast<unsigned short>(ucs4)); return QChar(static_cast<unsigned short>(ucs4));
} }