Images are almost fully reimplemented.

Font sizing is pretty much fixed.
Just need to re-initialize textures with the renderer.
This commit is contained in:
Aloshi 2012-08-29 16:52:25 -05:00
parent cdb63c4a4f
commit 07d8046a3e
8 changed files with 177 additions and 104 deletions

View file

@ -19,6 +19,8 @@ void Font::initLibrary()
Font::Font(std::string path, int size)
{
mMaxGlyphHeight = 0;
if(FT_New_Face(sLibrary, path.c_str(), 0, &face))
{
std::cout << "Error creating font face! (path: " << path.c_str() << "\n";
@ -49,10 +51,9 @@ void Font::buildAtlas()
h = std::max(h, g->bitmap.rows);
}*/
//GLES requires a power of two
//the max size (GL_MAX_TEXTURE_SIZE) is pretty small too, like 3300, so just force it
//the max size (GL_MAX_TEXTURE_SIZE) is like 3300
w = 2048;
h = 2048;
h = 512;
textureWidth = w;
textureHeight = h;
@ -99,23 +100,29 @@ void Font::buildAtlas()
{
x = 0;
y += maxHeight;
std::cout << "looping to next row, maxHeight: " << maxHeight << std::endl;
maxHeight = 0;
}
if(g->bitmap.rows > maxHeight)
maxHeight = g->bitmap.rows;
glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
charData[i].texX = x;
charData[i].texY = 0;
charData[i].texY = y;
charData[i].texW = g->bitmap.width;
charData[i].texH = g->bitmap.rows;
charData[i].advX = g->metrics.horiAdvance >> 6;
charData[i].advY = g->advance.y >> 6;
charData[i].bearingY = g->metrics.horiBearingY >> 6;
if(charData[i].texH > mMaxGlyphHeight)
mMaxGlyphHeight = charData[i].texH;
x += g->bitmap.width;
}
@ -138,6 +145,8 @@ Font::~Font()
//openGL reads these in the order they are in memory
//if I use an array, it will be 4 x values then 4 y values
//it'll read XX, XX, YY instead of XY, XY, XY
//...
//that was the thinking at the time and honestly an array would have been smarter wow I'm dumb
struct point {
GLfloat pos0x;
GLfloat pos0y;
@ -162,8 +171,11 @@ struct tex {
void Font::drawText(std::string text, int startx, int starty, int color)
{
starty += mMaxGlyphHeight;
//padding (another 0.5% is added to the bottom through the sizeText function)
starty += Renderer::getScreenHeight() * 0.005;
starty += (face->height / face->units_per_EM) << 6; //(face->height / face->units_per_EM) << 6;
int pointCount = text.length() * 2;
point* points = new point[pointCount];
@ -193,24 +205,24 @@ void Font::drawText(std::string text, int startx, int starty, int color)
if(letter < 32 || letter >= 128)
continue;
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY;
points[p].pos2x = x; points[p].pos2y = y - charData[letter].bearingY;
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY;
points[p].pos2x = x; points[p].pos2y = y - charData[letter].bearingY;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
texs[p].tex2x = charData[letter].texX / tw; texs[p].tex2y = charData[letter].texY / th;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
texs[p].tex2x = charData[letter].texX / tw; texs[p].tex2y = charData[letter].texY / th;
p++;
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
points[p].pos0x = x; points[p].pos0y = y + charData[letter].texH - charData[letter].bearingY;
points[p].pos1x = x + charData[letter].texW; points[p].pos1y = y - charData[letter].bearingY;
points[p].pos2x = x + charData[letter].texW; points[p].pos2y = y + charData[letter].texH - charData[letter].bearingY;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
texs[p].tex2x = texs[p].tex1x; texs[p].tex2y = texs[p].tex0y;
texs[p].tex0x = charData[letter].texX / tw; texs[p].tex0y = (charData[letter].texY + charData[letter].texH) / th;
texs[p].tex1x = (charData[letter].texX + charData[letter].texW) / tw; texs[p].tex1y = charData[letter].texY / th;
texs[p].tex2x = texs[p].tex1x; texs[p].tex2y = texs[p].tex0y;
x += charData[letter].advX;
@ -242,17 +254,16 @@ void Font::drawText(std::string text, int startx, int starty, int color)
void Font::sizeText(std::string text, int* w, int* h)
{
if(w != NULL)
int cwidth = 0;
for(unsigned int i = 0; i < text.length(); i++)
{
int cwidth = 0;
for(unsigned int i = 0; i < text.length(); i++)
{
cwidth += charData[(int)text[i]].advX;
}
*w = cwidth;
cwidth += charData[(int)text[i]].advX;
}
if(w != NULL)
*w = cwidth;
if(h != NULL)
*h = (face->height / face->units_per_EM) << 6;
*h = mMaxGlyphHeight + Renderer::getScreenWidth() * 0.01;
}

View file

@ -46,6 +46,7 @@ private:
int textureWidth;
int textureHeight;
int mMaxGlyphHeight;
};
#endif

View file

@ -6,8 +6,11 @@
namespace Renderer {
bool loadedFonts = false;
unsigned int getScreenWidth() { return 1680; }
unsigned int getScreenHeight() { return 1050; }
//defined and set in Renderer_init_rpi.cpp
extern unsigned int display_width;
extern unsigned int display_height;
unsigned int getScreenWidth() { return display_width; }
unsigned int getScreenHeight() { return display_height; }
void setColor4bArray(GLubyte* array, int color)
{
@ -52,25 +55,29 @@ namespace Renderer {
glDisableClientState(GL_COLOR_ARRAY);
}
Font* defaultFont = NULL;
Font* fonts[3] = {NULL, NULL, NULL};
void loadFonts()
{
std::cout << "loading fonts\n";
if(defaultFont != NULL)
delete defaultFont;
defaultFont = new Font("LinLibertine_R.ttf", 12);
unsigned int fontSizes[] = {10, 12, 22};
for(unsigned int i = 0; i < 3; i++)
{
fonts[i] = new Font("LinLibertine_R.ttf", fontSizes[i]);
}
loadedFonts = true;
}
void unloadFonts()
{
if(defaultFont)
for(unsigned int i = 0; i < 3; i++)
{
delete defaultFont;
defaultFont = NULL;
delete fonts[i];
fonts[i] = NULL;
}
loadedFonts = false;
@ -78,7 +85,10 @@ namespace Renderer {
Font* getFont(FontSize size)
{
return defaultFont;
if(!loadedFonts)
loadFonts();
return fonts[size];
}
@ -88,7 +98,7 @@ namespace Renderer {
loadFonts();
int h;
getFont(size)->sizeText("", NULL, &h);
getFont(size)->sizeText("HEIGHT", NULL, &h);
return h;
}

View file

@ -15,7 +15,10 @@ namespace Renderer
static EGL_DISPMANX_WINDOW_T nativewindow;
bool createSurface()
unsigned int display_width = 0;
unsigned int display_height = 0;
bool createSurface() //unsigned int display_width, unsigned int display_height)
{
std::cout << "Creating surface...\n";
@ -83,16 +86,15 @@ namespace Renderer
unsigned int display_width;
unsigned int display_height;
bool success = graphics_get_display_size(0, &display_width, &display_height); //0 = LCD
if(success < 0)
if(!display_width || !display_height)
{
std::cerr << "Error getting display size!\n";
return false;
bool success = graphics_get_display_size(0, &display_width, &display_height); //0 = LCD
if(success < 0)
{
std::cerr << "Error getting display size!\n";
return false;
}
}
std::cout << "Display size is " << display_width << "x" << display_height << "\n";
@ -139,7 +141,7 @@ namespace Renderer
void swapBuffers()
{
eglSwapBuffers(display, surface);
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void destroySurface()
@ -154,15 +156,21 @@ namespace Renderer
bool init(int w, int h)
{
bcm_host_init();
bool surface = createSurface();
if(!surface)
if(w)
display_width = w;
if(h)
display_height = h;
bool createdSurface = createSurface();
if(!createdSurface)
return false;
Font::initLibrary();
glViewport(0, 0, 1680, 1050);
glOrthof(0, 1680, 1050, 0, -1.0, 1.0);
glViewport(0, 0, display_width, display_height);
glOrthof(0, display_width, display_height, 0, -1.0, 1.0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
return true;

View file

@ -26,7 +26,6 @@ GuiGameList::GuiGameList(bool useDetail)
mScreenshot = new GuiImage(Renderer::getScreenWidth() * sInfoWidth * 0.5, Renderer::getFontHeight(Renderer::LARGE) + 2, "", Renderer::getScreenWidth() * sInfoWidth * 0.7);
mScreenshot->setOrigin(0.5, 0.0);
mScreenshot->setAlpha(true); //slower, but requested
addChild(mScreenshot);
}else{
mList = new GuiList<FileData*>(0, Renderer::getFontHeight(Renderer::LARGE) + 2);
@ -96,7 +95,7 @@ void GuiGameList::onRender()
ss << FRAMERATE;
std::string fps;
ss >> fps;
Renderer::drawText(fps, 0, 0, 0x00FF00);
Renderer::drawText(fps, 100, 0, 0x00FF00);
#endif
//header

View file

@ -5,7 +5,7 @@
int GuiImage::getWidth() { return mWidth; }
int GuiImage::getHeight() { return mHeight; }
GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int maxWidth, unsigned int maxHeight, bool resizeExact)
GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int resizeWidth, unsigned int resizeHeight, bool resizeExact)
{
mTextureID = 0;
@ -21,8 +21,8 @@ GuiImage::GuiImage(int offsetX, int offsetY, std::string path, unsigned int maxW
mTiled = false;
mMaxWidth = maxWidth;
mMaxHeight = maxHeight;
mResizeWidth = resizeWidth;
mResizeHeight = resizeHeight;
mResizeExact = resizeExact;
mUseAlpha = false;
@ -115,9 +115,6 @@ void GuiImage::loadImage(std::string path)
//force power of two for testing
//width = 512; height = 512;
//now for the openGL texture stuff
glGenTextures(1, &mTextureID);
glBindTexture(GL_TEXTURE_2D, mTextureID);
@ -135,6 +132,36 @@ void GuiImage::loadImage(std::string path)
//free the memory from that pointer
delete[] imageRGBA;
//a simple way to resize: lie about our real texture size!
//(we don't resize tiled images)
if(!mTiled)
{
float resizeScaleX = 0, resizeScaleY = 0;
if(mResizeExact)
{
if(mResizeWidth)
resizeScaleX = (float)mResizeWidth / mWidth;
if(mResizeHeight)
resizeScaleY = (float)mResizeHeight / mHeight;
}else{
if(mResizeWidth && mWidth > mResizeWidth)
resizeScaleX = (float)mResizeWidth / mWidth;
if(mResizeHeight && mHeight > mResizeHeight)
resizeScaleY = (float)mResizeHeight / mHeight;
}
if(resizeScaleX && !resizeScaleY)
resizeScaleY = resizeScaleX;
if(resizeScaleY && !resizeScaleX)
resizeScaleX = resizeScaleY;
if(resizeScaleX)
mWidth *= resizeScaleX;
if(resizeScaleY)
mHeight *= resizeScaleY;
}
std::cout << "Image load successful, w: " << mWidth << " h: " << mHeight << " texID: " << mTextureID << "\n";
}
@ -185,45 +212,60 @@ void GuiImage::onRender()
{
if(mTextureID)
{
glBindTexture(GL_TEXTURE_2D, mTextureID);
glEnable(GL_TEXTURE_2D);
GLfloat points[12];
points[0] = mOffsetX - (mWidth * mOriginX); points[1] = mOffsetY - (mHeight * mOriginY);
points[2] = mOffsetX - (mWidth * mOriginX); points[3] = mOffsetY + (mHeight * (1 - mOriginY));
points[4] = mOffsetX + (mWidth * (1 - mOriginX)); points[5] = mOffsetY - (mHeight * mOriginY);
points[6] = mOffsetX + (mWidth * (1 - mOriginX)); points[7] = mOffsetY - (mHeight * mOriginY);
points[8] = mOffsetX - (mWidth * mOriginX); points[9] = mOffsetY + (mHeight * (1 - mOriginY));
points[10] = mOffsetX + (mWidth * (1 -mOriginX)); points[11] = mOffsetY + (mHeight * (1 - mOriginY));
//std::cout << "x: " << points[0] << " y: " << points[1] << " to x: " << points[10] << " y: " << points[11] << std::endl;
//std::cout << "(w: " << mWidth << " h: " << mHeight << ")" << std::endl;
GLfloat texs[12];
texs[0] = 0; texs[1] = 1;
texs[2] = 0; texs[3] = 0;
texs[4] = 1; texs[5] = 1;
texs[6] = 1; texs[7] = 1;
texs[8] = 0; texs[9] = 0;
texs[10] = 1; texs[11] = 0;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, points);
glTexCoordPointer(2, GL_FLOAT, 0, texs);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
if(mTiled)
{
for(unsigned int x = 0; x < (unsigned int)((float)mResizeWidth/mWidth + 1.5); x++)
{
for(unsigned int y = 0; y < (unsigned int)((float)mResizeHeight/mHeight + 1.5); y++)
{
drawImage(mOffsetX + x*mWidth, mOffsetY + y*mHeight);
}
}
}else{
drawImage(mOffsetX, mOffsetY);
}
}
}
void GuiImage::drawImage(int posX, int posY)
{
glBindTexture(GL_TEXTURE_2D, mTextureID);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
GLfloat points[12];
points[0] = posX - (mWidth * mOriginX); points[1] = posY - (mHeight * mOriginY);
points[2] = posX - (mWidth * mOriginX); points[3] = posY + (mHeight * (1 - mOriginY));
points[4] = posX + (mWidth * (1 - mOriginX)); points[5] = posY - (mHeight * mOriginY);
points[6] = posX + (mWidth * (1 - mOriginX)); points[7] = posY - (mHeight * mOriginY);
points[8] = posX - (mWidth * mOriginX); points[9] = posY + (mHeight * (1 - mOriginY));
points[10] = posX + (mWidth * (1 -mOriginX)); points[11] = posY + (mHeight * (1 - mOriginY));
//std::cout << "x: " << points[0] << " y: " << points[1] << " to x: " << points[10] << " y: " << points[11] << std::endl;
//std::cout << "(w: " << mWidth << " h: " << mHeight << ")" << std::endl;
GLfloat texs[12];
texs[0] = 0; texs[1] = 1;
texs[2] = 0; texs[3] = 0;
texs[4] = 1; texs[5] = 1;
texs[6] = 1; texs[7] = 1;
texs[8] = 0; texs[9] = 0;
texs[10] = 1; texs[11] = 0;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, points);
glTexCoordPointer(2, GL_FLOAT, 0, texs);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}

View file

@ -23,11 +23,12 @@ public:
void onRender();
private:
int mMaxWidth, mMaxHeight;
unsigned int mResizeWidth, mResizeHeight;
float mOriginX, mOriginY;
bool mResizeExact, mTiled, mUseAlpha;
void loadImage(std::string path);
void drawImage(int x, int y);
void unloadImage();
std::string mPath;

View file

@ -32,8 +32,8 @@ int main(int argc, char* argv[])
SDL_Surface* sdlScreen = SDL_SetVideoMode(1, 1, 0, SDL_SWSURFACE);
std::cout << "Fake SDL window is " << sdlScreen->w << "x" << sdlScreen->h << "\n";
int width = 0;
int height = 0;
unsigned int width = 0;
unsigned int height = 0;
if(argc > 1)
{
for(int i = 1; i < argc; i++)
@ -56,7 +56,8 @@ int main(int argc, char* argv[])
}
}
if(!Renderer::init(width, height))
bool renderInit = Renderer::init(width, height);
if(!renderInit)
{
std::cerr << "Error initializing renderer!\n";
return 1;