// // Latex Project Public Licence (lppl1.3) applies // Originally written by Kwanleung Tse // First Release : 1st July, 2014 // Last Update : 25th September, 2014 // // package worker4math.hktex2; import java.util.ArrayList; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.SparseBooleanArray; public class Parsetable { public static volatile SparseArray thisypos = new SparseArray(); public static volatile SparseBooleanArray error = new SparseBooleanArray(); public static volatile SparseArray errormessage = new SparseArray(); public void parsetable(Canvas canvas, Block block, ParagraphBlock paragraphblock, Integer tid, Integer containerwidth, Integer containerheight, Integer tablelinenumber, ArrayList tablehlinecounter, Integer superblocknumber, SuperBlock superblock ,SparseArray> superblockline,SparseIntArray superblocknumline,SparseIntArray superblockstartline, SparseIntArray superblockendline, ArrayList tf , String columnspec, Float ypos, String attribute2, String attribute) { int i,j,ii; int k=0; int tid2=tid*1000; int captionnumline=-1; int viewportwidth=containerwidth-Header.leftsidemargin-Header.rightsidemargin; int adjustline=0; float linegap = Header.linegap; float columngap=Header.columngap; float totalwidth=0.0f; float adjusty=ypos; float adjustx=0.0f; float adjustx2=0.0f; float shiftx=0.0f; float thisypos2=0; String blockline = new String(); String rawblockline = new String(); String thisattribute=attribute; String columnspec2=new String(); String currentline=""; ArrayList columnwidth = new ArrayList(); ArrayList lineheight = new ArrayList(); ArrayList linedepth = new ArrayList(); ArrayList blockwidth = new ArrayList(); ArrayList blockheight = new ArrayList(); ArrayList blockdepth = new ArrayList(); ArrayList tablevlinecounter = new ArrayList(); ArrayList captionline = new ArrayList(); ArrayList tatom = new ArrayList(); ArrayList txpos = new ArrayList(); ArrayList typos = new ArrayList(); ArrayList tattribute = new ArrayList(); error.put(tid,false); errormessage.put(tid,""); thisypos.put(tid,ypos); columnspec2=""; int tablehlinenumber=-1; for (i=0;i<=tablelinenumber;i++){ tablehlinenumber=tablehlinenumber+(tablehlinecounter.get(i)+1); } tablevlinecounter.add(-1); for (i=0;i<=columnspec.length()-1;i++){ if (columnspec.charAt(i)=='|') {tablevlinecounter.set(tablevlinecounter.size()-1,tablevlinecounter.get(tablevlinecounter.size()-1)+1);} else if (columnspec.charAt(i)=='l' || columnspec.charAt(i)=='r' || columnspec.charAt(i)=='c'){columnspec2=columnspec2+columnspec.charAt(i); tablevlinecounter.add(-1);} } int numcolumn = columnspec2.length(); columnwidth.clear();lineheight.clear();linedepth.clear(); Paint textpaint = new Paint(); Rect textbounds = new Rect(); textpaint.setTextSize(Integer.parseInt(attribute.substring(1,4))); textpaint.setTypeface(tf.get(Integer.parseInt(attribute.substring(4,7)))); textpaint.getTextBounds("Aj",0,"Aj".length(),textbounds); float spacewidth=textpaint.measureText(" "); float spaceheight=textbounds.height(); float spacedepth=textbounds.bottom; Boolean captionattop=false; int tablefirstline=superblockstartline.get(superblocknumber); int tablelastline=superblockendline.get(superblocknumber); int lastline=superblockendline.get(superblocknumber)-superblockstartline.get(superblocknumber); String sfontsize; for (i=0;i<=lastline;i++){ currentline=superblockline.get(superblocknumber).get(i); String line=currentline.trim(); if (line.length() >=15 && line.substring(0,15).equals("!begin{caption}")){ if (i==0){captionattop=true;adjustline=2;} else {captionattop=false;adjustline=0;}; Boolean caption=true; i++; currentline=superblockline.get(superblocknumber).get(i); line=currentline.trim(); if (line.length() >=13 && line.substring(0,13).equals("!end{caption}")){caption=false;i++;captionnumline++;} while(caption){ j=line.indexOf("!!"); line=line.substring(0,j); captionline.add(line); i++;captionnumline++; currentline=superblockline.get(superblocknumber).get(i); line=currentline.trim(); if (line.length() >=13 && line.substring(0,13).equals("!end{caption}")){caption=false;i++;} } tablelinenumber=tablelinenumber-captionnumline-1; if(captionattop){tablefirstline=i+tablefirstline; currentline=superblockline.get(superblocknumber).get(i);} else {tablelastline=tablefirstline+tablelinenumber-1;} } } // Add top caption SuperBlock.tablestartline.put(tid2+SuperBlock.tablenumber.get(tid), SuperBlock.superblocklinenumber.get(tid)+1); if (captionattop){ Parsetext table = new Parsetext(); for (i=0;i<=captionnumline;i++){ sfontsize=Integer.toString(Header.fontsize); if (sfontsize.length()==1){ attribute2 = "100"+sfontsize+"002"+attribute2.substring(7); } else if (sfontsize.length()==2){ attribute2 = "10"+sfontsize+"002"+attribute2.substring(7); } else if (sfontsize.length()==3){ attribute2 = "1"+sfontsize+"002"+attribute2.substring(7); } table.parsetext(canvas, block, paragraphblock, tid, containerwidth, containerheight, superblocknumber, superblock, captionline.get(i), Header.leftsidemargin , adjusty, tf, attribute2, attribute, false, 0.0f); thisypos2=Parsetext.thisypos.get(tid); error.put(tid, Parsetext.error.get(tid)); if (error.get(tid)){errormessage.put(tid, Parsetext.errormessage.get(tid)); return;}; adjustx=(viewportwidth-SuperBlock.superblocklinewidth.get(tid).get(SuperBlock.superblocklinewidth.get(tid).size()-1))/2; for (int ij=0;ij<=SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).size()-1;ij++){ SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(ij,SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).get(ij)+adjustx); } adjusty=Parsetext.thisypos.get(tid); thisypos.put(tid,adjusty); }} Boolean firstline=true; for (i=tablefirstline;i<=tablelastline;i++){ if (!captionattop){ currentline=superblockline.get(superblocknumber).get(i-tablefirstline); } else { currentline=superblockline.get(superblocknumber).get(i-tablefirstline+captionnumline+3); } lineheight.add(0.0f); linedepth.add(0.0f); synchronized(this){superblock.create(tid);} for (ii=0;ii<=numcolumn-1;ii++){ // First parse if (firstline) columnwidth.add(0.0f); if (ii<=numcolumn-2){ j=currentline.indexOf("&"); if (j<0){error.put(tid, true);errormessage.put(tid, "Format error in table, parse failed !!");return;}; rawblockline=currentline.substring(0,j); currentline=currentline.substring(j+1); if (rawblockline.equals("")){rawblockline="!dno ";}; } else { rawblockline=currentline; if (rawblockline.equals("")){rawblockline="!dno ";}; } Parsepreparation prepareblockline = new Parsepreparation(); blockline=prepareblockline.parsepreparation(rawblockline,Symbol.symboltype,Symbol.matchsymbol); Parseblock parseblockline = new Parseblock(); parseblockline.parseblock(tid,canvas,block, blockline,tf,thisattribute); if (Block.error.get(tid)==true){error.put(tid, true); errormessage.put(tid, Block.errormessage.get(tid)); return;}; blockwidth.add(Math.max(Block.blockwidth2.get(tid),spacewidth)); blockheight.add(Math.max(Block.blockheight2.get(tid),spaceheight)); blockdepth.add(Math.max(Block.blockdepth2.get(tid),spacedepth)); superblock.add(tid,Block.subblock2,Block.subblockxpos2, Block.subblockypos2, Block.subblockattribute2, blockwidth.get(blockwidth.size()-1), blockheight.get(blockheight.size()-1), blockdepth.get(blockdepth.size()-1),'t',ii); columnwidth.set(ii,Math.max(columnwidth.get(ii), blockwidth.get(blockwidth.size()-1))); } } firstline=false; // add vertical lines int totalvline=0; for (ii=0;ii<=numcolumn;ii++){ for (k=0;k<=tablevlinecounter.get(ii);k++){ tatom.add("!vlin "); txpos.add(0.0f); typos.add(0.0f); tattribute.add(attribute); totalvline++; } synchronized(this){ superblock.add(tid,tatom,txpos, typos, tattribute,0.0f,0.0f,0.0f,'t',numcolumn-1);} tatom.clear(); txpos.clear(); typos.clear(); tattribute.clear(); } // add horizontal lines int totalhline=0; if (!captionattop){ for (ii=0; ii<=tablelastline-tablefirstline+1;ii++){ for (k=0;k<=tablehlinecounter.get(ii);k++){ totalhline++; tatom.add("!hlin "); txpos.add(0.0f); typos.add(0.0f); tattribute.add(attribute); } synchronized(this){ superblock.add(tid,tatom,txpos, typos, tattribute,0.0f,0.0f,0.0f,'t',numcolumn-1);} tatom.clear(); txpos.clear(); typos.clear(); tattribute.clear(); } } else { for (ii=0;ii<=tablelastline-tablefirstline+captionnumline+2 ;ii++){ if (!(ii>=1 && ii <=captionnumline+1)){ for (k=0;k<=tablehlinecounter.get(ii);k++){ totalhline++; tatom.add("!hlin "); txpos.add(0.0f); typos.add(0.0f); tattribute.add(attribute); } synchronized(this){ superblock.add(tid,tatom,txpos, typos, tattribute,0.0f,0.0f,0.0f,'t',numcolumn-1);} tatom.clear(); txpos.clear(); typos.clear(); tattribute.clear(); } } for (i=1;i<=tablelastline-tablefirstline+1;i++){tablehlinecounter.set(i,tablehlinecounter.get(i+captionnumline+1));} } // determine vertical height of table and assign ypos of horizontal lines // first line i=tablefirstline-adjustline; int index=SuperBlock.blockypos.get(tablelastline+tid2-adjustline).size()-(tablehlinenumber+1); for (k=0;k<=tablehlinecounter.get(0);k++){ SuperBlock.blockypos.get(tablelastline+tid2-adjustline).set(index+k, adjusty); adjusty=adjusty+linegap; } adjusty=adjusty+SuperBlock.superblocklineheight.get(tid).get(i)-SuperBlock.superblocklinedepth.get(tid).get(i); int l=0; if(tablefirstline==tablelastline){ l=totalhline+totalvline; } for (ii=0;ii<=SuperBlock.blockatom.get(i+tid2).size()-1-l;ii++){ SuperBlock.blockypos.get(i+tid2).set(ii, SuperBlock.blockypos.get(i+tid2).get(ii)+adjusty); } thisypos2=adjusty+SuperBlock.superblocklinedepth.get(tid).get(i)+linegap; // middle line for (i=tablefirstline+1;i<=tablelastline-1;i++){ index=index+k; for (k=0;k<=tablehlinecounter.get(i-tablefirstline);k++){ SuperBlock.blockypos.get(tablelastline+tid2-adjustline).set(index+k, thisypos2); thisypos2=thisypos2+linegap; adjusty=adjusty+linegap; } adjusty=adjusty+SuperBlock.superblocklinedepth.get(tid).get(i-1-adjustline)+linegap+SuperBlock.superblocklineheight.get(tid).get(i-adjustline)-SuperBlock.superblocklinedepth.get(tid).get(i-adjustline); for (ii=0;ii<=SuperBlock.blockatom.get(i+tid2-adjustline).size()-1;ii++){ SuperBlock.blockypos.get(i+tid2-adjustline).set(ii, SuperBlock.blockypos.get(i+tid2-adjustline).get(ii)+adjusty); } thisypos2=adjusty+SuperBlock.superblocklinedepth.get(tid).get(i-adjustline)+linegap; } // last line if (tablelastline > tablefirstline){ i=tablelastline-adjustline; index=index+k; for (k=0;k<=tablehlinecounter.get(i-tablefirstline+adjustline);k++){ SuperBlock.blockypos.get(tablelastline+tid2-adjustline).set(index+k, thisypos2); thisypos2=thisypos2+linegap; adjusty=adjusty+linegap; } adjusty=adjusty+SuperBlock.superblocklinedepth.get(tid).get(i-1)+linegap+SuperBlock.superblocklineheight.get(tid).get(i)-SuperBlock.superblocklinedepth.get(tid).get(i); for (ii=0;ii<=SuperBlock.blockatom.get(i+tid2).size()-1-(tablehlinenumber+1)-(columnspec.length()-columnspec2.length());ii++){ SuperBlock.blockypos.get(i+tid2).set(ii, SuperBlock.blockypos.get(i+tid2).get(ii)+adjusty); } thisypos2=adjusty+SuperBlock.superblocklinedepth.get(tid).get(i); thisypos2=thisypos2+linegap; } if (tablehlinecounter.get(tablelinenumber)>=0) { index=index+k; for (k=0;k<=tablehlinecounter.get(tablelinenumber);k++){ SuperBlock.blockypos.get(tablelastline+tid2-adjustline).set(index+k, thisypos2); thisypos2=thisypos2+linegap; } } else { thisypos2=thisypos2+linegap; } thisypos2=thisypos2-linegap; // assign vertical lines height index=SuperBlock.blockatom.get(SuperBlock.superblocklinenumber.get(tid)+tid2).size()-(tablehlinenumber+1)-(columnspec.length()-columnspec2.length()); float temp=thisypos2-thisypos.get(tid); sfontsize=Integer.toString((int)temp); int is=sfontsize.length(); for (k=0;k<=columnspec.length()-columnspec2.length()-1;k++){ if (is==1){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4)); } else if (is==2){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4)); } else if (is==3){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4)); } } // determine total width of table for (ii=0;ii<=numcolumn-1;ii++){ totalwidth=totalwidth+columnwidth.get(ii)+columngap+(columngap*(tablevlinecounter.get(ii)+1)); } if (tablevlinecounter.get(numcolumn)>=0){ totalwidth=totalwidth+(columngap*(tablevlinecounter.get(numcolumn))); } if (viewportwidth>totalwidth){shiftx=(viewportwidth-totalwidth)/2;} else {shiftx=(viewportwidth-totalwidth)/2;}; for (i=tablefirstline-adjustline;i<=tablelastline-adjustline;i++){ // assign xpos of first column adjustx=shiftx+Header.leftsidemargin; int columnnum=0; int iistart=0; index=SuperBlock.blockatom.get(SuperBlock.superblocklinenumber.get(tid)+tid2).size()-(tablehlinenumber+1)-(columnspec.length()-columnspec2.length()); for (k=0; k<=tablevlinecounter.get(0);k++){ if (i==tablelastline-adjustline){SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index,adjustx);SuperBlock.blockypos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisypos2);} adjustx=adjustx+columngap; } index=index+tablevlinecounter.get(0)+1; int index2=i+tid2; l=0; if (i==tablelastline-adjustline){l=totalvline+totalhline;} for (ii=0;SuperBlock.blockcolumnnum.get(index2).size()>= ii+1+l && SuperBlock.blockcolumnnum.get(index2).get(ii)==0;ii++){ if (columnspec2.charAt(columnnum)=='l'){SuperBlock.blockxpos.get(index2).set(ii, SuperBlock.blockxpos.get(index2).get(ii)+adjustx);} else if (columnspec2.charAt(columnnum)=='c'){adjustx2=(columnwidth.get(columnnum)-blockwidth.get((i-tablefirstline+adjustline)*numcolumn+columnnum))/2; SuperBlock.blockxpos.get(index2).set(ii, SuperBlock.blockxpos.get(index2).get(ii)+adjustx+adjustx2);} else if (columnspec2.charAt(columnnum)=='r'){adjustx2=columnwidth.get(columnnum)-blockwidth.get((i-tablefirstline+adjustline)*numcolumn+columnnum); SuperBlock.blockxpos.get(index2).set(ii, SuperBlock.blockxpos.get(index2).get(ii)+adjustx+adjustx2);}; columnnum=0; } iistart=ii; // assign xpos of all columns for (columnnum=1;columnnum<=numcolumn-1;columnnum++){ boolean endofcolumn=false; adjustx=adjustx+columngap+columnwidth.get(columnnum-1); // assign xpos and ypos of vertical lines for (k=0; k<=tablevlinecounter.get(columnnum);k++){ if (i==tablelastline-adjustline){SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index,adjustx);SuperBlock.blockypos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisypos2);} adjustx=adjustx+columngap; } index=index+tablevlinecounter.get(columnnum)+1; index2=0; if (i==SuperBlock.superblocklinenumber.get(tid)){ index2=SuperBlock.blockcolumnnum.get(i+tid2).size()-1-(tablehlinenumber+1)-(columnspec.length()-columnspec2.length()); } else { index2=SuperBlock.blockcolumnnum.get(i+tid2).size()-1; } for (ii=iistart;endofcolumn==false && ii <=index2;ii++){ if (columnnum == SuperBlock.blockcolumnnum.get(i+tid2).get(ii)){ if (columnspec2.charAt(columnnum)=='l'){SuperBlock.blockxpos.get(i+tid2).set(ii, SuperBlock.blockxpos.get(i+tid2).get(ii)+adjustx);} else if (columnspec2.charAt(columnnum)=='c'){adjustx2=(columnwidth.get(columnnum)-blockwidth.get((i-tablefirstline+adjustline)*numcolumn+columnnum))/2; SuperBlock.blockxpos.get(i+tid2).set(ii, SuperBlock.blockxpos.get(i+tid2).get(ii)+adjustx+adjustx2);} else if (columnspec2.charAt(columnnum)=='r'){adjustx2=columnwidth.get(columnnum)-blockwidth.get((i-tablefirstline+adjustline)*numcolumn+columnnum); SuperBlock.blockxpos.get(i+tid2).set(ii, SuperBlock.blockxpos.get(i+tid2).get(ii)+adjustx+adjustx2);}; } else { endofcolumn=true; iistart=ii; } } } // assign xpos and ypos of last vertical lines adjustx=adjustx+columngap+columnwidth.get(numcolumn-1); for (k=0; k<=tablevlinecounter.get(numcolumn);k++){ if (i==tablelastline-adjustline){SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index,adjustx);SuperBlock.blockypos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisypos2);} adjustx=adjustx+columngap; } // assign xpos and width of all horizontal lines index=SuperBlock.blockcolumnnum.get(i+tid2).size()-(tablehlinenumber+1); sfontsize=Integer.toString((int)totalwidth); is=sfontsize.length(); for (k=0; k<=tablehlinenumber;k++){ if (i==tablelastline-adjustline){ SuperBlock.blockxpos.get(tablelastline+tid2-adjustline).set(index+k,shiftx+Header.leftsidemargin); if (is==1){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4)); } else if (is==2){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4)); } else if (is==3){ SuperBlock.blockattribute.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(k+index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4)); } } } } thisypos2=thisypos2+linegap; thisypos.put(tid, thisypos2); columnwidth.clear(); lineheight.clear(); linedepth.clear();; blockwidth.clear();; blockheight.clear(); blockdepth.clear(); tablevlinecounter.clear(); if (!captionattop){ Parsetext table = new Parsetext(); for (i=0;i<=captionnumline;i++){ sfontsize=Integer.toString(Header.fontsize); if (sfontsize.length()==1){ attribute2 = "100"+sfontsize+"002"+attribute2.substring(7); } else if (sfontsize.length()==2){ attribute2 = "10"+sfontsize+"002"+attribute2.substring(7); } else if (sfontsize.length()==3){ attribute2 = "1"+sfontsize+"002"+attribute2.substring(7); } table.parsetext(canvas, block, paragraphblock, tid, containerwidth, containerheight, superblocknumber, superblock, captionline.get(i), Header.leftsidemargin , thisypos2, tf, attribute2, attribute, false, 0.0f); thisypos2=Parsetext.thisypos.get(tid); error.put(tid, Parsetext.error.get(tid)); if (error.get(tid)){errormessage.put(tid, Parsetext.errormessage.get(tid)); return;}; adjustx=(viewportwidth-SuperBlock.superblocklinewidth.get(tid).get(SuperBlock.superblocklinewidth.get(tid).size()-1))/2; for (int ij=0;ij<=SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).size()-1;ij++){ SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).set(ij,SuperBlock.blockxpos.get(SuperBlock.superblocklinenumber.get(tid)+tid2).get(ij)+adjustx); } thisypos.put(tid,Parsetext.thisypos.get(tid)); }} SuperBlock.tableendline.put(tid2+SuperBlock.tablenumber.get(tid), SuperBlock.superblocklinenumber.get(tid)); SuperBlock.tableheight.put(tid2+SuperBlock.tablenumber.get(tid),thisypos.get(tid)-ypos); }}