diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/java/android/graphics/Canvas.java | 129 |
1 files changed, 68 insertions, 61 deletions
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 061b55f..62d43eb 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1233,108 +1233,118 @@ public class Canvas { indices, indexOffset, indexCount, paint.mNativePaint); } - /** @hide */ - public char[] bidiProcess(char[] text,int start,int src_count) { - String str; - String oldstr=new String(text,start,src_count); - boolean hasbidi=false; - int strlen=oldstr.length(); - char[] ca=new char[strlen]; - - oldstr.getChars(0, strlen, ca, 0); - for (int i=0;i<oldstr.length();i++){ - if (ca[i]>=FIRST_RIGHT_TO_LEFT&&ca[i]<=LAST_RIGHT_TO_LEFT){ - hasbidi=true; + /** + * A lightweight BiDi processing to make all draw text work with RTL languages. + * written from scratch by David Kohen (kohen dot d at gmail dot com) - 2010 + * @hide + **/ + public char[] bidiProcess(char[] text,int start,int srcCount) { + + boolean hasBidi=false; + char[] destCharArray=new char[srcCount]; + + char[] buf = TemporaryBuffer.obtain(srcCount); + System.arraycopy(text,start, buf, 0, srcCount); + + // Check if there are BiDi characters in the string, of so, we need to work. + for (int i=0;i<srcCount;i++){ + if (buf[i]>=FIRST_RIGHT_TO_LEFT&&buf[i]<=LAST_RIGHT_TO_LEFT){ + hasBidi=true; break; } } - if (hasbidi) { - char[] ca2=new char[strlen]; - int count=0,srcindex=0; - boolean rtlmode=true; - for (int i=0;i<strlen;i++){ - srcindex=strlen-1-i; - if (ca[srcindex]>=FIRST_RIGHT_TO_LEFT&&ca[srcindex]<=LAST_RIGHT_TO_LEFT){ - ca2[i]=ca[srcindex]; - rtlmode=true; + if (hasBidi) { + // I'm doing the processing from the end of the string, since it worked well this way. + int count=0,srcIndex=0; + boolean rtlMode=true; + for (int i=0;i<srcCount;i++){ + srcIndex=srcCount-1-i; + if (buf[srcIndex]>=FIRST_RIGHT_TO_LEFT&&buf[srcIndex]<=LAST_RIGHT_TO_LEFT){ + destCharArray[i]=buf[srcIndex]; + // In rtl mode I'm mirroring glyphs. + rtlMode=true; } else { - srcindex=strlen-1-i; + srcIndex=srcCount-1-i; if (count==0) { - if (ca[srcindex]<='\u002f' || - (ca[srcindex]>'\u0039' && ca[srcindex]<='\u0040') || - (ca[srcindex]>'\u005a' && ca[srcindex]<='\u0060')|| - (ca[srcindex]>'\u007a' && ca[srcindex]<='\u00BF')) { - - if (rtlmode){ - switch (ca[srcindex]) { + // Direction neutral characters + if (buf[srcIndex]<='\u002f' || + (buf[srcIndex]>'\u0039' && buf[srcIndex]<='\u0040') || + (buf[srcIndex]>'\u005a' && buf[srcIndex]<='\u0060')|| + (buf[srcIndex]>'\u007a' && buf[srcIndex]<='\u00BF')) { + + if (rtlMode){ + switch (buf[srcIndex]) { case '[': - ca2[i]=']'; + destCharArray[i]=']'; break; case ']': - ca2[i]='['; + destCharArray[i]='['; break; case '}': - ca2[i]='{'; + destCharArray[i]='{'; break; case '{': - ca2[i]='}'; + destCharArray[i]='}'; break; case '(': - ca2[i]=')'; + destCharArray[i]=')'; break; case ')': - ca2[i]='('; + destCharArray[i]='('; break; case '>': - ca2[i]='<'; + destCharArray[i]='<'; break; case '<': - ca2[i]='>'; + destCharArray[i]='>'; break; default: - ca2[i]=ca[srcindex]; + destCharArray[i]=buf[srcIndex]; break; } - } else ca2[i]=ca[srcindex]; + } else destCharArray[i]=buf[srcIndex]; } else { - - while (((srcindex-count)>=0)&&((ca[srcindex-count]<FIRST_RIGHT_TO_LEFT)||(ca[srcindex-count]>LAST_RIGHT_TO_LEFT))){ + // Handling LTR embedded strings. + while (((srcIndex-count)>=0)&&((buf[srcIndex-count]<FIRST_RIGHT_TO_LEFT)||(buf[srcIndex-count]>LAST_RIGHT_TO_LEFT))){ count++; } int index=0; - int punctuation_marks=0; - - while (count>0 && (srcindex-(count)>=0) && - (ca[srcindex-(count-1)]<='\u002f' || - (ca[srcindex-(count-1)]>'\u0039' && ca[srcindex-(count-1)]<='\u0040') || - (ca[srcindex-(count-1)]>'\u005a' && ca[srcindex-(count-1)]<='\u0060')|| - (ca[srcindex-(count-1)]>'\u007a' && ca[srcindex-(count-1)]<='\u00BF'))){ - ca2[i+(count-1)]=ca[srcindex-(count-1)]; + int punctuationMarks=0; + + // Handling direction neutral characters in the middle of LTR + while (count>0 && (srcIndex-(count)>=0) && + (buf[srcIndex-(count-1)]<='\u002f' || + (buf[srcIndex-(count-1)]>'\u0039' && buf[srcIndex-(count-1)]<='\u0040') || + (buf[srcIndex-(count-1)]>'\u005a' && buf[srcIndex-(count-1)]<='\u0060')|| + (buf[srcIndex-(count-1)]>'\u007a' && buf[srcIndex-(count-1)]<='\u00BF'))){ + destCharArray[i+(count-1)]=buf[srcIndex-(count-1)]; count--; - punctuation_marks++; + punctuationMarks++; } while (count>0){ - ca2[i+index]=ca[srcindex-(count-1)]; + destCharArray[i+index]=buf[srcIndex-(count-1)]; count--; index++; } - count=index+punctuation_marks-1; + count=index+punctuationMarks-1; } } else { + // Avoiding spaghetti code and mangling of loop counter count--; } - rtlmode=false; + rtlMode=false; } } - str=new String(ca2); } else { - str=new String(oldstr); + // We don't want to return a temporary buffer, do we? + System.arraycopy(buf, 0 , destCharArray, 0, srcCount); + TemporaryBuffer.recycle(buf); } - return str.toCharArray(); + return destCharArray; } @@ -1422,10 +1432,9 @@ public class Canvas { if ((start | end | (end - start) | (text.length() - end)) < 0) { throw new IndexOutOfBoundsException(); } - int i = 0; String bidiText; bidiText=new String(bidiProcess(text.toCharArray(),start,end-start)); - native_drawText(mNativeCanvas, bidiText, i, end-start, x, y, + native_drawText(mNativeCanvas, bidiText, 0, end-start, x, y, paint.mNativePaint); } @@ -1550,10 +1559,9 @@ public class Canvas { if (index < 0 || index + count > text.length) { throw new ArrayIndexOutOfBoundsException(); } - int i = 0; char[] bidiText; bidiText=bidiProcess(text,index,count); - native_drawTextOnPath(mNativeCanvas, bidiText, i, count, + native_drawTextOnPath(mNativeCanvas, bidiText, 0, count, path.ni(), hOffset, vOffset, paint.mNativePaint); } @@ -1574,7 +1582,6 @@ public class Canvas { public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { if (text.length() > 0) { - int i = 0; String bidiText; bidiText=new String(bidiProcess(text.toCharArray(),0,text.length())); native_drawTextOnPath(mNativeCanvas, bidiText, path.ni(), |