[原创]JNI绘制文字的方法

首先,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

}

你可能感兴趣的:(java,jvm,android,String,jni,buffer)