Added android alternate source files

This commit is contained in:
n00b87
2025-11-24 19:27:29 -06:00
parent 320adcf808
commit 762ef94b7b
5 changed files with 850 additions and 123 deletions

View File

@@ -299,6 +299,10 @@ ul, #myUL {
<li><a href="stack_size_s.html" target="main">Stack_Size_S</a></li>
<li><a href="stack_n_exists.html" target="main">Stack_N_Exists</a></li>
<li><a href="stack_s_exists.html" target="main">Stack_S_Exists</a></li>
</ul>
</li>
@@ -569,6 +573,18 @@ ul, #myUL {
<li><a href="getspritecanvasrenderpriority.html" target="main">GetSpriteCanvasRenderPriority</a></li>
<li><a href="setposteffect.html" target="main">SetPostEffect</a></li>
<li><a href="clearposteffect.html" target="main">ClearPostEffect</a></li>
<li><a href="setposteffectproperty.html" target="main">SetPostEffectProperty</a></li>
<li><a href="getposteffectproperty.html" target="main">GetPostEffectProperty</a></li>
<li><a href="setposteffectactive.html" target="main">SetPostEffectActive</a></li>
<li><a href="posteffectisactive.html" target="main">PostEffectIsActive</a></li>
</ul>
</li>
@@ -1173,6 +1189,8 @@ ul, #myUL {
<li><a href="getmatrixscale.html" target="main">GetMatrixScale</a></li>
<li><a href="matrixexists.html" target="main">MatrixExists</a></li>
</ul>
</li>
@@ -1451,6 +1469,8 @@ ul, #myUL {
<li><a href="getspriteshapeoffset.html" target="main">GetSpriteShapeOffset</a></li>
<li><a href="getspriteworldcenter.html" target="main">GetSpriteWorldCenter</a></li>
</ul>
</li>
@@ -1691,6 +1711,16 @@ ul, #myUL {
<li><a href="flipmeshsurfaces.html" target="main">FlipMeshSurfaces</a></li>
<li><a href="setmeshbuffer.html" target="main">SetMeshBuffer</a></li>
<li><a href="getmeshbuffercount.html" target="main">GetMeshBufferCount</a></li>
<li><a href="getmeshbuffervertexcount.html" target="main">GetMeshBufferVertexCount</a></li>
<li><a href="getmeshbufferindexcount.html" target="main">GetMeshBufferIndexCount</a></li>
<li><a href="getmeshbuffer.html" target="main">GetMeshBuffer</a></li>
</ul>
</li>
@@ -2233,6 +2263,12 @@ ul, #myUL {
<li><a href="getsceneambientcolor.html" target="main">GetSceneAmbientColor</a></li>
<li><a href="pipeline_begin.html" target="main">Pipeline_Begin</a></li>
<li><a href="pipeline_end.html" target="main">Pipeline_End</a></li>
<li><a href="pipeline_render.html" target="main">Pipeline_Render</a></li>
</ul>
</li>

Binary file not shown.

180
rcbasic_runtime/Android.mk Executable file → Normal file
View File

