Commits

Ivan Vučica  committed 16c75ea

Font. Text container.

  • Participants
  • Parent commits 34b3e8c

Comments (0)

Files changed (12)

 
 CFLAGS += -Ilibpng-android/jni
 
-OBJS=src/catchdroid.o src/Texture.o src/Asset.o src/Page.o src/Character.o src/Scene.o
+OBJS=src/catchdroid.o src/Texture.o src/Asset.o src/Page.o src/Character.o src/Scene.o src/Font.o src/TextContainer.o
 
 all: $(APKNAME).apk
 
 It evolved from an exercise in building Android native activities with
 GNU Make.
 
+Third-party assets
+------------------
+
+'Hand-drawn bitmap font' by Nathan Korth has been taken under 
+CC-BY 3.0 license from:
+<http://opengameart.org/content/hand-drawn-bitmap-font>
+
+
 Windows
 -------
 

File assets/font-hand-24x32.png

Added
New image

File assets/textcontainer.png

Added
New image
+#import <Foundation/Foundation.h>
+@class Texture;
+
+@interface Font : NSObject
+{
+  Texture * _texture;
+  int _charWidth;
+  int _charHeight;
+  int _charsPerRow;
+}
+@property (retain) Texture * texture;
+@property (assign) int charWidth;
+@property (assign) int charHeight;
+@property (assign) int charsPerRow;
+- (id) initWithPath: (NSString *)path
+          charWidth: (int)charWidth
+         charHeight: (int)charHeight
+        charsPerRow: (int)charsPerRow;
+- (void) drawText: (NSString *)text;
+@end
+
+@interface NSString (CatchdroidFont)
+- (void) drawWithCDFont: (Font *)font;
+@end
+#import "Font.h"
+#import "Texture.h"
+
+@implementation Font
+@synthesize texture=_texture;
+@synthesize charWidth=_charWidth;
+@synthesize charHeight=_charHeight;
+@synthesize charsPerRow=_charsPerRow;
+- (id) initWithPath: (NSString *)path
+          charWidth: (int)charWidth
+         charHeight: (int)charHeight
+        charsPerRow: (int)charsPerRow
+{
+  self = [super init];
+  if (!self)
+    return nil;
+
+  _texture = [[Texture textureWithPath: path] retain];
+  _charWidth = charWidth;
+  _charHeight = charHeight;
+  _charsPerRow = charsPerRow;
+
+  return self;
+}
+- (void) dealloc
+{
+  [_texture release];
+  [super dealloc];
+}
+- (void) drawText: (NSString *)text
+{
+  // TODO(ivucica): instead of drawing character by character,
+  // we should pre-bake a mesh.
+  
+  glPushMatrix();    
+
+  glEnable(GL_TEXTURE_2D);
+  glEnableClientState(GL_VERTEX_ARRAY);
+  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+  glBindTexture(GL_TEXTURE_2D, [_texture textureId]);
+
+  for(int i = 0; i < [text length]; i++)
+  {
+    unichar c = [text characterAtIndex: i];
+    glTranslatef(1, 0, 0);
+    [self drawCharacter: c];
+  }
+
+  glDisableClientState(GL_VERTEX_ARRAY);
+  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+  glDisable(GL_TEXTURE_2D);
+  glPopMatrix();
+}
+- (void) drawCharacter: (unichar)c
+{
+  c -= 32; // first character in a font is 32
+  int col = c % _charsPerRow;
+  int row = c / _charsPerRow;
+  int x = col * _charWidth;
+  int y = row * _charHeight;
+  GLfloat x1 = ((GLfloat)x) / _texture.textureWidth;
+  GLfloat y1 = ((GLfloat)y) / _texture.textureHeight;
+  GLfloat x2 = ((GLfloat)x+_charWidth) / _texture.textureWidth;
+  GLfloat y2 = ((GLfloat)y+_charHeight) / _texture.textureHeight;
+  
+  GLfloat vertices[] = {
+    -0.5, -0.5,
+     0.5, -0.5,
+     0.5, 0.5,
+
+     0.5, 0.5,
+    -0.5, 0.5,
+    -0.5, -0.5,
+  };
+  GLfloat textures[] = {
+    x1, y2,
+    x2, y2,
+    x2, y1,
+
+    x2, y1,
+    x1, y1,
+    x1, y2
+  };
+  glVertexPointer(2, GL_FLOAT, 0, vertices);
+  glTexCoordPointer(2, GL_FLOAT, 0, textures);
+  glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+@end
+
+@implementation NSString (CatchdroidFont)
+- (void) drawWithCDFont: (Font *)font
+{
+  [font drawText: self];
+}
+@end
       0, 0, 0, 1.-fabs(_fadeProgress),
       0, 0, 0, 1.-fabs(_fadeProgress),
     };
