在上一篇文章我们知道了如何在android使用SDL2.0来渲染显示一张png图,而且在上上一篇我们知道如何使用sdl来渲染输出bmp图,那么sdl是否可以渲染输出自己喜爱的字体库的字体呢?答案是当然可以。
我们需要移植SDL_ttf字体库来支持相应的字体的渲染输出。
一、移植SDL_ttf库:
使用如下命令,从SDL Mercurial获取SDL_image的源码:
hg clone https://hg.libsdl.org/SDL_ttf/
将SDL_ttf拷贝到在上一篇文章中的android-project\jni\下,将平台相关的代码去掉以及自动自动化相关的文件去掉,保留android相关的代码与文件。
二、在android中添加相关的引用:
修改android-project\jni\src\Android.mk,添加相关的引用:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main SDL_PATH := ../SDL SDL_IMAGE_PATH := ../SDL2_image SDL_TTF_PATH := ../SDL_ttf LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SDL_IMAGE_PATH) LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SDL_TTF_PATH) # Add your application source files here... LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c SDL_lesson.c LOCAL_SHARED_LIBRARIES := SDL2 LOCAL_SHARED_LIBRARIES += SDL2_image LOCAL_SHARED_LIBRARIES += SDL2_ttf LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog include $(BUILD_SHARED_LIBRARY)
三、代码中引用相关的头文件:
/* * SDL_lesson.c * Clipping Sprite Sheets * Created on: Aug 12, 2014 * Author: clarck */ #include <jni.h> #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include "SDL_logger.h" #include "SDL_main.h" #include "SDL_cleanup.h" //The attributes of the screen const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; struct SDL_Window *window = NULL; struct SDL_Renderer *render = NULL; struct SDL_Texture *background = NULL; struct SDL_Texture *image = NULL; struct SDL_Surface *surface = NULL; struct SDL_Texture *texture = NULL;
四、加载图片的部分修改为IMG_LoadTexture:
* SDL_lesson.c * Clipping Sprite Sheets * Created on: Aug 12, 2014 * Author: clarck */ #include <jni.h> #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include "SDL_logger.h" #include "SDL_main.h" #include "SDL_cleanup.h" //The attributes of the screen const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; struct SDL_Window *window = NULL; struct SDL_Renderer *render = NULL; struct SDL_Texture *background = NULL; struct SDL_Texture *image = NULL; struct SDL_Surface *surface = NULL; struct SDL_Texture *texture = NULL; /* * Loads a image into a texture on the rendering device * @param file The image file to load * @param ren The renderer to load the texture onto * @return the loaded texture, or NULL if something went wrong. */ SDL_Texture* loadTexture(const char *file, SDL_Renderer *render) { struct SDL_Texture *texture = NULL; texture = IMG_LoadTexture(render, file); if (texture == NULL) { LOGE("SDL_CreateTextureFromSurface failed %s", SDL_GetError()); } else { LOGI("SDL_CreateTextureFromSurface successful."); } return texture; } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height * @param tex The source texture we want to draw * @param ren The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param w The width of the texture to draw * @param h The height of the texture to draw */ void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst, SDL_Rect *clip) { SDL_RenderCopy(ren, tex, clip, &dst); } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height and taking a clip of the texture if desired * If a clip is passed, the clip‘s width and height will be used instead of the texture‘s * @param tex The source texture we want to draw * @param rend The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param clip The sub-section of the texture to draw (clipping rect) * default of nullptr draws the entire texture */ void renderTexture2(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip) { SDL_Rect dst; dst.x = x; dst.y = y; if (clip != NULL) { dst.w = clip->w; dst.h = clip->h; } else { SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); } renderTexture(tex, ren, dst, clip); }
五、添加字体渲染功能函数:
/* * SDL_lesson.c * Clipping Sprite Sheets * Created on: Aug 12, 2014 * Author: clarck */ #include <jni.h> #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include "SDL_logger.h" #include "SDL_main.h" #include "SDL_cleanup.h" //The attributes of the screen const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; struct SDL_Window *window = NULL; struct SDL_Renderer *render = NULL; struct SDL_Texture *background = NULL; struct SDL_Texture *image = NULL; struct SDL_Surface *surface = NULL; struct SDL_Texture *texture = NULL; /* * Loads a image into a texture on the rendering device * @param file The image file to load * @param ren The renderer to load the texture onto * @return the loaded texture, or NULL if something went wrong. */ SDL_Texture* loadTexture(const char *file, SDL_Renderer *render) { struct SDL_Texture *texture = NULL; texture = IMG_LoadTexture(render, file); if (texture == NULL) { LOGE("SDL_CreateTextureFromSurface failed %s", SDL_GetError()); } else { LOGI("SDL_CreateTextureFromSurface successful."); } return texture; } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height * @param tex The source texture we want to draw * @param ren The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param w The width of the texture to draw * @param h The height of the texture to draw */ void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst, SDL_Rect *clip) { SDL_RenderCopy(ren, tex, clip, &dst); } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height and taking a clip of the texture if desired * If a clip is passed, the clip‘s width and height will be used instead of the texture‘s * @param tex The source texture we want to draw * @param rend The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param clip The sub-section of the texture to draw (clipping rect) * default of nullptr draws the entire texture */ void renderTexture2(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip) { SDL_Rect dst; dst.x = x; dst.y = y; if (clip != NULL) { dst.w = clip->w; dst.h = clip->h; } else { SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); } renderTexture(tex, ren, dst, clip); } SDL_Texture* renderText(char *message, char *fontFile, SDL_Color color, int fontSize, SDL_Renderer *renderer) { //Open the font TTF_Font *font = TTF_OpenFont(fontFile, fontSize); if (font == NULL) { LOGE("renderText error: %s", SDL_GetError()); return NULL; } surface = TTF_RenderText_Blended(font, message, color); if (surface == NULL) { TTF_CloseFont(font); LOGE("TTF_RenderText_Blended error: %s", SDL_GetError()); return NULL; } texture = SDL_CreateTextureFromSurface(renderer, surface); if (texture == NULL) { LOGE("SDL_CreateTextureFromSurface error: %s", SDL_GetError()); } //Clean up the surface and font SDL_FreeSurface(surface); TTF_CloseFont(font); return texture; }
六、编写主函数功能:
/* * SDL_lesson.c * Clipping Sprite Sheets * Created on: Aug 12, 2014 * Author: clarck */ #include <jni.h> #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include "SDL_logger.h" #include "SDL_main.h" #include "SDL_cleanup.h" //The attributes of the screen const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; struct SDL_Window *window = NULL; struct SDL_Renderer *render = NULL; struct SDL_Texture *background = NULL; struct SDL_Texture *image = NULL; struct SDL_Surface *surface = NULL; struct SDL_Texture *texture = NULL; /* * Loads a image into a texture on the rendering device * @param file The image file to load * @param ren The renderer to load the texture onto * @return the loaded texture, or NULL if something went wrong. */ SDL_Texture* loadTexture(const char *file, SDL_Renderer *render) { struct SDL_Texture *texture = NULL; texture = IMG_LoadTexture(render, file); if (texture == NULL) { LOGE("SDL_CreateTextureFromSurface failed %s", SDL_GetError()); } else { LOGI("SDL_CreateTextureFromSurface successful."); } return texture; } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height * @param tex The source texture we want to draw * @param ren The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param w The width of the texture to draw * @param h The height of the texture to draw */ void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst, SDL_Rect *clip) { SDL_RenderCopy(ren, tex, clip, &dst); } /* * Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving * the texture‘s width and height and taking a clip of the texture if desired * If a clip is passed, the clip‘s width and height will be used instead of the texture‘s * @param tex The source texture we want to draw * @param rend The renderer we want to draw too * @param x The x coordinate to draw too * @param y The y coordinate to draw too * @param clip The sub-section of the texture to draw (clipping rect) * default of nullptr draws the entire texture */ void renderTexture2(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip) { SDL_Rect dst; dst.x = x; dst.y = y; if (clip != NULL) { dst.w = clip->w; dst.h = clip->h; } else { SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h); } renderTexture(tex, ren, dst, clip); } SDL_Texture* renderText(char *message, char *fontFile, SDL_Color color, int fontSize, SDL_Renderer *renderer) { //Open the font TTF_Font *font = TTF_OpenFont(fontFile, fontSize); if (font == NULL) { LOGE("renderText error: %s", SDL_GetError()); return NULL; } surface = TTF_RenderText_Blended(font, message, color); if (surface == NULL) { TTF_CloseFont(font); LOGE("TTF_RenderText_Blended error: %s", SDL_GetError()); return NULL; } texture = SDL_CreateTextureFromSurface(renderer, surface); if (texture == NULL) { LOGE("SDL_CreateTextureFromSurface error: %s", SDL_GetError()); } //Clean up the surface and font SDL_FreeSurface(surface); TTF_CloseFont(font); return texture; } int main(int argc, char *argv[]) { //char *filefolder = "/storage/sdcard0/"; char *filefolder = argv[1]; char *font_temp = "sample.ttf"; char *image_temp = "image.png"; char *background_temp = "background.png"; LOGI("natvie_SDL %s", filefolder); char *background_file = (char*) malloc( strlen(filefolder) + strlen(background_temp) + 1); strcpy(background_file, filefolder); strcat(background_file, background_temp); LOGI("natvie_SDL background_file : %s", background_file); char *image_file = (char*) malloc( strlen(filefolder) + strlen(image_temp) + 1); strcpy(image_file, filefolder); strcat(image_file, image_temp); LOGI("natvie_SDL image_file : %s", image_file); char *font_file = (char*) malloc( strlen(filefolder) + strlen(font_temp) + 1); strcpy(font_file, filefolder); strcat(font_file, font_temp); LOGI("natvie_SDL font_file : %s", font_file); if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { LOGE("SDL_Init failed %s", SDL_GetError()); return 1; } if (TTF_Init() != 0) { LOGE("TTF_Init failed %s", SDL_GetError()); SDL_Quit(); return 1; } window = SDL_CreateWindow("lesson5", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (window == NULL) { LOGE("SDL_CreateWindow failed %s", SDL_GetError()); TTF_Quit(); SDL_Quit(); return 1; } render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (render == NULL) { LOGE("SDL_CreateRenderer failed %s", SDL_GetError()); cleanup_window(window); TTF_Quit(); SDL_Quit(); return 1; } SDL_Color color = { 255, 255, 255, 255 }; image = renderText("TTF fonts are cool !", font_file, color, 64, render); if (image == NULL) { cleanup_texture(image); cleanup_render(render); cleanup_window(window); TTF_Quit(); SDL_Quit(); return 1; } //Clear the window SDL_RenderClear(render); //Draw our image in the center of the window //We need the foreground image‘s width to properly compute the position //of it‘s top left corner so that the image will be centered int iW, iH; int x = SCREEN_WIDTH / 2 - iW / 2; int y = SCREEN_HEIGHT / 2 - iH / 2; SDL_Event e; int quit = 1; while (quit != 0) { //Read any events that occured, for now we‘ll just quit if any event occurs while (SDL_PollEvent(&e)) { //If user closes the window if (e.type == SDL_QUIT) { quit = 0; } if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { quit = 0; } } //Rendering SDL_RenderClear(render); //Draw the image renderTexture2(image, render, x, y, NULL); SDL_RenderPresent(render); } //Destroy the various items cleanup_texture(image); cleanup_render(render); cleanup_window(window); IMG_Quit(); SDL_Quit(); return 0; }
七、修改SDLActivity,添加SDL_ttf动态库的load:
// Load the .so static { System.loadLibrary("SDL2"); System.loadLibrary("SDL2_image"); //System.loadLibrary("SDL2_mixer"); //System.loadLibrary("SDL2_net"); System.loadLibrary("SDL2_ttf"); System.loadLibrary("main"); }
运行截图: