aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2011-03-30 10:27:05 +1100
committernyamatongwe <unknown>2011-03-30 10:27:05 +1100
commitf88ad3864ccdf534e46cc004b377b2c08d318a04 (patch)
tree2efa44a4ecfe7b1b864c2c049d1bc6397b779bc3
parentef7f8a349a89dd7d72d62f7a162cb3e553ca4ba6 (diff)
downloadscintilla-mirror-f88ad3864ccdf534e46cc004b377b2c08d318a04.tar.gz
Optimize font use by only allocating platform font resources for unique fonts
and using aliases of these in the Style objects. Font measurement is also performed once for each unique font and the results copied into each style. No change is needed in callers. On PLAT_WX, the font ascent is cached in the Font object when Ascent is called but this is not copied into the aliases as ascent is protected. Therefore the code that copies the FontID into the alias also calls Ascent to ensure the ascent value is cached.
-rw-r--r--src/Style.cxx136
-rw-r--r--src/Style.h61
-rw-r--r--src/ViewStyle.cxx117
-rw-r--r--src/ViewStyle.h15
4 files changed, 217 insertions, 112 deletions
diff --git a/src/Style.cxx b/src/Style.cxx
index 392fd1c9a..b86884aa5 100644
--- a/src/Style.cxx
+++ b/src/Style.cxx
@@ -16,8 +16,41 @@
using namespace Scintilla;
#endif
+FontAlias::FontAlias() {
+}
+
+FontAlias::~FontAlias() {
+ SetID(0);
+ // ~Font will not release the actual font resource sine it is now 0
+}
+
+void FontAlias::ClearFont() {
+ SetID(0);
+}
+
+bool FontSpecification::EqualTo(const FontSpecification &other) const {
+ return bold == other.bold &&
+ italic == other.italic &&
+ size == other.size &&
+ characterSet == other.characterSet &&
+ fontName == other.fontName;
+}
+
+FontMeasurements::FontMeasurements() {
+ Clear();
+}
+
+void FontMeasurements::Clear() {
+ lineHeight = 2;
+ ascent = 1;
+ descent = 1;
+ externalLeading = 0;
+ aveCharWidth = 1;
+ spaceWidth = 1;
+ sizeZoomed = 2;
+}
+
Style::Style() {
- aliasOfDefaultFont = true;
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT,
false, false, false, false, caseMixed, true, true, false);
@@ -42,11 +75,6 @@ Style::Style(const Style &source) {
}
Style::~Style() {
- if (aliasOfDefaultFont)
- font.SetID(0);
- else
- font.Release();
- aliasOfDefaultFont = false;
}
Style &Style::operator=(const Style &source) {
@@ -70,10 +98,10 @@ Style &Style::operator=(const Style &source) {
}
void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
- const char *fontName_, int characterSet_,
- bool bold_, bool italic_, bool eolFilled_,
- bool underline_, ecaseForced caseForce_,
- bool visible_, bool changeable_, bool hotspot_) {
+ const char *fontName_, int characterSet_,
+ bool bold_, bool italic_, bool eolFilled_,
+ bool underline_, ecaseForced caseForce_,
+ bool visible_, bool changeable_, bool hotspot_) {
fore.desired = fore_;
back.desired = back_;
characterSet = characterSet_;
@@ -87,79 +115,31 @@ void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
visible = visible_;
changeable = changeable_;
hotspot = hotspot_;
- if (aliasOfDefaultFont)
- font.SetID(0);
- else
- font.Release();
- aliasOfDefaultFont = false;
- sizeZoomed = 2;
- lineHeight = 2;
- ascent = 1;
- descent = 1;
- externalLeading = 0;
- aveCharWidth = 1;
- spaceWidth = 1;
+ font.ClearFont();
+ FontMeasurements::Clear();
}
void Style::ClearTo(const Style &source) {
Clear(
- source.fore.desired,
- source.back.desired,
- source.size,
- source.fontName,
- source.characterSet,
- source.bold,
- source.italic,
- source.eolFilled,
- source.underline,
- source.caseForce,
- source.visible,
- source.changeable,
- source.hotspot);
+ source.fore.desired,
+ source.back.desired,
+ source.size,
+ source.fontName,
+ source.characterSet,
+ source.bold,
+ source.italic,
+ source.eolFilled,
+ source.underline,
+ source.caseForce,
+ source.visible,
+ source.changeable,
+ source.hotspot);
}
-bool Style::EquivalentFontTo(const Style *other) const {
- if (bold != other->bold ||
- italic != other->italic ||
- size != other->size ||
- characterSet != other->characterSet)
- return false;
- if (fontName == other->fontName)
- return true;
- if (!fontName)
- return false;
- if (!other->fontName)
- return false;
- return strcmp(fontName, other->fontName) == 0;
-}
-
-void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle, int extraFontFlag) {
- sizeZoomed = size + zoomLevel;
- if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
- sizeZoomed = 2;
-
- if (aliasOfDefaultFont)
- font.SetID(0);
- else
- font.Release();
- int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
- aliasOfDefaultFont = defaultStyle &&
- (EquivalentFontTo(defaultStyle) || !fontName);
- if (aliasOfDefaultFont) {
- font.SetID(defaultStyle->font.GetID());
- } else if (fontName) {
- font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
- } else {
- font.SetID(0);
- }
-
+void Style::Copy(Font &font_, const FontMeasurements &fm_) {
+ font.SetID(font_.GetID());
+ (FontMeasurements &)(*this) = fm_;
+#if PLAT_WX
ascent = surface.Ascent(font);
- descent = surface.Descent(font);
- // Probably more typographically correct to include leading
- // but that means more complex drawing as leading must be erased
- //lineHeight = surface.ExternalLeading() + surface.Height();
- externalLeading = surface.ExternalLeading(font);
- lineHeight = surface.Height(font);
- aveCharWidth = surface.AverageCharWidth(font);
- spaceWidth = surface.WidthChar(font, ' ');
+#endif
}
diff --git a/src/Style.h b/src/Style.h
index c1f87e1b3..460dad490 100644
--- a/src/Style.h
+++ b/src/Style.h
@@ -12,18 +12,53 @@
namespace Scintilla {
#endif
+struct FontSpecification {
+ const char *fontName;
+ bool bold;
+ bool italic;
+ int size;
+ int characterSet;
+ int extraFontFlag;
+ FontSpecification() :
+ fontName(0),
+ bold(false),
+ italic(false),
+ size(10),
+ characterSet(0),
+ extraFontFlag(0) {
+ }
+ bool EqualTo(const FontSpecification &other) const;
+};
+
+// Just like Font but only has a copy of the FontID so should not delete it
+class FontAlias : public Font {
+ // Private so FontAlias objects can not be copied
+ FontAlias(const FontAlias &);
+ FontAlias &operator=(const FontAlias &);
+public:
+ FontAlias();
+ virtual ~FontAlias();
+ void ClearFont();
+};
+
+struct FontMeasurements {
+ unsigned int lineHeight;
+ unsigned int ascent;
+ unsigned int descent;
+ unsigned int externalLeading;
+ unsigned int aveCharWidth;
+ unsigned int spaceWidth;
+ int sizeZoomed;
+ FontMeasurements();
+ void Clear();
+};
+
/**
*/
-class Style {
+class Style : public FontSpecification, public FontMeasurements {
public:
ColourPair fore;
ColourPair back;
- bool aliasOfDefaultFont;
- bool bold;
- bool italic;
- int size;
- const char *fontName;
- int characterSet;
bool eolFilled;
bool underline;
enum ecaseForced {caseMixed, caseUpper, caseLower};
@@ -32,14 +67,7 @@ public:
bool changeable;
bool hotspot;
- Font font;
- int sizeZoomed;
- unsigned int lineHeight;
- unsigned int ascent;
- unsigned int descent;
- unsigned int externalLeading;
- unsigned int aveCharWidth;
- unsigned int spaceWidth;
+ FontAlias font;
Style();
Style(const Style &source);
@@ -52,8 +80,7 @@ public:
bool underline_, ecaseForced caseForce_,
bool visible_, bool changeable_, bool hotspot_);
void ClearTo(const Style &source);
- bool EquivalentFontTo(const Style *other) const;
- void Realise(Surface &surface, int zoomLevel, Style *defaultStyle = 0, int extraFontFlag = 0);
+ void Copy(Font &font_, const FontMeasurements &fm_);
bool IsProtected() const { return !(changeable && visible);}
};
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 78ba1f78c..30911d3f5 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -72,11 +72,65 @@ const char *FontNames::Save(const char *name) {
return names[max-1];
}
+FontRealised::FontRealised(const FontSpecification &fs) {
+ frNext = NULL;
+ (FontSpecification &)(*this) = fs;
+}
+
+FontRealised::~FontRealised() {
+ delete frNext;
+ frNext = 0;
+}
+
+void FontRealised::Realise(Surface &surface, int zoomLevel) {
+ PLATFORM_ASSERT(fontName);
+ sizeZoomed = size + zoomLevel;
+ if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
+ sizeZoomed = 2;
+
+ int deviceHeight = surface.DeviceHeightFont(sizeZoomed);
+ Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag);
+
+ ascent = surface.Ascent(*this);
+ descent = surface.Descent(*this);
+ externalLeading = surface.ExternalLeading(*this);
+ lineHeight = surface.Height(*this);
+ aveCharWidth = surface.AverageCharWidth(*this);
+ spaceWidth = surface.WidthChar(*this, ' ');
+ if (frNext) {
+ frNext->Realise(surface, zoomLevel);
+ }
+}
+
+FontRealised *FontRealised::Find(const FontSpecification &fs) {
+ if (!fs.fontName)
+ return this;
+ FontRealised *fr = this;
+ while (fr) {
+ if (fr->EqualTo(fs))
+ return fr;
+ fr = fr->frNext;
+ }
+ return 0;
+}
+
+void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) {
+ FontRealised *fr = this;
+ while (fr) {
+ if (maxAscent < ascent)
+ maxAscent = ascent;
+ if (maxDescent < descent)
+ maxDescent = descent;
+ fr = fr->frNext;
+ }
+}
+
ViewStyle::ViewStyle() {
Init();
}
ViewStyle::ViewStyle(const ViewStyle &source) {
+ frFirst = NULL;
Init(source.stylesSize);
for (unsigned int sty=0; sty<source.stylesSize; sty++) {
styles[sty] = source.styles[sty];
@@ -155,9 +209,12 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
ViewStyle::~ViewStyle() {
delete []styles;
styles = NULL;
+ delete frFirst;
+ frFirst = NULL;
}
void ViewStyle::Init(size_t stylesSize_) {
+ frFirst = NULL;
stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_);
@@ -290,22 +347,51 @@ void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
pal.WantFind(hotspotBackground, want);
}
+void ViewStyle::CreateFont(const FontSpecification &fs) {
+ if (fs.fontName) {
+ for (FontRealised *cur=frFirst; cur; cur=cur->frNext) {
+ if (cur->EqualTo(fs))
+ return;
+ if (!cur->frNext) {
+ cur->frNext = new FontRealised(fs);
+ return;
+ }
+ }
+ frFirst = new FontRealised(fs);
+ }
+}
+
void ViewStyle::Refresh(Surface &surface) {
+ delete frFirst;
+ frFirst = NULL;
selbar.desired = Platform::Chrome();
selbarlight.desired = Platform::ChromeHighlight();
- styles[STYLE_DEFAULT].Realise(surface, zoomLevel, NULL, extraFontFlag);
- maxAscent = styles[STYLE_DEFAULT].ascent;
- maxDescent = styles[STYLE_DEFAULT].descent;
+
+ for (unsigned int i=0; i<stylesSize; i++) {
+ styles[i].extraFontFlag = extraFontFlag;
+ }
+
+ CreateFont(styles[STYLE_DEFAULT]);
+ for (unsigned int i=0; i<stylesSize; i++) {
+ CreateFont(styles[i]);
+ }
+
+ frFirst->Realise(surface, zoomLevel);
+
+ for (unsigned int i=0; i<stylesSize; i++) {
+ FontRealised *fr = frFirst->Find(styles[i]);
+ styles[i].Copy(*fr, *fr);
+ }
+ maxAscent = 1;
+ maxDescent = 1;
+ frFirst->FindMaxAscentDescent(maxAscent, maxDescent);
+ maxAscent += extraAscent;
+ maxDescent += extraDescent;
+ lineHeight = maxAscent + maxDescent;
+
someStylesProtected = false;
someStylesForceCase = false;
for (unsigned int i=0; i<stylesSize; i++) {
- if (i != STYLE_DEFAULT) {
- styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag);
- if (maxAscent < styles[i].ascent)
- maxAscent = styles[i].ascent;
- if (maxDescent < styles[i].descent)
- maxDescent = styles[i].descent;
- }
if (styles[i].IsProtected()) {
someStylesProtected = true;
}
@@ -313,10 +399,7 @@ void ViewStyle::Refresh(Surface &surface) {
someStylesForceCase = true;
}
}
- maxAscent += extraAscent;
- maxDescent += extraDescent;
- lineHeight = maxAscent + maxDescent;
aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
@@ -361,10 +444,10 @@ void ViewStyle::EnsureStyle(size_t index) {
void ViewStyle::ResetDefaultStyle() {
styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
- ColourDesired(0xff,0xff,0xff),
- Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
- SC_CHARSET_DEFAULT,
- false, false, false, false, Style::caseMixed, true, true, false);
+ ColourDesired(0xff,0xff,0xff),
+ Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
+ SC_CHARSET_DEFAULT,
+ false, false, false, false, Style::caseMixed, true, true, false);
}
void ViewStyle::ClearStyles() {
diff --git a/src/ViewStyle.h b/src/ViewStyle.h
index 6ca488dff..cf45be41f 100644
--- a/src/ViewStyle.h
+++ b/src/ViewStyle.h
@@ -39,6 +39,19 @@ public:
const char *Save(const char *name);
};
+class FontRealised : public Font, public FontSpecification, public FontMeasurements {
+ // Private so FontRealised objects can not be copied
+ FontRealised(const FontRealised &);
+ FontRealised &operator=(const FontRealised &);
+public:
+ FontRealised *frNext;
+ FontRealised(const FontSpecification &fs);
+ virtual ~FontRealised();
+ void Realise(Surface &surface, int zoomLevel);
+ FontRealised *Find(const FontSpecification &fs);
+ void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent);
+};
+
enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
@@ -48,6 +61,7 @@ enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterInden
class ViewStyle {
public:
FontNames fontNames;
+ FontRealised *frFirst;
size_t stylesSize;
Style *styles;
LineMarker markers[MARKER_MAX + 1];
@@ -119,6 +133,7 @@ public:
ViewStyle(const ViewStyle &source);
~ViewStyle();
void Init(size_t stylesSize_=64);
+ void CreateFont(const FontSpecification &fs);
void RefreshColourPalette(Palette &pal, bool want);
void Refresh(Surface &surface);
void AllocStyles(size_t sizeNew);