@@ -1,151 +1,85 @@
LOCAL_PATH := $(call my-dir)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Bullet-prebuilt
LOCAL_SRC_FILES := ../bullet3/build3/Android/obj/local/$(TARGET_ARCH_ABI)/libBullet.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/..
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := freetype-prebuilt
LOCAL_SRC_FILES := ../freetype/Android/libs/$(TARGET_ARCH_ABI)/libfreetype.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/..
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := main
SDL_PATH := ../SDL
SDL_IMAGE_PATH := ../SDL2_image
SDL_MIXER_PATH := ../SDL2_mixer
SDL_NET_PATH := ../SDL2_net
IRRLICHT_PATH := ../RCIrrlicht
SDL_MIXER_PATH := ../SDL_mixer
SDL_NET_PATH := ../SDL_net
THEORA_PATH := ../theora
IRR_PATH := ../RCIrrlicht
BULLET_PATH := ../bullet3
IRRBULLET_PATH := ../irrBullet
IRRTHEORA_PATH := ../irrTheora
FREETYPE_PATH := ../freetype
BOX2D_PATH := ../box2d-2.4.2
IRR_THEORA_PATH := ../irrTheora
AN8_PATH := ../an8-parser
BOX2D_PATH := ../box2d-2.4.2
BULLET_PATH := ../bullet3
IRR_BULLET_PATH := ../irrBullet
VORBIS_LIBRARY_PATH := ../libvorbis64
THEORAPLAY_PATH := ../src/theoraplay
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
VORBIS_LIBRARY_PATH := ../libvorbisidec-1.2.1
THEORAPLAY_PATH := ../src/theoraplay_tremor
endif
FREETYPE_PATH := ../freetype-2.9.1
LOCAL_CFLAGS := -I$(LOCAL_PATH)/$(THEORAPLAY_PATH) -I$(LOCAL_PATH)/$(IRR_PATH)/include -DRC_ANDROID_BUILD
LOCAL_CPP_FEATURES += exceptions
LOCAL_CFLAGS := -I$(LOCAL_PATH)/$(THEORAPLAY_PATH) -DRC_ANDROID_BUILD
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include \
$(LOCAL_PATH)/$(SDL_IMAGE_PATH) \
$(LOCAL_PATH)/$(SDL_MIXER_PATH) \
$(LOCAL_PATH)/$(SDL_NET_PATH) \
$(LOCAL_PATH)/$(THEORA_PATH) \
$(LOCAL_PATH)/$(SDL_MIXER_PATH)/include \
$(LOCAL_PATH)/$(SDL_NET_PATH)/include \
$(LOCAL_PATH)/$(THEORA_PATH)/include \
$(LOCAL_PATH)/$(VORBIS_LIBRARY_PATH)/include \
$(LOCAL_PATH)/$(THEORAPLAY_PATH) \
$(LOCAL_PATH)/$(IRR_PATH)/include \
$(LOCAL_PATH)/$(BULLET_PATH)/src \
$(LOCAL_PATH)/$(IRRBULLET_PATH)/include \
$(LOCAL_PATH)/$(IRRTHEORA_PATH) \
$(LOCAL_PATH)/$(IRR_THEORA_PATH) \
$(LOCAL_PATH)/$(FREETYPE_PATH)/include \
$(LOCAL_PATH)/$(AN8_PATH) \
$(LOCAL_PATH)/$(BOX2D_PATH)/include
$(LOCAL_PATH)/$(BOX2D_PATH)/include \
$(LOCAL_PATH)/$(BULLET_PATH)/src \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(IRRLICHT_PATH)/include
# Add your application source files here...
LOCAL_SRC_FILES := main.cpp $(LOCAL_PATH)/$(THEORAPLAY_PATH)/theoraplay.c gui_freetype_font.cpp
LOCAL_SRC_FILES := main.cpp \
CShader.cpp \
gui_freetype_font.cpp \
ProjectiveTextures.cpp \
theoraplay.c
LOCAL_SRC_FILES += \
$(BOX2D_PATH)/src/collision/b2_broad_phase.cpp \
$(BOX2D_PATH)/src/collision/b2_chain_shape.cpp \
$(BOX2D_PATH)/src/collision/b2_circle_shape.cpp \
$(BOX2D_PATH)/src/collision/b2_collide_circle.cpp \
$(BOX2D_PATH)/src/collision/b2_collide_edge.cpp \
$(BOX2D_PATH)/src/collision/b2_collide_polygon.cpp \
$(BOX2D_PATH)/src/collision/b2_collision.cpp \
$(BOX2D_PATH)/src/collision/b2_distance.cpp \
$(BOX2D_PATH)/src/collision/b2_dynamic_tree.cpp \
$(BOX2D_PATH)/src/collision/b2_edge_shape.cpp \
$(BOX2D_PATH)/src/collision/b2_polygon_shape.cpp \
$(BOX2D_PATH)/src/collision/b2_time_of_impact.cpp \
$(BOX2D_PATH)/src/common/b2_block_allocator.cpp \
$(BOX2D_PATH)/src/common/b2_draw.cpp \
$(BOX2D_PATH)/src/common/b2_math.cpp \
$(BOX2D_PATH)/src/common/b2_settings.cpp \
$(BOX2D_PATH)/src/common/b2_stack_allocator.cpp \
$(BOX2D_PATH)/src/common/b2_timer.cpp \
$(BOX2D_PATH)/src/dynamics/b2_body.cpp \
$(BOX2D_PATH)/src/dynamics/b2_chain_circle_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_chain_polygon_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_circle_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_contact_manager.cpp \
$(BOX2D_PATH)/src/dynamics/b2_contact_solver.cpp \
$(BOX2D_PATH)/src/dynamics/b2_distance_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_edge_circle_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_edge_polygon_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_fixture.cpp \
$(BOX2D_PATH)/src/dynamics/b2_friction_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_gear_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_island.cpp \
$(BOX2D_PATH)/src/dynamics/b2_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_motor_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_mouse_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_polygon_circle_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_polygon_contact.cpp \
$(BOX2D_PATH)/src/dynamics/b2_prismatic_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_pulley_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_revolute_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_weld_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_wheel_joint.cpp \
$(BOX2D_PATH)/src/dynamics/b2_world_callbacks.cpp \
$(BOX2D_PATH)/src/dynamics/b2_world.cpp \
$(BOX2D_PATH)/src/rope/b2_rope.cpp \
$(IRRBULLET_PATH)/src/irrBulletBoxShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletBvhTriangleMeshShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletCapsuleShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionCallBackInformation.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionObjectAffectorAttract.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionObjectAffector.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionObjectAffectorDelete.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionObject.cpp \
$(IRRBULLET_PATH)/src/irrBulletCollisionShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletcommon.cpp \
$(IRRBULLET_PATH)/src/irrBulletConeShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletConvexHullShape.cpp \
$(IRRBULLET_PATH)/src/irrBullet.cpp \
$(IRRBULLET_PATH)/src/irrBulletCylinderShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletGhostObject.cpp \
$(IRRBULLET_PATH)/src/irrBulletGImpactMeshShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletLiquidBody.cpp \
$(IRRBULLET_PATH)/src/irrBulletMotionState.cpp \
$(IRRBULLET_PATH)/src/irrBulletPhysicsDebug.cpp \
$(IRRBULLET_PATH)/src/irrBulletRayCastVehicle.cpp \
$(IRRBULLET_PATH)/src/irrBulletRigidBody.cpp \
$(IRRBULLET_PATH)/src/irrBulletSoftBody.cpp \
$(IRRBULLET_PATH)/src/irrBulletSphereShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletTriangleMeshShape.cpp \
$(IRRBULLET_PATH)/src/irrBulletWorld.cpp
# Add irrBullet source files
LOCAL_SRC_FILES += $(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletBoxShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletBvhTriangleMeshShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCapsuleShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionCallBackInformation.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionObjectAffectorAttract.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionObjectAffector.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionObjectAffectorDelete.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionObject.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCollisionShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletcommon.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletConeShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletConvexHullShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBullet.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletCylinderShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletGhostObject.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletGImpactMeshShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletLiquidBody.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletMotionState.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletPhysicsDebug.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletRayCastVehicle.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletRigidBody.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletSoftBody.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletSphereShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletTriangleMeshShape.cpp \
$(LOCAL_PATH)/$(IRR_BULLET_PATH)/src/irrBulletWorld.cpp
# LOCAL_SHARED_LIBRARIES := SDL2 SDL2_mixer SDL2_net ogg_shared vorbis64 theora
LOCAL_SHARED_LIBRARIES := SDL2 SDL2_mixer SDL2_net SDL2_ttf ogg_shared vorbis64 theora
LOCAL_STATIC_LIBRARIES := Irrlicht Box2d Bullet freetype
LOCAL_SHARED_LIBRARIES := SDL2 SDL2_image SDL2_mixer SDL2_net Irrlicht freetype-prebuilt
LOCAL_STATIC_LIBRARIES := Bullet-prebuilt android_native_app_glue
RC_TH_LOCAL_SHARED_LIBRARIES := ogg_shared vorbis64 theora
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
RC_TH_LOCAL_SHARED_LIBRARIES := ogg_shared tremor theora
LOCAL_CFLAGS += -DRC_USE_TREMOR -O2
endif
LOCAL_SHARED_LIBRARIES += $(RC_TH_LOCAL_SHARED_LIBRARIES)
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
include $(BUILD_SHARED_LIBRARY)

View File

@@ -0,0 +1,616 @@
#include "gui_freetype_font.h"
#include <SDL_ttf.h>
#if COMPILE_WITH_FREETYPE
#include <cassert>
#include <android/log.h>
#define LOGE(TAG, ...) __android_log_print(ANDROID_LOG_ERROR , TAG,__VA_ARGS__)
using namespace irr;
using namespace gui;
#ifdef _MSC_VER
#pragma warning(disable: 4996)
#endif
// --------------------------------------------------------
CGUITTGlyph::CGUITTGlyph()
: IReferenceCounted()
,cached(false)
,size(0)
,top(0)
,left(0)
,texw(0)
,texh(0)
,imgw(0)
,imgh(0)
,tex(NULL)
,top16(0)
,left16(0)
,texw16(0)
,texh16(0)
,imgw16(0)
,imgh16(0)
,tex16(NULL)
,image(NULL)
{
}
CGUITTGlyph::~CGUITTGlyph()
{
delete[] image;
}
//void CGUITTGlyph::cache(u32 idx_, CGUITTFace& ttFace_, video::IVideoDriver* driver_, irr::core::dimension2d<irr::u32> &largestSize)
void CGUITTGlyph::cache(u32 idx_, const CGUIFreetypeFont * freetypeFont)
{
assert(freetypeFont);
FT_Face face = freetypeFont->TrueTypeFace->face;
FT_Set_Pixel_Sizes(face, 0, size);
if ( size > freetypeFont->LargestGlyph.Height )
freetypeFont->LargestGlyph.Height = size;
if ( !FT_Load_Glyph(face, idx_, FT_LOAD_NO_HINTING|FT_LOAD_NO_BITMAP) )
{
FT_GlyphSlot glyph = face->glyph;
FT_Bitmap bits;
if (glyph->format == ft_glyph_format_outline )
{
if (!FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL))
{
bits = glyph->bitmap;
u8 *pt = bits.buffer;
delete[] image;
image = new u8[bits.width * bits.rows];
memcpy(image,pt,bits.width * bits.rows);
top = glyph->bitmap_top;
left = glyph->bitmap_left;
imgw = 1;
imgh = 1;
texw = bits.width;
texh = bits.rows;
for(;;)
{
if (imgw > texw)
{
break;
}
else
{
imgw <<= 1;
}
}
for(;;)
{
if (imgh > texh)
{
break;
}
else
{
imgh <<= 1;
}
}
if (imgw > imgh)
{
imgh = imgw;
}
else
{
imgw = imgh;
}
s32 offx = left;
s32 offy = size - top;
if ( offx+texw > freetypeFont->LargestGlyph.Width )
freetypeFont->LargestGlyph.Width = offx+texw;
if ( offy+texh > freetypeFont->LargestGlyph.Height )
freetypeFont->LargestGlyph.Height = offy+texh;
u32 *texd = new u32[imgw*imgh];
memset(texd,0,imgw*imgh*sizeof(u32));
u32 *texp = texd;
bool cflag = (freetypeFont->Driver->getDriverType() == video::EDT_DIRECT3D9);
for (int i = 0;i < bits.rows;i++)
{
u32 *rowp = texp;
for (int j = 0;j < bits.width;j++)
{
if (*pt)
{
if (cflag)
{
*rowp = *pt;
*rowp *= 0x01010101;
}
else
{
*rowp = *pt << 24;
*rowp |= 0xffffff;
}
}
else
{
*rowp = 0;
}
pt++;
rowp++;
}
texp += imgw;
}
c8 name[128];
sprintf(name,"ttf%d_%d_%p",idx_, size, freetypeFont );
video::IImage *img = freetypeFont->Driver->createImageFromData(video::ECF_A8R8G8B8,core::dimension2d<u32>(imgw,imgh),texd);
setGlyphTextureFlags(freetypeFont->Driver);
tex = freetypeFont->Driver->addTexture(name,img);
img->drop();
restoreTextureFlags(freetypeFont->Driver);
delete[] texd;
cached = true;
}
}
}
if (!FT_Load_Glyph(face,idx_,FT_LOAD_NO_HINTING|FT_LOAD_RENDER|FT_LOAD_MONOCHROME))
{
FT_GlyphSlot glyph = face->glyph;
FT_Bitmap bits = glyph->bitmap;
u8 *pt = bits.buffer;
top16 = glyph->bitmap_top;
left16 = glyph->bitmap_left;
imgw16 = 1;
imgh16 = 1;
texw16 = bits.width;
texh16 = bits.rows;
for(;;)
{
if (imgw16 >= texw16)
{
break;
}
else
{
imgw16 <<= 1;
}
}
for(;;)
{
if (imgh16 >= texh16)
{
break;
}
else
{
imgh16 <<= 1;
}
}
if (imgw16 > imgh16)
{
imgh16 = imgw16;
}
else
{
imgw16 = imgh16;
}
s32 offx = left;
s32 offy = size - top;
if ( offx+texw > freetypeFont->LargestGlyph.Width )
freetypeFont->LargestGlyph.Width = offx+texw;
if ( offy+texh > freetypeFont->LargestGlyph.Height )
freetypeFont->LargestGlyph.Height = offy+texh;
u16 *texd16 = new u16[imgw16*imgh16];
memset(texd16,0,imgw16*imgh16*sizeof(u16));
u16 *texp16 = texd16;
for (int y = 0;y < bits.rows;y++)
{
u16 *rowp = texp16;
for (int x = 0;x < bits.width;x++)
{
if (pt[y * bits.pitch + (x / 8)] & (0x80 >> (x % 8)))
{
*rowp = 0xffff;
}
rowp++;
}
texp16 += imgw16;
}
c8 name[128];
sprintf(name,"ttf%d_%d_%p_16",idx_, size, freetypeFont );
video::IImage *img = freetypeFont->Driver->createImageFromData(video::ECF_A1R5G5B5,core::dimension2d<u32>(imgw16,imgh16),texd16);
setGlyphTextureFlags(freetypeFont->Driver);
tex16 = freetypeFont->Driver->addTexture(name,img);
img->drop();
restoreTextureFlags(freetypeFont->Driver);
// freetypeFont->Driver->makeColorKeyTexture(tex16,video::SColor(0,0,0,0));
delete[] texd16;
}
}
bool CGUITTGlyph::mTexFlag16 = false;
bool CGUITTGlyph::mTexFlag32 = true;
bool CGUITTGlyph::mTexFlagMip = false;
void CGUITTGlyph::setGlyphTextureFlags(video::IVideoDriver* driver_)
{
mTexFlag16 = driver_->getTextureCreationFlag(video::ETCF_ALWAYS_16_BIT);
mTexFlag32 = driver_->getTextureCreationFlag(video::ETCF_ALWAYS_32_BIT);
mTexFlagMip = driver_->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
driver_->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT,false);
driver_->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
driver_->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
}
void CGUITTGlyph::restoreTextureFlags(video::IVideoDriver* driver_)
{
driver_->setTextureCreationFlag(video::ETCF_ALWAYS_16_BIT, mTexFlag16);
driver_->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, mTexFlag32);
driver_->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mTexFlagMip);
}
// --------------------------------------------------------
FT_Library CGUITTFace::library = 0;
int CGUITTFace::countClassObjects = 0;
bool CGUITTFace::ttf_init = false;
CGUITTFace::CGUITTFace()
: face(0)
{
++countClassObjects;
is_sdl = false;
if(!ttf_init)
{
TTF_Init();
ttf_init = true;
}
}
CGUITTFace::~CGUITTFace()
{
if( is_sdl )
{
TTF_CloseFont(sdl_font);
face = NULL;
sdl_font = NULL;
}
if ( face )
FT_Done_Face( face );
--countClassObjects;
assert(countClassObjects >= 0 );
if ( !countClassObjects && library )
{
FT_Done_FreeType( library );
library = 0;
}
}
//! loads a font file
bool CGUITTFace::load(const irr::io::path& filename)
{
//TTF_Font* sdl_font = TTF_Open
if ( !library )
{
if (FT_Init_FreeType( &library ))
{
return false;
}
}
core::stringc ansiFilename(filename); // path can be anything but freetype can only work with ansi-filenames
if (FT_New_Face( library,ansiFilename.c_str(),0,&face ))
{
return false;
}
return true;
}
// --------------------------------------------------------
//! constructor
CGUIFreetypeFont::CGUIFreetypeFont(video::IVideoDriver* driver)
: Driver(driver)
, TrueTypeFace(0)
{
#ifdef _DEBUG
setDebugName("CGUIFreetypeFont");
#endif
if (Driver)
Driver->grab();
AntiAlias = false;
Transparency = false;
}
//! destructor
CGUIFreetypeFont::~CGUIFreetypeFont()
{
if ( TrueTypeFace )
TrueTypeFace->drop();
if (Driver)
Driver->drop();
clearGlyphs();
}
bool CGUIFreetypeFont::attach(CGUITTFace *Face,u32 size)
{
if (!Driver || !Face)
return false;
Face->grab();
if ( TrueTypeFace )
TrueTypeFace->drop();
TrueTypeFace = Face;
if ( !TrueTypeFace )
return false;
clearGlyphs();
Glyphs.reallocate(TrueTypeFace->face->num_glyphs);
Glyphs.set_used(TrueTypeFace->face->num_glyphs);
for (int i = 0;i < TrueTypeFace->face->num_glyphs;i++)
{
CGUITTGlyph * glyph = new CGUITTGlyph();
glyph->size = size;
// glyph->cache((wchar_t)i + 1);
Glyphs[i] = glyph;
}
// TODO: this is a workaround to get a probably ok height for getDimensions. So we check a few extreme characters which usually make trouble.
getGlyphByChar(L'A');
getGlyphByChar(L'g');
getGlyphByChar(L'.');
getGlyphByChar(L'(');
return true;
}
bool CGUIFreetypeFont::sdl_loadfont(irr::io::path font_file,irr::u32 size)
{
if (!Driver)
return false;
CGUITTFace *Face = new CGUITTFace();
if(!Face)
return false;
TTF_Font* sdl_font = TTF_OpenFont(font_file.c_str(), size);
if(!sdl_font)
{
LOGE("RCTEST", "TTF_OpenFont(%s) FAILED -> error: %s", font_file.c_str(), TTF_GetError());
delete Face;
return false;
}
Face->face = (FT_Face)TTF_GetFreeTypeFace(sdl_font);
Face->is_sdl = true;
Face->grab();
if ( TrueTypeFace )
TrueTypeFace->drop();
TrueTypeFace = Face;
if ( !TrueTypeFace )
return false;
clearGlyphs();
Glyphs.reallocate(TrueTypeFace->face->num_glyphs);
Glyphs.set_used(TrueTypeFace->face->num_glyphs);
for (int i = 0;i < TrueTypeFace->face->num_glyphs;i++)
{
CGUITTGlyph * glyph = new CGUITTGlyph();
glyph->size = size;
// glyph->cache((wchar_t)i + 1);
Glyphs[i] = glyph;
}
// TODO: this is a workaround to get a probably ok height for getDimensions. So we check a few extreme characters which usually make trouble.
getGlyphByChar(L'A');
getGlyphByChar(L'g');
getGlyphByChar(L'.');
getGlyphByChar(L'(');
return true;
}
CGUITTFace* CGUIFreetypeFont::getFace()
{
return TrueTypeFace;
}
void CGUIFreetypeFont::clearGlyphs()
{
for ( unsigned int i=0; i < Glyphs.size(); ++i )
{
if ( Glyphs[i] )
{
Glyphs[i]->drop();
}
Glyphs[i] = 0;
}
}
u32 CGUIFreetypeFont::getGlyphByChar(wchar_t c) const
{
u32 idx = FT_Get_Char_Index( TrueTypeFace->face, c );
if ( idx && !Glyphs[idx - 1]->cached )
Glyphs[idx - 1]->cache(idx, this);
return idx;
}
//! returns the dimension of a text
core::dimension2d<u32> CGUIFreetypeFont::getDimension(const wchar_t* text) const
{
core::dimension2d<u32> dim(0, Glyphs[0]->size);
for(const wchar_t* p = text; *p; ++p)
{
dim.Width += getWidthFromCharacter(*p);
}
// TODO: The correct solution might be working with TrueTypeFace->height but I can't figure out how to use units_per_EM
// even if I know which FT_Render_Mode I used. I'm sure there is some way to figure that out, but I have to give up for now.
if ( TrueTypeFace && LargestGlyph.Height > dim.Height)
dim.Height = LargestGlyph.Height;
return dim;
}
inline u32 CGUIFreetypeFont::getWidthFromCharacter(wchar_t c) const
{
u32 n = getGlyphByChar(c);
if ( n > 0)
{
int w = Glyphs[n - 1]->texw;
s32 left = Glyphs[n - 1]->left;
if (w + left > 0)
return w + left;
}
if (c >= 0x2000)
{
return Glyphs[0]->size;
}
else
{
return Glyphs[0]->size / 2;
}
}
//! draws an text and clips it to the specified rectangle if wanted
void CGUIFreetypeFont::draw(const irr::core::stringw& textstring, const irr::core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{
if (!Driver)
return;
core::dimension2d<s32> textDimension;
core::position2d<s32> offset = position.UpperLeftCorner;
video::SColor colors[4];
for (int i = 0;i < 4;i++)
{
colors[i] = color;
}
const wchar_t * text = textstring.c_str();
if (hcenter || vcenter)
{
textDimension = getDimension(text);
if (hcenter)
offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X;
if (vcenter)
offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y;
}
u32 n;
while(*text)
{
n = getGlyphByChar(*text);
if ( n > 0)
{
if (AntiAlias)
{
// s32 imgw = Glyphs[n-1]->imgw;
// s32 imgh = Glyphs[n-1]->imgh;
s32 texw = Glyphs[n-1]->texw;
s32 texh = Glyphs[n-1]->texh;
s32 offx = Glyphs[n-1]->left;
s32 offy = Glyphs[n-1]->size - Glyphs[n-1]->top;
if (Driver->getDriverType() != video::EDT_SOFTWARE)
{
if (!Transparency)
color.color |= 0xff000000;
Driver->draw2DImage(Glyphs[n-1]->tex,core::position2d<s32>(offset.X+offx,offset.Y+offy),core::rect<s32>(0,0,texw,texh),clip,color,true);
}
else
{
s32 a = color.getAlpha();
s32 r = color.getRed();
s32 g = color.getGreen();
s32 b = color.getBlue();
u8 *pt = Glyphs[n-1]->image;
if (!Transparency) a = 255;
for (int y = 0;y < texh;y++)
{
for (int x = 0;x < texw;x++)
{
if (!clip || clip->isPointInside(core::position2d<s32>(offset.X+x+offx,offset.Y+y+offy)))
{
if (*pt)
{
Driver->draw2DRectangle(video::SColor((a * *pt)/255,r,g,b),core::rect<s32>(offset.X+x+offx,offset.Y+y+offy,offset.X+x+offx+1,offset.Y+y+offy+1));
}
pt++;
}
}
}
}
}
else
{
// s32 imgw = Glyphs[n-1]->imgw16;
// s32 imgh = Glyphs[n-1]->imgh16;
s32 texw = Glyphs[n-1]->texw16;
s32 texh = Glyphs[n-1]->texh16;
s32 offx = Glyphs[n-1]->left16;
s32 offy = Glyphs[n-1]->size - Glyphs[n-1]->top16;
if (!Transparency)
{
color.color |= 0xff000000;
}
Driver->draw2DImage(Glyphs[n-1]->tex16,
core::position2d<s32>(offset.X+offx,offset.Y+offy),
core::rect<s32>(0,0,texw,texh),
clip, color, true);
}
offset.X += getWidthFromCharacter(*text);
}
else
{
offset.X += getWidthFromCharacter(*text);
}
++text;
}
}
//! Calculates the index of the character in the text which is on a specific position.
s32 CGUIFreetypeFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
{
s32 x = 0;
s32 idx = 0;
while (text[idx])
{
x += getWidthFromCharacter(text[idx]);
if (x >= pixel_x)
return idx;
++idx;
}
return -1;
}
#endif // #if COMPILE_WITH_FREETYPE

View File

@@ -0,0 +1,141 @@
#include "rc_os_defines.h"
#ifndef _GUI_FREETYPE_FONT_H
#define _GUI_FREETYPE_FONT_H
//! freetype support enabled with 1 and disabled with 0
#define COMPILE_WITH_FREETYPE 1
#if COMPILE_WITH_FREETYPE
#ifdef RC_ANDROID
#include "ft2build.h"
#include "freetype/freetype.h"
#include <SDL_ttf.h>
#else
#include <freetype2/ft2build.h>
#include <freetype/freetype.h>
#endif // RC_ANDROID
#include <irrlicht.h>
class CGUITTFace : public irr::IReferenceCounted
{
public:
CGUITTFace();
virtual ~CGUITTFace();
bool load(const irr::io::path& filename);
FT_Face face; // handle to face
bool is_sdl;
private:
static bool ttf_init;
static int countClassObjects;
static FT_Library library; // handle to library
TTF_Font* sdl_font;
};
class CGUIFreetypeFont;
class CGUITTGlyph : public irr::IReferenceCounted
{
public:
CGUITTGlyph();
virtual ~CGUITTGlyph();
bool cached;
void cache(irr::u32 idx_, const CGUIFreetypeFont * freetypeFont);
irr::u32 size;
irr::u32 top;
irr::u32 left;
irr::u32 texw;
irr::u32 texh;
irr::u32 imgw;
irr::u32 imgh;
irr::video::ITexture *tex;
irr::u32 top16;
irr::u32 left16;
irr::u32 texw16;
irr::u32 texh16;
irr::u32 imgw16;
irr::u32 imgh16;
irr::video::ITexture *tex16;
irr::u8 *image;
private:
void setGlyphTextureFlags(irr::video::IVideoDriver* driver_);
void restoreTextureFlags(irr::video::IVideoDriver* driver_);
static bool mTexFlag16;
static bool mTexFlag32;
static bool mTexFlagMip;
};
class CGUIFreetypeFont : public irr::gui::IGUIFont
{
friend class CGUITTGlyph;
public:
//! constructor
CGUIFreetypeFont(irr::video::IVideoDriver* Driver);
//! destructor
virtual ~CGUIFreetypeFont();
//! loads a truetype font file
bool attach(CGUITTFace *Face,irr::u32 size);
//! loads a truetype font file using SDL2
bool sdl_loadfont(irr::io::path font_file,irr::u32 size);
CGUITTFace* getFace();
//! draws an text and clips it to the specified rectangle if wanted
virtual void draw(const irr::core::stringw& text, const irr::core::rect<irr::s32>& position, irr::video::SColor color, bool hcenter=false, bool vcenter=false, const irr::core::rect<irr::s32>* clip=0);
//! returns the dimension of a text
virtual irr::core::dimension2d<irr::u32> getDimension(const wchar_t* text) const;
//! Calculates the index of the character in the text which is on a specific position.
virtual irr::s32 getCharacterFromPos(const wchar_t* text, irr::s32 pixel_x) const;
//! Not yet supported
virtual void setKerningWidth (irr::s32 kerning) {}
//! Not yet supported
virtual void setKerningHeight (irr::s32 kerning) {}
//! Not yet supported
virtual irr::s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const { return 0; }
//! Not yet supported
virtual irr::s32 getKerningHeight() const { return 0; }
//! Not yet supported
virtual void setInvisibleCharacters( const wchar_t *s ) {}
bool AntiAlias;
bool Transparency;
protected:
void clearGlyphs();
private:
irr::u32 getWidthFromCharacter(wchar_t c) const;
irr::u32 getGlyphByChar(wchar_t c) const;
irr::video::IVideoDriver* Driver;
irr::core::array< CGUITTGlyph* > Glyphs;
CGUITTFace * TrueTypeFace;
mutable irr::core::dimension2d<irr::u32> LargestGlyph;
};
#endif // #if COMPILE_WITH_FREETYPE
#endif // _GUI_FREETYPE_FONT_H