[原]零基础学习SDL开发之在Android使用SDL2.0加载字体

时间:2021-04-04 03:31:57

在上一篇文章我们知道了如何在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");
}

 

运行截图:

[原]零基础学习SDL开发之在Android使用SDL2.0加载字体