-    NSLog(@"%g", 1.-fabs(_fadeProgress));
     GLfloat vertices[] = {
       -0.5, -0.5,
        0.5, -0.5,

File src/TextContainer.h

+#import <Foundation/Foundation.h>
+@class Texture;
+@class Font;
+
+@interface TextContainer : NSObject
+{
+  Texture * _texture;
+  Font * _font;
+  NSMutableArray * _queue;
+  float _progress;
+}
+- (id) initWithFont: (Font *)font;
+- (void) enqueueText: (NSString *)text;
+- (void) update: (float)dt;
+@end

File src/TextContainer.m

+#import "TextContainer.h"
+#import "Font.h"
+#import "Texture.h"
+
+#define CD_MIN(x,y) ((x) < (y) ? (x) : (y))
+
+
+@implementation TextContainer
+- (id) initWithFont: (Font *)font
+{
+  self = [super init];
+  if (!self)
+    return nil;
+
+  _queue = [NSMutableArray new];
+  _texture = [[Texture textureWithPath: @"textcontainer.png"] retain];
+  _font = [font retain];
+
+  return self;
+}
+- (void) dealloc
+{
+  [_font release];
+  [_texture release];
+  [_queue release];
+  [super dealloc];
+}
+- (void) enqueueText: (NSString *)text
+{
+  [_queue addObjectsFromArray: [text componentsSeparatedByString: @"\n"]];
+}
+- (void) update: (float)dt
+{
+  if (![_queue count])
+    return;
+  _progress += dt;
+}
+- (void) draw
+{
+  if (![_queue count])
+    return;
+
+  glPushMatrix();    
+  glEnable(GL_TEXTURE_2D);
+  glEnableClientState(GL_VERTEX_ARRAY);
+  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+  glBindTexture(GL_TEXTURE_2D, [_texture textureId]);
+  glScalef(15, 7, 1);
+  glTranslatef(0.4875 + 0.0375, 0.1, 0);
+  GLfloat vertices[] = {
+    -0.5, -0.5,
+     0.5, -0.5,
+     0.5, 0.5,
+
+     0.5, 0.5,
+    -0.5, 0.5,
+    -0.5, -0.5,
+  };
+  GLfloat textures[] = {
+    0, 1,
+    1, 1,
+    1, 0,
+
+    1, 0,
+    0, 0,
+    0, 1
+  };
+  glVertexPointer(2, GL_FLOAT, 0, vertices);
+  glTexCoordPointer(2, GL_FLOAT, 0, textures);
+  glDrawArrays(GL_TRIANGLES, 0, 6);
+
+  glDisableClientState(GL_VERTEX_ARRAY);
+  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+  glDisable(GL_TEXTURE_2D);
+
+  glPopMatrix();
+
+  glPushMatrix();
+  glTranslatef(0.5, 0.5, 0);
+  NSString * line1 = [_queue objectAtIndex: 0];
+  line1 = [line1 substringToIndex: CD_MIN([line1 length], [line1 length] * _progress * 2)];
+  [line1 drawWithCDFont: _font];
+
+  if(_progress > 0.5)
+  {
+    glTranslatef(0, -1, 0);
+    NSString * line2 = [_queue objectAtIndex: 1];
+    line2 = [line2 substringToIndex: CD_MIN([line2 length], [line2 length] * (_progress-0.5) * 2)];
+    [line2 drawWithCDFont: _font];
+  }
+
+  glPopMatrix();
+}
+@end

File src/Texture.h

   GLuint _id;
   Asset * _asset;
   NSString * _path;
+  int _textureWidth, _textureHeight;
 }
 @property (nonatomic, retain) Asset * asset;
 @property (nonatomic, retain) NSString * path;
 @property (nonatomic, assign) GLuint textureId;
+@property (nonatomic, assign) int textureWidth;
+@property (nonatomic, assign) int textureHeight;
 + (Texture *) textureWithPath: (NSString *)path;
 - (id) initWithPath: (NSString *)path;
 @end

File src/Texture.m

 @synthesize asset=_asset;
 @synthesize path=_path;
 @synthesize textureId=_id;
+@synthesize textureWidth=_textureWidth;
+@synthesize textureHeight=_textureHeight;
 + (Texture *) textureWithPath: (NSString *)path
 {
   return [[[self alloc] initWithPath: path] autorelease];
   glTexImage2D(
       GL_TEXTURE_2D, 0, rawData.gl_color_format, rawData.width, rawData.height, 0, rawData.gl_color_format, GL_UNSIGNED_BYTE, rawData.data);
 
+  _textureWidth = rawData.width;
+  _textureHeight = rawData.height;
+
   //glGenerateMipmap(GL_TEXTURE_2D); // only gles2.0
  
   glBindTexture(GL_TEXTURE_2D, 0);

File src/catchdroid.m

 #import "Page.h"
 #import "Character.h"
 #import "Scene.h"
+#import "Font.h"
+#import "TextContainer.h"
 
 /**
  * Our saved state data.
     Texture * _controls;
     double _previousFrameTime;
     Scene * _scene;
+    Font * _font;
+    TextContainer * _textContainer;
 }
 -(int)setupDisplay;
 -(void)terminateDisplay;
     [_controls retain];
 
     _scene = [Scene new];
+    _font = [[Font alloc] initWithPath: @"font-hand-24x32.png"
+                             charWidth: 24
+                            charHeight: 32
+                           charsPerRow: 16];
+    _textContainer = [[TextContainer alloc] initWithFont: _font];
+
+    [_textContainer enqueueText: @"hello\nworld"];
 
     //[self showToast: @"Tap to begin"];
 
     glPopMatrix();
     //////////////////
 
+    glPushMatrix();
+    glScalef(0.3, 0.3, 1.);
+    glTranslatef(-8, -1, 0);
+    //[_font drawText: @"hello();"];
+    [_textContainer draw];
+    glPopMatrix();
+
     eglSwapBuffers(self->display, self->surface);
 }
 
 
     // update all objects
     [_scene update: deltaT];
+    [_textContainer update: deltaT];
   }
   _previousFrameTime = currentTime;
 
     NSString * home2 = [NSString stringWithFormat: @"HOME=%@", home];
 
     const char* argv[1] = { [exe UTF8String] };
-    const char* env[4] = { "USER=android", [home UTF8String], [path UTF8String], NULL };
+    const char* env[4] = { "USER=android", [home2 UTF8String], [path UTF8String], NULL };
     
     GSInitializeProcess(1, argv, env);
     //[[NSUserDefaults standardUserDefaults] readFromPath:userDefaultsPath()];