首先,jni本地绘图,也就是linux好像是不能直接绘制文字,然后就想到通过java,当然如果都给java画那底层就乱了。
还有Native是用opengles,所以理论上获取文字buffer就可以了。
然后就是实现步骤:
C告诉java,我要画文字,文字的大小,颜色 ->java生成buffer->给C绘图。
1:C叫java
int Jni_DrawText(const wchar_t*str,int sx,int sy,int color)
{
//JNIEnv *env;
//JavaVM *jvm;
long status;
jclass cls;
jmethodID mid;
jboolean not;
jobject jobj;
JNIEnv* Javaenv;
DEBUG("Jni_DrawText");
{
(*Javavm)->GetEnv(Javavm,(void**)&Javaenv, JNI_VERSION_1_6); // 获得当前线程可以使用的 JNIEnv * 指针
cls = (*Javaenv)->FindClass(Javaenv,"com/sfapi/SFRenderer");
DEBUG("Jni_DrawText1");
if (cls !=0) {
mid =(*Javaenv)->GetStaticMethodID(Javaenv,cls, "drawText", "(Ljava/lang/String;III)V");
if (mid !=0) {
jstring jstr;
int ilen = strlen(str)*4+1;
char *cchar=malloc(ilen);
ucs2_to_utf8(cchar,ilen,str,-1,SFNull);
jstr= (*Javaenv)->NewStringUTF(Javaenv,cchar);
(*Javaenv)->CallStaticVoidMethod(Javaenv,cls, mid,jstr, sx,sy,-1);
free(cchar);
}
}
//(*Javavm)-> DetachCurrentThread(Javavm);
//(*jvm)->DestroyJavaVM(jvm);
return 0;
}
}
2:JAVA端生成文字buffer
public static void drawText(String mstr,int sx,int sy,int color)
{
int colorbg = 0;
boolean bWhiteColor=false;
int iWordHigh ;
int iWordWidth;
String familyName ="宋体";
Typeface font = Typeface.create(familyName,Typeface.BOLD);
Paint pt = new Paint();
pt.setColor(Color.YELLOW);
pt.setTypeface(font);
pt.setTextSize(25);
FontMetrics fm = pt.getFontMetrics();
iWordWidth =(int)pt.measureText(mstr);
iWordHigh=(int) Math.ceil(fm.descent - fm.top);
Bitmap bmp = Bitmap.createBitmap(iWordWidth,iWordHigh, Bitmap.Config.ARGB_8888); //图象大小要根据文字大小算下,以和文本长度对应
Canvas canvasTemp = new Canvas(bmp);
color = Color.BLACK;
if(color == Color.WHITE)
{
colorbg = Color.BLACK;
bWhiteColor =false;
}
else
{
colorbg= Color.WHITE;
bWhiteColor =true;
}
//String mstrTitle = "Hello 中国字";
canvasTemp.drawColor(colorbg);
canvasTemp.drawText(mstr,0,0-fm.top,pt); //注意Drawtext的第二个参数为基准线(baseline),
//参考这里http://fonter.javaeye.com/blog/474526,所以取值为0-fm.top
int[] buffer = new int[iWordWidth*iWordHigh];
Log.v("drawText","drawText");
bmp.getPixels(buffer, 0, iWordWidth, 0, 0, iWordWidth, iWordHigh);
short[] array= intToWord(buffer);//把int数组转成short,因为opengles要的是byte数组,所以这里先转换一下
Log.v("drawText2","drawText2");
DrawTextBack(array,sx,sy,iWordWidth,iWordHigh,bWhiteColor);
}
private static short []intToWord(int [] parValue) { //这里很经典的RGB_888转RGB_565色的方法
short retValue [] = new short [parValue.length];
for(int i = 0;i<parValue.length;i++)
{
int iRgb = parValue[i];
retValue[i] =(short) (((( iRgb)>>>3)&0x1f)|((( iRgb)>>>5)&0x7E0)|((( iRgb)>>>8)&0xF800));
}
return (retValue);
}
3:C端处理显示:
(1)首先是jni函数
void Java_com_sfapi_SFRenderer_DrawTextBack( JNIEnv* env , jobject thiz,jshortArray arr,jint x ,jint y,jint width,jint high,jboolean bWhite)
{
jshort *sarr;
int size = (*env)->GetArrayLength(env, arr);
sarr =(*env)->GetShortArrayElements(env,arr,0);
Jni_DrawTextBack(sarr,size,x,y,width,high,bWhite);
(*env)->ReleaseShortArrayElements(env, arr, sarr, 0);
}
(2)然后是绘制函数
void Jni_DrawTextBack(void *arrbuffer,int length,int x,int y,int iwidth,int ihigh,int bWhite)
{
DEBUG("Jni_DrawTextBack");
__android_log_print(ANDROID_LOG_INFO, "Jni_DrawTextBack", "length = %d",length);
//略,这里每个人方法不一样了,我这里也给不了参考,总之拿到的buffer已经是文字的buffer,只不过是
//带背景色,通过bWhite来检查背景色是白色还是黑色,来过滤显示,然后把这个buffer贴到材质buffer上去显示
//就ok了,至于怎么显示可以看我前面的blog
}