[dasher: 3/28] iPhone+Mac: cache label sizes at one font size, scale proportionately (faster!)
- From: Patrick Welche <pwelche src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dasher: 3/28] iPhone+Mac: cache label sizes at one font size, scale proportionately (faster!)
- Date: Tue, 22 Nov 2011 17:02:55 +0000 (UTC)
commit b9b25c1bf7882776ac8b61d342d575a1aec55a30
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date: Tue Sep 13 18:08:41 2011 +0100
iPhone+Mac: cache label sizes at one font size, scale proportionately (faster!)
as opposed to asking OS for exact dimensions at every font size.
(This was taking ~50% CPU time on iPhone; fix improves framerate ~18 -> ~28)
Src/Common/OpenGLScreen.h | 9 +++++----
Src/Common/OpenGLScreen.mm | 31 +++++++++++++++++--------------
Src/MacOSX/DasherViewOpenGL.mm | 30 ++++++++++++------------------
Src/iPhone/Classes/EAGLView.h | 2 +-
Src/iPhone/Classes/EAGLView.mm | 9 +++++----
5 files changed, 40 insertions(+), 41 deletions(-)
---
diff --git a/Src/Common/OpenGLScreen.h b/Src/Common/OpenGLScreen.h
index ecb753e..59878e2 100755
--- a/Src/Common/OpenGLScreen.h
+++ b/Src/Common/OpenGLScreen.h
@@ -23,6 +23,7 @@ namespace Dasher {
NSString *str;
GLuint texture;
GLfloat texcoords[8];
+ CGSize sz; //at base font size, or wrapped size if appropriate
AlphabetLetter(OpenGLScreen *pScreen, const std::string &strText, unsigned int iWrapSize);
~AlphabetLetter();
void PrepareTexture();
@@ -48,10 +49,10 @@ namespace Dasher {
void resize(screenint iWidth, screenint iHeight, GLshort backingWidth, GLshort backingHeight, GLfloat tc_x, GLfloat tc_y);
void RegenerateLabels();
///Render a string onto a CoreGraphics context, using the context's current colour etc.
- /// \param iFontSize if 0, render on a single line, in 36pt font; any other value,
- /// render in that size, but constrained to the screen width, wrapping across multiple
- /// lines if necessary
- virtual void RenderStringOntoCGContext(NSString *string, CGContextRef context, unsigned int iFontSize)=0;
+ /// \param iFontSize font size to use
+ /// \param bWrap if true, constrain to screen width and wrap across multiple lines (if necessary);
+ /// if false, render on a single line.
+ virtual void RenderStringOntoCGContext(NSString *string, CGContextRef context, unsigned int iFontSize, bool bWrap)=0;
/// Get the pixel dimensions of a string when rendered in a specified font size
/// \param bWrap if true, string should be wrapped to the screen width, possibly
/// over multiple lines (=> returned height will reflect this); if false,
diff --git a/Src/Common/OpenGLScreen.mm b/Src/Common/OpenGLScreen.mm
index e4c18f2..a29aa31 100644
--- a/Src/Common/OpenGLScreen.mm
+++ b/Src/Common/OpenGLScreen.mm
@@ -13,6 +13,8 @@
using namespace Dasher;
using namespace std;
+#define BASE_SIZE 32
+
OpenGLScreen::OpenGLScreen(screenint iWidth, screenint iHeight, GLshort backingWidth, GLshort backingHeight, GLfloat tc_x, GLfloat tc_y, GLuint *_textures)
: CLabelListScreen(iWidth,iHeight), colourTable(NULL), circ_rad(-1.0f), circ_coords(NULL), circPoints(0), textures(_textures) {
resize(iWidth,iHeight,backingWidth,backingHeight,tc_x,tc_y);
@@ -205,22 +207,23 @@ OpenGLScreen::AlphabetLetter::AlphabetLetter(OpenGLScreen *pScreen, const string
}
void OpenGLScreen::AlphabetLetter::PrepareTexture() {
+
+ sz = static_cast<OpenGLScreen *>(m_pScreen)->TextSize(str,m_iWrapSize ? m_iWrapSize : BASE_SIZE,m_iWrapSize);
+
int width=1, height=1;
GLfloat texw,texh;
- {
- CGSize sz = static_cast<OpenGLScreen *>(m_pScreen)->TextSize(str,m_iWrapSize ? m_iWrapSize : 36,m_iWrapSize);
- while (width<sz.width) width<<=1;
- while (height<sz.height) height<<=1;
- texw = sz.width/(float)width;
- texh = sz.height/(float)height;
- }
+
+ while (width<sz.width) width<<=1;
+ while (height<sz.height) height<<=1;
+ texw = sz.width/(float)width;
+ texh = sz.height/(float)height;
char *data = new char[width*height*4];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(data, width, height, 8, width*4, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextClearRect(context, CGRectMake(0.0, 0.0, width, height));
- static_cast<OpenGLScreen *>(m_pScreen)->RenderStringOntoCGContext(str,context,m_iWrapSize);
+ static_cast<OpenGLScreen *>(m_pScreen)->RenderStringOntoCGContext(str,context,m_iWrapSize ? m_iWrapSize : BASE_SIZE,m_iWrapSize);
glBindTexture(GL_TEXTURE_2D, texture);
//...but tell the GL _not_ to interpolate between texels, as that results in a _big_
@@ -267,12 +270,12 @@ void OpenGLScreen::DrawString(CDasherScreen::Label *label, screenint x, screenin
// by the currently selected GL foreground colour
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f(colourTable[iColour].r, colourTable[iColour].g, colourTable[iColour].b, 1.0); //so we select the colour we want the text to appear in
- CGSize sz = TextSize(l->str, iFontSize, l->m_iWrapSize);
+ pair<screenint,screenint> rect = TextSize(label, iFontSize);
GLshort coords[8];
coords[0] = x; coords[1]=y;
- coords[2] = x+sz.width; coords[3] = y;
- coords[4] = x; coords[5] = y+sz.height;
- coords[6] = x+sz.width; coords[7]=y+sz.height;
+ coords[2] = x+rect.first; coords[3] = y;
+ coords[4] = x; coords[5] = y+rect.second;
+ coords[6] = x+rect.first; coords[7]=y+rect.second;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_SHORT, 0, coords);
@@ -285,8 +288,8 @@ void OpenGLScreen::DrawString(CDasherScreen::Label *label, screenint x, screenin
pair<screenint,screenint> OpenGLScreen::TextSize(CDasherScreen::Label *label, unsigned int iFontSize) {
const AlphabetLetter *l(static_cast<AlphabetLetter *> (label));
- CGSize sz = TextSize(l->str, iFontSize, l->m_iWrapSize);
+ const int baseSize(l->m_iWrapSize ? l->m_iWrapSize : BASE_SIZE);
//apply "ceil" to floating-point width/height ?
- return pair<screenint,screenint>(sz.width, sz.height);
+ return pair<screenint,screenint>((l->sz.width*iFontSize)/baseSize, (l->sz.height*iFontSize)/baseSize);
}
diff --git a/Src/MacOSX/DasherViewOpenGL.mm b/Src/MacOSX/DasherViewOpenGL.mm
index 4bf73b6..58cd8b6 100755
--- a/Src/MacOSX/DasherViewOpenGL.mm
+++ b/Src/MacOSX/DasherViewOpenGL.mm
@@ -26,17 +26,12 @@
class COSXDasherScreen : public OpenGLScreen {
DasherViewOpenGL *dasherView;
- NSDictionary *fontAttrs;
public:
COSXDasherScreen(DasherViewOpenGL *_dasherView,screenint iWidth, screenint iHeight, GLfloat tc_x, GLfloat tc_y, GLuint *textures)
- : OpenGLScreen(iWidth, iHeight, iWidth, iHeight,tc_x,tc_y,textures), dasherView(_dasherView), fontAttrs(nil) {
+ : OpenGLScreen(iWidth, iHeight, iWidth, iHeight,tc_x,tc_y,textures), dasherView(_dasherView) {
RegenerateLabels(); //no actual labels, so just initialize fontAttrs
}
-
- ~COSXDasherScreen() {
- [fontAttrs release];
- }
-
+
void SendMarker(int iMarker) {
[dasherView sendMarker:iMarker];
}
@@ -50,26 +45,25 @@ public:
OpenGLScreen::resize(w,h, w,h, tc_x,tc_y);
}
+ ///Override just to make callable from DasherViewOpenGL
void RegenerateLabels() {
- [fontAttrs release];
- //white text on (default) transparent background means that when we texture
- //a surface using a colour, the text appears in that colour...
- fontAttrs = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:dasherView.cachedFontName size:36.0],NSFontAttributeName,[NSColor whiteColor],NSForegroundColorAttributeName,nil];
- //dictionaryWith...: does an autorelease - only "alloc" methods do not.
- // But we want to keep the fontAttrs indefinitely...
- [fontAttrs retain];
OpenGLScreen::RegenerateLabels();
}
protected:
- void RenderStringOntoCGContext(NSString *string, CGContextRef context, unsigned int iWrapSize) {
+ void RenderStringOntoCGContext(NSString *string, CGContextRef context, unsigned int iFontSize, bool bWrap) {
NSGraphicsContext *old = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:YES]];
- if (iWrapSize)
- [string drawWithRect:NSMakeRect(0.0, 0.0, GetWidth(), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:dasherView.cachedFontName size:iWrapSize],NSFontAttributeName,[NSColor whiteColor],NSForegroundColorAttributeName,nil]];
+ //white text on (default) transparent background means that when we texture
+ //a surface using a colour, the text appears in that colour...
+ NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:dasherView.cachedFontName size:iFontSize], NSFontAttributeName, [NSColor whiteColor], NSForegroundColorAttributeName, nil];
+ //dictionaryWith...: does an autorelease - only "alloc" methods do not.
+
+ if (bWrap)
+ [string drawWithRect:NSMakeRect(0.0, 0.0, GetWidth(), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs];
else
- [string drawAtPoint:NSMakePoint(0.0, 0.0) withAttributes:fontAttrs];
+ [string drawAtPoint:NSMakePoint(0.0, 0.0) withAttributes:attrs];
[NSGraphicsContext setCurrentContext:old];
}
diff --git a/Src/iPhone/Classes/EAGLView.h b/Src/iPhone/Classes/EAGLView.h
index 71f7f4a..e457768 100644
--- a/Src/iPhone/Classes/EAGLView.h
+++ b/Src/iPhone/Classes/EAGLView.h
@@ -27,7 +27,7 @@ public:
void SendMarker(int iMarker);
protected:
- void RenderStringOntoCGContext(NSString *str, CGContextRef context, unsigned int iWrapFontSize);
+ void RenderStringOntoCGContext(NSString *str, CGContextRef context, unsigned int iFontSize, bool bWrap);
CGSize TextSize(NSString *str, unsigned int iFontSize, bool bWrap);
};
diff --git a/Src/iPhone/Classes/EAGLView.mm b/Src/iPhone/Classes/EAGLView.mm
index 4e4bf98..fa08f73 100644
--- a/Src/iPhone/Classes/EAGLView.mm
+++ b/Src/iPhone/Classes/EAGLView.mm
@@ -42,17 +42,18 @@ void CDasherScreenBridge::SendMarker(int iMarker) {
[view sendMarker:iMarker];
}
-void CDasherScreenBridge::RenderStringOntoCGContext(NSString *str, CGContextRef context, unsigned int iFontWrapSize) {
+void CDasherScreenBridge::RenderStringOntoCGContext(NSString *str, CGContextRef context, unsigned int iFontSize, bool bWrap) {
UIGraphicsPushContext(context);
//white text on transparent background means that when we texture
//a surface using a colour, the text appears in that colour...
const CGFloat whiteComps[] = {1.0, 1.0, 1.0, 1.0};
CGColorRef white = CGColorCreate(CGBitmapContextGetColorSpace(context), whiteComps);
CGContextSetFillColorWithColor(context, white);
- if (iFontWrapSize)
- [str drawInRect:CGRectMake(0.0, 0.0, GetWidth(), CGFLOAT_MAX) withFont:[UIFont systemFontOfSize:iFontWrapSize]];
+ UIFont *font = [UIFont systemFontOfSize:iFontSize];
+ if (bWrap)
+ [str drawInRect:CGRectMake(0.0, 0.0, GetWidth(), CGFLOAT_MAX) withFont:font];
else
- [str drawAtPoint:CGPointMake(0.0, 0.0) withFont:[UIFont systemFontOfSize:36]];
+ [str drawAtPoint:CGPointMake(0.0, 0.0) withFont:font];
CGColorRelease(white);
UIGraphicsPopContext();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]