//
// Latex Project Public Licence (lppl1.3) applies
// Originally written by Kwanleung Tse
// First Release : 1st July, 2014
// Last Update : 27th 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.SparseIntArray;

public class Parseblock {
	
	private ArrayList<Integer> blockfractionlevel = new ArrayList<Integer>(); 
	private ArrayList<Integer> blocklevel = new ArrayList<Integer>();
	private ArrayList<Integer> blockenclosurelevel = new ArrayList<Integer>();
	private ArrayList<Integer> blocksuperscriptlevel = new ArrayList<Integer>();
	private ArrayList<Integer> blocksubscriptlevel = new ArrayList<Integer>();
	private ArrayList<Integer> blocktabularlevel = new ArrayList<Integer>();
	private ArrayList<Float> blockwidth = new ArrayList<Float>(); 
	private ArrayList<Float> blockheight = new ArrayList<Float>();
	private ArrayList<Float> blockdepth = new ArrayList<Float>();
	
	private ArrayList<ArrayList<String>> subblock = new ArrayList<ArrayList<String>>();
	private ArrayList<ArrayList<Float>> subblockwidth  = new ArrayList<ArrayList<Float>>();
	private ArrayList<ArrayList<Float>> subblockheight = new ArrayList<ArrayList<Float>>();
	private ArrayList<ArrayList<Float>> subblockdepth = new ArrayList<ArrayList<Float>>();
	private ArrayList<ArrayList<Float>> subblockxpos = new ArrayList<ArrayList<Float>>();
	private ArrayList<ArrayList<Float>> subblockypos = new ArrayList<ArrayList<Float>>(); 
	private ArrayList<ArrayList<String>> subblockattribute  = new ArrayList<ArrayList<String>>();
	
	public  void parseblock(int tid, Canvas canvas, Block block, String molecule, ArrayList<Typeface> tf , String defaultattribute){
		
	    SparseIntArray subblocknumber = new SparseIntArray();
	    subblocknumber.put(tid, -1);
	    
		char charExclam = '!';

		String stringfra = "fra";
		String stringcnb = "cnb";
		String stringodb = "odb";
		String stringcdb = "cdb";
		String stringosp = "osp";
		String stringcsp = "csp";
		String stringosu = "osu";
		String stringcsu = "csu";
		String stringobx = "obx";
		String stringcbx = "cbx";
		String stringbta = "bta";
		String stringeta = "eta";
		String stringbln = "bln";
		String stringeln = "eln";
		String stringolb = "olb";
		String stringclb = "clb";
		String stringhline = "!hlin ";			
		String stringdnot = "!dno ";
		String key="";
		String key2="";
		String parentkey="";			
		String sfontsize="";
		String thisattribute;
		String attribute2;
		String columnspec="";
		
        boolean showcloseenclosure = true;
        boolean containfraction = false;
        boolean containenclosure = false;
		
		int i,j = 0;
		int ii=0;
		int iii=0;
		int i3=0;
		int j3=0;
		int index=0;
		int index2=0;
		int blocknumber = 0;	 
		int currentblock=0;
		int previousblock=0;
		int parentblock = 0;
		int fontsize = Integer.parseInt(defaultattribute.substring(1,4));
		int thisfontsize = fontsize;
		int fontinteger = Integer.parseInt(defaultattribute.substring(4,7));
      
		int thisblocklevel = 0;
		int thisfractionlevel = 0;
		int thisenclosurelevel = -1;
		int thissuperscriptlevel = -1;
		int thissubscriptlevel = -1;			
		int thistabularlevel = -1;
		int fractionnumber = -1;
		int currentfraction = -1;
		int previousfraction = -1;
		int numeratornumber = -1;
		int currentnumerator = -1;
		int denominatornumber = -1;
		int currentdenominator = -1;
		int previousdenominator = -1;
		int enclosurenumber = -1;
		int currentenclosure = -1;
		int previousenclosure = -1;
		int tabularnumber = -1;
		int currenttabular = -1;
		int previoustabular = -1;
		int tabularlinenumber = -1;
		int currenttabularline = -1;
		int previoustabularline = -1;
		int tabularlineblocknumber = -1;
		int currenttabularlineblock = -1;
		int superscriptnumber = -1;
		int currentsuperscript = -1;
		int subscriptnumber = -1;
		int currentsubscript = -1;
		int previoussubscript = -1;
		int previoussuperscript = -1;
		int numcolumn=0;
		int column = 0;

		float ypos = 0.0f;
		float xpos = 0.0f;
		float halfheight=0.0f;
		float maxtop=0.0f;
		float gap=Header.characterheadroom;
		float columngap=Header.columngap;
		float strokewidth=0.0f;
		float width1 = 0.0f;
		float width2 = 0.0f;
		float width3 = 0.0f;
		float maxwidth = 0.0f;
		float maxwidth1=0.0f;
		float maxcolumnwidth=0.0f;
		float totalcolumnwidth=0.0f;
		float tempx=0.0f;
		float tempy=0.0f;
		float twidth=0.0f;
		float twidth2=0.0f;
		float case6xmargin=0.0f;
		float case7xmargin=0.0f;
		float theight=0.0f;
		float tdepth=0.0f;
		float totaltabularheight=0.0f;
		float totaltabulardepth=0.0f;
		float spacewidth=0.0f;
		float spaceheight=0.0f;
		float spacedepth=0.0f;
		
		ArrayList<Boolean> showopenenclosure = new ArrayList<Boolean>();
		ArrayList<Boolean> aftersuperscript = new ArrayList<Boolean>();
		ArrayList<Boolean> aftersubscript = new ArrayList<Boolean>();
		
    	ArrayList<Float> numeratorwidth = new ArrayList<Float>();
    	ArrayList<Float> numeratorheight = new ArrayList<Float>();
    	ArrayList<Float> numeratordepth = new ArrayList<Float>();
    	ArrayList<Float> denominatorwidth = new ArrayList<Float>();
    	ArrayList<Float> denominatorheight = new ArrayList<Float>();
    	ArrayList<Float> denominatordepth = new ArrayList<Float>();
    	ArrayList<Float> fractionwidth = new ArrayList<Float>();
    	ArrayList<Float> fractionheight = new ArrayList<Float>();
    	ArrayList<Float> fractiondepth = new ArrayList<Float>();
    	ArrayList<Float> columnwidth = new ArrayList<Float>();
    	
    	ArrayList<Integer> openblock = new ArrayList<Integer>();
    	ArrayList<Integer> closeblock = new ArrayList<Integer>();	    	
    	ArrayList<Integer> subparentblock = new ArrayList<Integer>();
    	ArrayList<Integer> supparentblock = new ArrayList<Integer>();
    	ArrayList<Integer> linenu = new ArrayList<Integer>();
    	ArrayList<Integer> openfraction = new ArrayList<Integer>();
    	ArrayList<Integer> closefraction = new ArrayList<Integer>();
    	ArrayList<Integer> opennumerator = new ArrayList<Integer>();
    	ArrayList<Integer> closenumerator = new ArrayList<Integer>();
    	ArrayList<Integer> opendenominator = new ArrayList<Integer>();
    	ArrayList<Integer> closedenominator = new ArrayList<Integer>();
		ArrayList<Integer> homeblock = new ArrayList<Integer>();	    	
    	ArrayList<Integer> numeratorindex = new ArrayList<Integer>();
    	ArrayList<Integer> denominatorindex = new ArrayList<Integer>();
		ArrayList<Integer> opensubscript = new ArrayList<Integer>();
		ArrayList<Integer> closesubscript = new ArrayList<Integer>();
		ArrayList<Integer> opensuperscript = new ArrayList<Integer>();
		ArrayList<Integer> closesuperscript = new ArrayList<Integer>();
		ArrayList<Integer> openenclosure = new ArrayList<Integer>();
		ArrayList<Integer> closeenclosure = new ArrayList<Integer>();			
		ArrayList<Integer> opentabular = new ArrayList<Integer>();
		ArrayList<Integer> closetabular = new ArrayList<Integer>();
		ArrayList<Integer> opentabularline = new ArrayList<Integer>();
		ArrayList<Integer> closetabularline = new ArrayList<Integer>();
		ArrayList<Integer> opentabularlineblock = new ArrayList<Integer>();
		ArrayList<Integer> closetabularlineblock = new ArrayList<Integer>();
		
		ArrayList<String> supparentkey = new ArrayList<String>();
		ArrayList<String> subparentkey = new ArrayList<String>();
		
		double[] fractionfontfactor = {1.0,0.75,0.5};


	    Fontfile font = new Fontfile();
	    font.fontfile();
	 
	    Colorfile color = new Colorfile();
	    color.colorfile();

		Paint textpaint = new Paint();
	    Rect textbounds = new Rect();
		textpaint.setTextSize(thisfontsize);
		textpaint.setTypeface(tf.get(fontinteger));
		textpaint.getTextBounds("Aj",0,"Aj".length(),textbounds);
		spacewidth=textpaint.measureText(" ");
		spaceheight=textbounds.height();
		spacedepth=textbounds.bottom;
		
		Paint textpaint5 = new Paint();
	    Rect textbounds5 = new Rect();
		textpaint5.setTextSize(thisfontsize);
		textpaint5.setTypeface(tf.get(5));
		
		Paint symbolpaint = new Paint();
	    Rect symbolbounds = new Rect();
		symbolpaint.setTextSize(thisfontsize);
		symbolpaint.setTypeface(tf.get(4));
		

		thisattribute=defaultattribute;
		attribute2=defaultattribute;
		sfontsize=Integer.toString(thisfontsize);
		int ij=sfontsize.length();
		if (ij==1){
		thisattribute=thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4);
		} else if (ij==2){
			thisattribute=thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4);
		} else if (ij==3){
			thisattribute=thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4);
		}			
		
		molecule=molecule.trim();
		molecule = molecule + charExclam + charExclam + charExclam + charExclam + charExclam;

		j=0;
		
		char temp = molecule.charAt(j);
		if (temp == charExclam){
			key = "";
			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
				key = key + molecule.charAt(ii);
			}}
		
		create(tid,blocknumber, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);
		subblocknumber.put(tid, subblocknumber.get(tid)+1);add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,0.0f,0.0f,thisattribute);
		openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);

		for (i=0;!((molecule.charAt(j) == charExclam) && (molecule.charAt(j+1)==charExclam)) ; i++) {

			if (temp == charExclam && key.equals("openblock")) {  
				previousblock=currentblock;
				blocknumber++;			  
				currentblock= blocknumber;					  
				thisblocklevel++;
				  
				create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);
	    		  
				subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
				openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);
	    		  
				j+=11;
				temp = molecule.charAt(j);
				if (temp == charExclam){
					key = "";
					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
						key = key + molecule.charAt(ii);
					}}				
			} else if (temp == charExclam && key.equals("closeblock")) {
				closeblock.set(currentblock, subblocknumber.get(tid));
				previousblock=currentblock;
				for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
					currentblock--;
				}							  

				insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock),blockdepth.get(previousblock) );		

				thisblocklevel--;
				j+=12;
				temp = molecule.charAt(j);
				if (temp == charExclam){
					key = "";
					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
						key = key + molecule.charAt(ii);
					}}				
			} else if (temp == charExclam && key.equals(stringfra)) {                                // open fraction, open numerator
				  
				thisfractionlevel++;
				fractionnumber++;
				currentfraction=fractionnumber;
				  
				previousblock=currentblock;
				blocknumber++;			  
				currentblock= blocknumber;					  
				thisblocklevel++;

				create(tid, currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);		    		  
				subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);

				openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);

				openfraction.add(subblocknumber.get(tid)); closefraction.add(-1);
				if (thissubscriptlevel ==-1 && thissuperscriptlevel ==-1){
					if (thisfractionlevel<=2){
						thisfontsize=(int)((double)fontsize*fractionfontfactor[thisfractionlevel]);
					}else {
						thisfontsize=(int)((double)fontsize*fractionfontfactor[2]); 
					};				      
					if (thisfontsize<8){thisfontsize=8;};
				};
				numeratornumber++;
				currentnumerator=numeratornumber;
				  
				previousblock=currentblock;
				blocknumber++;			  
				currentblock= blocknumber;				
				thisblocklevel++;

				create(tid,currentblock, thisblocklevel, thisfractionlevel,thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);		    		  
				subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);

				openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);	    		  
	    		 
				numeratorindex.add(currentblock); numeratorwidth.add(0.0f); numeratorheight.add(0.0f);numeratordepth.add(0.0f);
				denominatorindex.add(-1); denominatorwidth.add(0.0f); denominatorheight.add(0.0f);denominatordepth.add(0.0f);
				fractionwidth.add(0.0f); fractionheight.add(0.0f);  fractiondepth.add(0.0f);
				opennumerator.add(subblocknumber.get(tid)); closenumerator.add(-1);
				opendenominator.add(-1); closedenominator.add(-1);
				linenu.add(currentblock); 

				j+=9;
				temp = molecule.charAt(j);
				if (temp == charExclam){
					key = "";
					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
						key = key + molecule.charAt(ii);
					}}				  

			} else if (temp == charExclam && key.equals(stringcnb) ) {                          // close numerator

				numeratorwidth.set(currentnumerator,blockwidth.get(currentblock)); 
				numeratorheight.set(currentnumerator,blockheight.get(currentblock));
				numeratordepth.set(currentnumerator,blockdepth.get(currentblock));
				closenumerator.set(currentnumerator, subblocknumber.get(tid));
		        closeblock.set(currentblock, subblocknumber.get(tid));	        
				      
		        containfraction = false;
		        containenclosure=false;
				for (i=currentblock+1;i<=blocknumber && !containfraction && !containenclosure;i++){
					if (blockenclosurelevel.get(i)==thisenclosurelevel && 
							blocksuperscriptlevel.get(i)==thissuperscriptlevel && 
							blocksubscriptlevel.get(i)==thissubscriptlevel && 
							blockfractionlevel.get(i)==thisfractionlevel+1 && 
							openblock.get(i)> openblock.get(currentblock) && closeblock.get(i) <= closeblock.get(currentblock)){
						containfraction=true;
					}
					else if (blockenclosurelevel.get(i)==thisenclosurelevel+1 && blocklevel.get(i)==thisblocklevel+1 && openblock.get(i)>openblock.get(currentblock) && closeblock.get(i)<=closeblock.get(currentblock)){
						containenclosure=true;	
					}
				}
						        
				textpaint.setTextSize(thisfontsize);
				textpaint.setTypeface(tf.get(0));
				textpaint.getTextBounds("1",0,"1".length(),textbounds);	
				Float off=(float) textbounds.height()/2;
				
				if (containfraction){
					adjustfraction(tid,currentblock, blocknumber, homeblock,openblock,closeblock,thisfractionlevel, thisblocklevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, off, gap);
				}
               
				strokewidth=(float)thisfontsize/10; if (strokewidth < 1){strokewidth=1;};
				subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringhline,0.0f,strokewidth,strokewidth,subblockxpos.get(currentblock).get(0),ypos+gap+blockdepth.get(currentblock),thisattribute);

				closenumerator.set(currentnumerator, subblocknumber.get(tid));
		        closeblock.set(currentblock, subblocknumber.get(tid));homeblock.add(currentblock);					
		        thisblocklevel--;
		       
		        for (i=subblocknumber.get(tid);currentnumerator >=0 && closenumerator.get(currentnumerator)>=0;i--){
		        	currentnumerator--;
		        }
		        previousblock=currentblock;
		        for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
		        	currentblock--;
		        }		
		        parentkey="";
			    j+=5;
			    temp = molecule.charAt(j);
				if (temp == charExclam){
					key = "";
					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
				    key = key + molecule.charAt(ii);
					}}
				} else  if (temp == charExclam && key.equals(stringcdb)) {                                                 // close denominator
                    
//denominator block
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					homeblock.add(currentblock);
	    		  
					closedenominator.set(currentdenominator, subblocknumber.get(tid));
					closeblock.set(currentblock, subblocknumber.get(tid));
				 
					denominatorwidth.set(currentdenominator,blockwidth.get(currentblock)); 
					denominatorheight.set(currentdenominator,blockheight.get(currentblock));
					denominatordepth.set(currentdenominator,blockdepth.get(currentblock));

					fractionwidth.set(currentfraction,  Math.max(numeratorwidth.get(currentfraction),denominatorwidth.get(currentdenominator)));		
					fractionheight.set(currentfraction,  numeratorheight.get(currentfraction) + denominatorheight.get(currentdenominator) + gap*2);
					fractiondepth.set(currentfraction,  denominatorheight.get(currentdenominator) + gap);
				
					index=numeratorindex.get(currentfraction);
					int l=subblockwidth.get(index).size();
					subblockwidth.get(index).set(l-1,fractionwidth.get(currentfraction));
					tempy=fractionwidth.get(currentfraction);
					sfontsize=Integer.toString((int)tempy);
					ij=sfontsize.length();
					index=numeratorindex.get(currentfraction);
			
					if (ij==1){
						subblockattribute.get(index).set(l-1,thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));		
					} else if (ij==2){
						subblockattribute.get(index).set(l-1,thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));								
					} else if (ij==3){
						subblockattribute.get(index).set(l-1,thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
					}				
				
					containfraction = false;
					containenclosure=false;
					for (i=currentblock+1;i<=blocknumber && !containfraction && !containenclosure;i++){
						if (blockenclosurelevel.get(i)==thisenclosurelevel && 
								blocksuperscriptlevel.get(i)==thissuperscriptlevel && 
								blocksubscriptlevel.get(i)==thissubscriptlevel && 
								blockfractionlevel.get(i)==thisfractionlevel+1 && 
								openblock.get(i)> openblock.get(currentblock) && closeblock.get(i) <= closeblock.get(currentblock)){
							containfraction=true;
						}
						else if (blockenclosurelevel.get(i)==thisenclosurelevel+1 && blocklevel.get(i)==thisblocklevel+1 && openblock.get(i)>openblock.get(currentblock) && closeblock.get(i)<=closeblock.get(currentblock)){
							containenclosure=true;	
						}	
					}
				
					textpaint.setTextSize(thisfontsize);
					textpaint.setTypeface(tf.get(0));
					textpaint.getTextBounds("1",0,"1".length(),textbounds);	
					Float off=(float) textbounds.height()/2;
			
					if (containfraction){adjustfraction(tid,currentblock, blocknumber, homeblock,openblock,closeblock,thisfractionlevel, thisblocklevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, off, gap);}
					thisblocklevel--;
			
			  //  adjust horizontal position of numerator and denominator
			  
					if (numeratorwidth.get(currentfraction) > denominatorwidth.get(currentdenominator)){
						tempx = (numeratorwidth.get(currentfraction) - denominatorwidth.get(currentdenominator))/2;
						index=currentblock;
						for (i=0;i<=subblock.get(index).size()-1;i++){subblockxpos.get(index).set(i,  subblockxpos.get(index).get(i) + tempx);};                 	
					} else if (numeratorwidth.get(currentfraction) < denominatorwidth.get(currentdenominator)){
						tempx = (denominatorwidth.get(currentdenominator) - numeratorwidth.get(currentfraction))/2;
						index=numeratorindex.get(currentfraction);
						blockwidth.set(numeratorindex.get(currentfraction),numeratorwidth.get(currentfraction));
						for (i=0;i<=subblock.get(index).size()-2;i++){subblockxpos.get(index).set(i, subblockxpos.get(index).get(i) + tempx);};                 	
					}	  

			  //  adjust vertical position of denominator

					index=numeratorindex.get(currentfraction);
					index2=currentblock;
					tempy=subblockypos.get(index).get(subblock.get(index).size()-1)-subblockypos.get(index).get(0);
					for (ii=0;ii<=subblock.get(index2).size()-1;ii++){
						subblockypos.get(index2).set(ii,subblockypos.get(index2).get(ii)+tempy+gap+blockheight.get(currentblock)-blockdepth.get(currentblock));
					}
					index=0;

					previousdenominator=currentdenominator;
					halfheight=(float) 0;
					for (i=subblocknumber.get(tid);currentdenominator >=0 &&  closedenominator.get(currentdenominator)>=0;i--){
						currentdenominator--;
					}                   
					previousblock=currentblock;
					for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
						currentblock--;
					}		
                  
					if (thisfractionlevel == 1){
					  
						textpaint.setTextSize(thisfontsize);
						textpaint.setTypeface(tf.get(0));
						textpaint.getTextBounds("a",0,"a".length(),textbounds);	
						halfheight=textbounds.height()*5/8;
						
						index=numeratorindex.get(currentfraction);
						tempy=subblockypos.get(index).get(subblock.get(index).size()-1)-subblockypos.get(index).get(0);			
						for (i=1;i<=subblock.get(index).size()-1;i++){							
							subblockypos.get(index).set(i, subblockypos.get(index).get(i)-tempy-halfheight);
						}
						ypos=subblockypos.get(index).get(0);
						xpos=subblockxpos.get(index).get(subblock.get(index).size()-1)+fractionwidth.get(currentfraction);
						index=previousblock;
						for (i=1;i<=subblock.get(index).size()-2;i++){					
							subblockypos.get(index).set(i, subblockypos.get(index).get(i)-tempy-halfheight);
						}					  
						fractiondepth.set(currentfraction,fractiondepth.get(currentfraction)-halfheight);
					}  
					else  if (thisfractionlevel >= 2){
					  //    adjust position after fraction 
					  
						textpaint.setTextSize(thisfontsize);
						textpaint.setTypeface(tf.get(0));
						textpaint.getTextBounds("a",0,"a".length(),textbounds);	
						halfheight=textbounds.height()*5/8;
						
					    index=numeratorindex.get(currentfraction);
					    iii=subblock.get(index).size()-1;
					    tempy=subblockypos.get(index).get(0);
					    blockdepth.set(currentblock,blockdepth.get(currentblock)-tempy+ypos);
					    ypos=tempy;
					    xpos=subblockxpos.get(index).get(iii)+subblockwidth.get(index).get(iii);
					}

					index = numeratorindex.get(currentfraction);
					insert(tid,index, currentblock,0.0f,0.0f,0.0f);	                  
					insert(tid,previousblock, currentblock,0.0f,0.0f,0.0f);		
					blockwidth.set(index, numeratorwidth.get(currentfraction));
					maxtop=Math.max(blockheight.get(currentblock)-blockdepth.get(currentblock), blockheight.get(index)-blockdepth.get(index));		                  
					blockdepth.set(currentblock, Math.max(blockdepth.get(currentblock),blockdepth.get(index)));
					blockheight.set(currentblock, maxtop+blockdepth.get(currentblock));
					blockwidth.set(previousblock, denominatorwidth.get(currentfraction));
					maxtop=Math.max(blockheight.get(currentblock)-blockdepth.get(currentblock), blockheight.get(previousblock)-blockdepth.get(previousblock));		                  
					blockdepth.set(currentblock, Math.max(blockdepth.get(currentblock),blockdepth.get(previousblock)));
					blockheight.set(currentblock, maxtop+blockdepth.get(currentblock));
                  
//fraction block
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					homeblock.add(currentblock);
	    		  
					closefraction.set(currentfraction, subblocknumber.get(tid));
					closeblock.set(currentblock, subblocknumber.get(tid));
					thisblocklevel--;
					thisfractionlevel--;		
				  
					if (thissubscriptlevel >= 0 || thissuperscriptlevel >= 0){
						thisfontsize=fontsize/3;
					}else if (thisfractionlevel<=2){
						thisfontsize=(int)((double)fontsize*fractionfontfactor[thisfractionlevel]);
					}else {
						thisfontsize=(int)((double)fontsize*fractionfontfactor[2]); 
					};
					if (thisfontsize<8){thisfontsize=8;};					  
				  
					previousfraction=currentfraction;
					for (i=subblocknumber.get(tid);currentfraction >=0 && closefraction.get(currentfraction)>=0;i--){
						currentfraction--;
					}
					previousblock=currentblock;
					for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
						currentblock--;
					}		
				  				
					blockwidth.set(previousblock, fractionwidth.get(previousfraction));
					blockheight.set(previousblock, fractionheight.get(previousfraction));
					if (thisfractionlevel==0) {blockdepth.set(previousblock,denominatorheight.get(previousdenominator)+gap-halfheight);}
					else {blockdepth.set(previousblock, numeratordepth.get(previousfraction)+denominatorheight.get(previousdenominator)+gap*2);};
                 
					twidth=fractionwidth.get(previousfraction);
					theight=fractionheight.get(previousfraction);
					tdepth=blockdepth.get(previousblock);
					insert(tid,previousblock, currentblock,twidth, theight, tdepth);

					parentkey="";
					j+=5;
					temp = molecule.charAt(j);				      
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				} else  if (temp == charExclam && key.equals(stringodb)) {                        // open denominator

					denominatornumber++;
					currentdenominator=denominatornumber;
				  
					previousblock=currentblock;
					blocknumber++;					  
					currentblock=blocknumber;
					thisblocklevel++;
				  
			        index = numeratorindex.get(currentfraction);
			        ypos=subblockypos.get(index).get(0);
			        xpos=subblockxpos.get(index).get(subblock.get(index).size()-1);
		        
			        create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);		    		  
			        subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);

			        openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);
	    		  
			        denominatorindex.set(currentdenominator,currentblock);  
				  
			        j+=5;
			        temp = molecule.charAt(j);
			        if (temp == charExclam){
			        	key = "";
			        	for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			        		key = key + molecule.charAt(ii);
			        	}}				  
             				  
			        opendenominator.set(currentdenominator,  subblocknumber.get(tid));				  
	        
				} else  if (temp == charExclam && key.equals(stringbta)) {                   // begin tabular
				
				    thistabularlevel=0;
		  			tabularnumber=0;
		  			currenttabular=tabularnumber;
		  			opentabularline.clear();closetabularline.clear();opentabular.clear();closetabular.clear();opentabularlineblock.clear();closetabularlineblock.clear();
		  			
		  			if (thisfractionlevel>0){
		  				synchronized(this){
		  				Block.error.put(tid, true);
		  				Block.errormessage.put(tid, "Fraction cannot have tabular, parse failed!");}
		  				return;
		  			}
		  			if (thistabularlevel>0){
		  				synchronized(this){
		  				Block.error.put(tid, true);
		  				Block.errormessage.put(tid, "Tabular cannot have tabular, parse failed!");}
		  				return;
		  			}
		  			blocknumber++;			  
		  			currentblock= blocknumber;
		  			thisblocklevel++;

		  			create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);		    		  
		  			subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);

		  			openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);	    		  				   		  								
		  			opentabular.add(subblocknumber.get(tid)); closetabular.add(-1); 

		  			tabularlinenumber=-1;
		  			j+=5;
		  			int i4=molecule.indexOf("{",j);
		  			numcolumn=0;
		  			for (i=j;i<=i4-2;i++){
		  				if (molecule.charAt(i)=='l' || molecule.charAt(i)=='c' || molecule.charAt(i)=='r'){
		  					numcolumn++;
		  				}
		  			}
		  			columnspec=molecule.substring(j,i4-1);
		  			totalcolumnwidth=0;
		  			columnwidth.clear();
	  				opentabularlineblock.clear();
	  				
	  				j=i4+1;
	  				temp = molecule.charAt(j);
	  				if (temp == charExclam){
	  					key = "";
	  					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
	  						key = key + molecule.charAt(ii);
	  					}}	

				}else  if (temp == charExclam && key.equals(stringeta)) {                   // end tabular
	  				  			
					thistabularlevel--;
         	 closetabular.set(currenttabular, subblocknumber.get(tid));closeblock.set(currentblock, subblocknumber.get(tid));
         
         	 blockwidth.set(currentblock, totalcolumnwidth);
         	 twidth=0;totalcolumnwidth=0;

         	 for (i=0;i<=numcolumn-1;i++){
         		 totalcolumnwidth=totalcolumnwidth+columnwidth.get(i)+columngap;
         	 }
         	 totalcolumnwidth=totalcolumnwidth-columngap;
         	 index2=currentblock;
         	 blockwidth.set(currentblock, totalcolumnwidth);
         	 xpos=subblockxpos.get(index2).get(0)+blockwidth.get(currentblock);
         	 for (iii=0;iii<=currenttabularline;iii++){
         		 twidth=0;
         		 for (i=0;i<=numcolumn-1;i++){       		 	 
         			 for (ii=1;ii<=subblock.get(homeblock.get(opentabularlineblock.get(iii*numcolumn+i))).size()-1;ii++){        		
         				 index=	 opentabularlineblock.get(iii*numcolumn+i)-openblock.get(currentblock)+ii;     

         				 if (columnspec.charAt(i)=='l'){subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(index)+twidth);}
         				 else if (columnspec.charAt(i)=='c'){twidth2=(columnwidth.get(i)-blockwidth.get(homeblock.get(opentabularlineblock.get(iii*numcolumn+i))))/2; subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(index)+twidth+twidth2);}
         				 else if (columnspec.charAt(i)=='r'){twidth2=columnwidth.get(i)-blockwidth.get(homeblock.get(opentabularlineblock.get(iii*numcolumn+i))); subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(index)+twidth+twidth2);};
         			 }
         			 twidth=twidth+columnwidth.get(i)+columngap;    
         		 }}
   	 
         	 previousblock=currentblock;
         	 for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
         		 currentblock--;
         	 }	
         	 previoustabular=currenttabular;
         	 for (i=subblocknumber.get(tid);currenttabular >=0 && closeblock.get(currenttabular)>=0;i--){
         		 currenttabular--;
         	 }	

         	 if (tabularlinenumber>0) {					  
         		 textpaint.setTextSize(thisfontsize);
         		 textpaint.getTextBounds("a",0,"a".length(),textbounds);
         		 tempy=blockdepth.get(previousblock)-blockheight.get(previousblock)/2+textbounds.height()/2;
         		 for (i=opentabularlineblock.get(0)-opentabular.get(previoustabular);i<=closetabularlineblock.get(currenttabularlineblock)-opentabular.get(previoustabular);i++){
         			 subblockypos.get(previousblock).set(i, subblockypos.get(previousblock).get(i)-tempy);
         		 }
         		 blockdepth.set(previousblock,blockdepth.get(previousblock)-tempy);}
         	 insert(tid,previousblock, currentblock, blockwidth.get(previousblock), blockheight.get(previousblock),blockdepth.get(previousblock));				                  

         	 j+=5;
         	 temp = molecule.charAt(j);
         	 if (temp == charExclam){
         		 key = "";
         		 for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
         			 key = key + molecule.charAt(ii);
         		 }}	
				}else  if (temp == charExclam && key.equals(stringbln)) {                   // begin tabular line
					tabularlinenumber++;
					previoustabularline=currenttabularline;
					currenttabularline=tabularlinenumber;
	  					  		
					blocknumber++;			 
					previousblock=currentblock;
					currentblock= blocknumber;
					thisblocklevel++;
	  							 
					if (currenttabularline >=1){xpos=subblockxpos.get(homeblock.get(opentabularline.get(previoustabularline))).get(0);};
					create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);
	  				    		 
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);	    		  				   		  								
					opentabularline.add(subblocknumber.get(tid)); closetabularline.add(-1); 
	  								
					tabularlineblocknumber=-1;
	  				
	  				column=-1;
	  				maxcolumnwidth=0;

	  				j+=5;
	  				temp = molecule.charAt(j);
	  				if (temp == charExclam){
	  					key = "";
	  					for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
	  						key = key + molecule.charAt(ii);
	  					}}	
				}else  if (temp == charExclam && key.equals(stringeln)) {                   // end tabular line

					closetabularline.set(currenttabularline, subblocknumber.get(tid));closeblock.set(currentblock, subblocknumber.get(tid));
           
					float gap2=gap*thisfontsize/fontsize;
					index2=currentblock;
					if (currenttabularline > 0){
						tempy=totaltabulardepth+blockheight.get(currentblock)-blockdepth.get(currentblock)+gap2;
						for (i=1;i<=subblock.get(currentblock).size()-1;i++){
							subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+tempy);
						}
					}
            
       	 
					previousblock=currentblock;
					for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
						currentblock--;
					}	

					if (currenttabularline >=1) {
						totaltabularheight=totaltabularheight+blockheight.get(previousblock)+gap2;
						totaltabulardepth=totaltabulardepth+blockheight.get(previousblock)+gap2;		  
						insert(tid,previousblock, currentblock, 0.0f, totaltabularheight, totaltabulardepth);				                  
					} else {
						insert(tid,previousblock, currentblock,  blockwidth.get(previousblock),blockheight.get(previousblock)  , blockdepth.get(previousblock));
						totaltabularheight=blockheight.get(previousblock);
						totaltabulardepth=blockdepth.get(previousblock);
					}
			  
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				}else  if (temp == charExclam && key.equals(stringolb)) {                   // begin tabular line block

					tabularlineblocknumber++;
					currenttabularlineblock=tabularlineblocknumber;
					column++;columnwidth.add(0.0f);
					blocknumber++;			 
					previousblock=currentblock;
					currentblock= blocknumber;
					thisblocklevel++;
					  
					textpaint.setTextSize(thisfontsize);
					textpaint.setTypeface(tf.get(fontinteger));
					textpaint.getTextBounds("Aj",0,"Aj".length(),textbounds);
					spacewidth=textpaint.measureText(" ");
					spaceheight=textbounds.height();
					spacedepth=textbounds.bottom;
						
					create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);			    		  
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,spacewidth,spaceheight,spacedepth,xpos,ypos,thisattribute);
					openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);	    		  				   		  								
					opentabularlineblock.add(subblocknumber.get(tid)); closetabularlineblock.add(-1); 
					xpos=subblockxpos.get(homeblock.get(opentabularline.get(0))).get(0);
					  					 					  
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				}else  if (temp == charExclam && key.equals(stringclb)) {                   // end tabular line block

					closetabularlineblock.set(currenttabularlineblock, subblocknumber.get(tid));closeblock.set(currentblock, subblocknumber.get(tid));

					maxcolumnwidth = Math.max(columnwidth.get(column),blockwidth.get(currentblock));
					columnwidth.set(column, maxcolumnwidth);
					previousblock=currentblock;
					for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
						currentblock--;
					}	
					insert(tid,previousblock, currentblock,  blockwidth.get(previousblock),blockheight.get(previousblock) , blockdepth.get(previousblock));

					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				}else if (temp == charExclam && key.equals("blank")) { 

					sfontsize=Integer.toString(thisfontsize);
					ij=sfontsize.length();
					if (ij==1){
						thisattribute=thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4);
					} else if (ij==2){
						thisattribute=thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4);
					  } else if (ij==3){
						  thisattribute=thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4);
					  }			
	
					textpaint.setTextSize(thisfontsize);
					textpaint.setTypeface(tf.get(fontinteger));
	  
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock," ",(float)textpaint.measureText(" "),0.0f,0.0f,xpos,ypos,thisattribute);
					homeblock.add(currentblock);
					xpos=xpos+textbounds.width();
	  
					j+=7;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}				   

				}else if (temp == charExclam && key.equals("dno")) {                                // do nothing
		    		  
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					homeblock.add(currentblock);
					    
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}				   
				}else if (temp == charExclam && key.equals(stringobx)) {                                // open mbox
                 
					thisattribute=thisattribute.substring(0,4)+"000"+thisattribute.substring(7);
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				}else if (temp == charExclam && key.equals(stringcbx)) {                                // close mbox
             
					thisattribute=thisattribute.substring(0,4)+defaultattribute.substring(4,7)+thisattribute.substring(7);
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
							key = key + molecule.charAt(ii);
						}}	
				} else if (temp == charExclam && key.charAt(0) == 'A') {                       //Begin attribute

					if (key.charAt(1) == 'o'){
						String attribute;
			    		int jj=key.indexOf("(");
			    		if (jj >2){
			    			attribute = key.substring(2,jj);
			    		} else {
			    			attribute = key.substring(2);
			    		}
			    		if (attribute.equals("underlinetext")){			    			
			    			thisattribute="0"+thisattribute.substring(1,18)+"1"+thisattribute.substring(19);			    			
			    		} else if (attribute.equals("strikethru")){			    			
			    			thisattribute="0"+thisattribute.substring(1,19)+'1'+thisattribute.substring(20);			    			
			    		} else if (attribute.equals("skew")){			    			
			    			if (molecule.charAt(j+attribute.length()+3)=='(' ){
			    				jj = molecule.indexOf(')',j+attribute.length()+3);
			    				thisattribute="0"+thisattribute.substring(1,20)+molecule.substring(j+attribute.length()+4,jj)+thisattribute.substring(25);;				    				
			    				j=jj-key.length();
			    			} else {
			    				thisattribute="0"+thisattribute.substring(1,20)+"-0.25"+thisattribute.substring(25);
			    			};							    						    			
			    		}else if (attribute.equals("alpha")){   // alpha does not work
			    			synchronized(this){
			    				Block.error.put(tid, true);
			    				Block.errormessage.put(tid, "Alpha does not work, parse failed!");}
			    			return;
			    		}else if (attribute.equals("shadow")){

			    			if (molecule.charAt(j+attribute.length()+3)=='(' ){
			    				jj = molecule.indexOf(')',j+attribute.length()+3);
			    				thisattribute="0"+thisattribute.substring(1,29)+molecule.substring(j+attribute.length()+4,jj);				    				
			    				j=jj-key.length();
			    			} else {
			    				thisattribute="0"+thisattribute.substring(1,29)+"222black";}
			    		};
			    		j=j+key.length()+2;
			    		temp = molecule.charAt(j);
			    		if (temp == charExclam){
			    			key = "";
			    			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			    				key = key + molecule.charAt(ii);
			    			}}	

			    		} else if (key.charAt(1) == 'c'){
			    			String attribute;
			    			attribute = key.substring(2);			    		
			    			if (attribute.equals("underlinetext")){			    			    			
			    			thisattribute=thisattribute.substring(0,18)+"0"+thisattribute.substring(19);				    			
			    		} else if (attribute.equals("strikethru")){			    			
			    			thisattribute=thisattribute.substring(0,19)+"0"+thisattribute.substring(20);
			    		} else if (attribute.equals("skew")){			    			
			    			thisattribute=thisattribute.substring(0,20)+"+0.00"+thisattribute.substring(25);
			    		}else if (attribute.equals("alpha")){			    			
		//	    			thisattribute=thisattribute.substring(0,25)+"0xFF"+thisattribute.substring(29);  //alpha not working !!
			    		}else if (attribute.equals("shadow")){			    			
			    			thisattribute=thisattribute.substring(0,29)+"0000xFF000000";
			    		};
			    		
			    		if (thisattribute.substring(1).equals(defaultattribute.substring(1))){ thisattribute='1'+thisattribute.substring(1);};
			    		
			    		j=j+key.length()+2;
			    		temp = molecule.charAt(j);
			    		if (temp == charExclam){
			    			key = "";
			    			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			    				key = key + molecule.charAt(ii);
			    			}}					    		
			    		}
				} else if (temp == charExclam && key.charAt(0) == 'F') {                       //Begin font
					
					String fontname = key.substring(2);
					if (key.charAt(1) == 'o'){
						fontinteger = font.fontname.indexOf(fontname);
			    		
						if (Integer.toString(fontinteger).length()==1){
							thisattribute=thisattribute.substring(0,4)+"00"+Integer.toString(fontinteger)+thisattribute.substring(7);
						} else if (Integer.toString(fontinteger).length()==2){
							thisattribute=thisattribute.substring(0,4)+"0"+Integer.toString(fontinteger)+thisattribute.substring(7);
						} else if (Integer.toString(fontinteger).length()==3){
							thisattribute=thisattribute.substring(0,4)+Integer.toString(fontinteger)+thisattribute.substring(7);
						} 
						j=j+key.length()+2;
						temp = molecule.charAt(j);
						if (temp == charExclam){
							key = "";
							for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
								key = key + molecule.charAt(ii);
							}}	
					} else if (key.charAt(1) == 'c'){
						fontinteger = Integer.parseInt(defaultattribute.substring(4,7));
						if (Integer.toString(fontinteger).length()==1){
							thisattribute=thisattribute.substring(0,4)+"00"+Integer.toString(fontinteger)+thisattribute.substring(7);
						} else if (Integer.toString(fontinteger).length()==2){
							thisattribute=thisattribute.substring(0,4)+"0"+Integer.toString(fontinteger)+thisattribute.substring(7);
						} else if (Integer.toString(fontinteger).length()==3){
							thisattribute=thisattribute.substring(0,4)+Integer.toString(fontinteger)+thisattribute.substring(7);
						} 
						j=j+key.length()+2;
						temp = molecule.charAt(j);
						if (temp == charExclam){
							key = "";
							for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
								key = key + molecule.charAt(ii);
							}}					    		
					}
				} else if (temp == charExclam && key.charAt(0) == 'X') {                //   Begin size
					String sizename = key.substring(2);
					if (key.charAt(1) == 'o'){
						thisfontsize= (int)((float)fontsize*Header.sizefactor.get(sizename));
						j=j+key.length()+2;
						temp = molecule.charAt(j);
						if (temp == charExclam){
							key = "";
							for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
								key = key + molecule.charAt(ii);
							}}	
					} else if (key.charAt(1) == 'c'){
			    		thisfontsize= fontsize;			    		
			    		j=j+key.length()+2;
			    		temp = molecule.charAt(j);
			    		if (temp == charExclam){
			    			key = "";
			    			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			    				key = key + molecule.charAt(ii);
			    			}}					    		
					}
				} else if (temp == charExclam && key.charAt(0) == 'C') {                //   Begin color
			    	
					String colorname = key.substring(2);
			    	if (key.charAt(1) == 'o'){
			    		thisattribute=thisattribute.substring(0,7)+color.colorinteger.get(colorname)+thisattribute.substring(17);
			    		j=j+key.length()+2;
			    		temp = molecule.charAt(j);
			    		if (temp == charExclam){
			    			key = "";
			    			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			    				key = key + molecule.charAt(ii);
			    			}}									
			    	} else if (key.charAt(1) == 'c'){
			    		
			    		thisattribute=thisattribute.substring(0,7)+defaultattribute.substring(7,17)+thisattribute.substring(17);
			    		j=j+key.length()+2;
			    		temp = molecule.charAt(j);
			    		if (temp == charExclam){
			    			key = "";
			    			for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!'||molecule.charAt(ii)==')' || molecule.charAt(ii)=='(');ii++){
			    				key = key + molecule.charAt(ii);
			    			}}					    		
			    	}	
				}else  if (temp == charExclam  && key.charAt(0) == 'V') {                       // open enclosure
					key = key.substring(1);
					if (Symbol.symboltype.containsKey(key) && 
							(Symbol.symboltype.get(key) == 1 || Symbol.symboltype.get(key) == 2 ||Symbol.symboltype.get(key) == 3 || Symbol.symboltype.get(key) == 5 || Symbol.symboltype.get(key) == 6 || Symbol.symboltype.get(key) == 7 || Symbol.symboltype.get(key) == 8 || Symbol.symboltype.get(key) == 9)) {                        // open enclosure
						ii=j+key.length()+2;
						temp=molecule.charAt(ii);
			    	   
						if (temp=='{'){

							enclosurenumber++;
							currentenclosure=enclosurenumber;
							thisenclosurelevel++;
							previousblock=currentblock;
							blocknumber++;			  
							currentblock= blocknumber;
							thisblocklevel++;
							synchronized(this){
								create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);		    		  
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
							}
							openblock.add(subblocknumber.get(tid)); closeblock.add(-1);homeblock.add(currentblock);	    
	    		  					
							openenclosure.add(subblocknumber.get(tid)); closeenclosure.add(-1); showopenenclosure.add(true); 
							index2=+currentblock;
							switch(Symbol.symboltype.get(key)){
							case 1:
							case 3:
								j3=j+key.length()+3;
								if ( molecule.charAt(j3)== '!' && molecule.charAt(j3+1)== '.'){
									showopenenclosure.set(currentenclosure, false);
									subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
									homeblock.add(currentblock);								
									j=j+2;
								} else {
									key2="!"+key+" ";
									subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
									homeblock.add(currentblock);							    
								};
								break;	    
							case 5:
							case 6:
							case 7:
							case 8:
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);	
								break;
							case 9:
								key2="!"+key+" ";
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);			
								break;       
							}					
							parentkey=key;
							index2=currentblock;
							index = subblocknumber.get(tid)-openblock.get(currentblock);
							subblockxpos.get(index2).set(index,xpos);
							subblockypos.get(index2).set(index,ypos);			                
							blockwidth.set(currentblock, 0.0f);
							blockheight.set(currentblock, 0.0f);
							blockdepth.set(currentblock, 0.0f);
	                				  		    
							j=j+key.length()+3;
							temp = molecule.charAt(j);
							key = "";
							for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
								key = key + molecule.charAt(ii);
							}				  				
						} else if (temp == '}'){                                             // close enclosure
							index2=currentblock;
							closeblock.set(currentblock, subblocknumber.get(tid));
							containfraction = false;
							containenclosure=false;
							for (i=currentblock+1;i<=blocknumber && !containfraction && !containenclosure;i++){
								if (blockenclosurelevel.get(i)==thisenclosurelevel && 
										blocksuperscriptlevel.get(i)==thissuperscriptlevel && 
										blocksubscriptlevel.get(i)==thissubscriptlevel && 
										blockfractionlevel.get(i)==thisfractionlevel+1 && 
										blocktabularlevel.get(i)==-1 &&
										openblock.get(i)> openblock.get(currentblock) && closeblock.get(i) <= closeblock.get(currentblock)){
									containfraction=true;
								}}						
              
							textpaint.setTextSize(thisfontsize);
							textpaint.setTypeface(tf.get(0));
							textpaint.getTextBounds("1",0,"1".length(),textbounds);	
							Float off=(float) textbounds.height()/2;
							if (containfraction){adjustfraction(tid,currentblock, blocknumber, homeblock,openblock,closeblock,thisfractionlevel, thisblocklevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, off, gap);}
							containfraction = false;
							containenclosure=false;
                
							switch(Symbol.symboltype.get(key)){
							case 2:
							case 3:					
								j3=j+key.length()+3;
								if ( molecule.charAt(j3)== '!' && molecule.charAt(j3+1)== '.'){
									showcloseenclosure=false;
									subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
									homeblock.add(currentblock);	
									j=j+2;
								} else {
									key2="!"+key+" ";
									showcloseenclosure=true;
									subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
									homeblock.add(currentblock);	
								}
								closeblock.set(currentblock,subblocknumber.get(tid));
				
								closeenclosure.set(currentenclosure,subblocknumber.get(tid));
								twidth=0;theight=0;tdepth=0;
								for (i=0; theight<=blockheight.get(currentblock)+1;i++){
									symbolpaint.setTextSize(i+8); 
				     		
									symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);					      		  
									theight = symbolbounds.height();
									i3=i;};								  
									twidth =  symbolpaint.measureText(Symbol.symbolunicode.get(key));
									tdepth = symbolbounds.bottom;
									index=subblocknumber.get(tid)-openblock.get(currentblock);
									if (showopenenclosure.get(currentenclosure)){
										subblockwidth.get(index2).set(1,twidth);
										subblockheight.get(index2).set(1,theight);
										subblockdepth.get(index2).set(1,tdepth);
										sfontsize=Integer.toString(i3+8);
										int is=sfontsize.length();
										if (is==1){
											subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
										} else if (is==2){
											subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
										} else if (is==3){
											subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
										}			
							
										subblockypos.get(index2).set(1,  ypos+blockdepth.get(currentblock)-tdepth);
										subblockxpos.get(index2).set(1, subblockxpos.get(index2).get(0));
										blockwidth.set(currentblock,blockwidth.get(currentblock)+subblockwidth.get(index2).get(1));
										for (i=2; i<=subblocknumber.get(tid)-openblock.get(currentblock);i++)
										{subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+subblockwidth.get(index2).get(1));};
									};
						    
									if (showcloseenclosure){
										subblockwidth.get(index2).set(index,twidth);
										subblockheight.get(index2).set(index,theight);
										subblockdepth.get(index2).set(index,tdepth);	

										sfontsize=Integer.toString(i3+8);
										int is=sfontsize.length();
										if (is==1){
											subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
										} else if (is==2){
											subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
										} else if (is==3){
											subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
										}			
										subblockypos.get(index2).set(index,  ypos+blockdepth.get(currentblock)-tdepth);
										subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0)+blockwidth.get(currentblock));
										blockwidth.set(currentblock,blockwidth.get(currentblock)+subblockwidth.get(index2).get(index));
									};
									if (showopenenclosure.get(currentenclosure) || showcloseenclosure){
										blockheight.set(currentblock,Math.max(blockheight.get(currentblock),theight+gap));
									}			
									if (showcloseenclosure){
										xpos = subblockxpos.get(index2).get(index)+ twidth;
									} else {
										xpos = subblockxpos.get(index2).get(index);
									}
									parentkey=key; parentblock=currentblock;
									break;
							case 5:
							case 6 :
								j3=j+key.length()+3;
								key2="!"+key+" ";
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);	

								closeblock.set(currentblock,subblocknumber.get(tid));							
								closeenclosure.set(currentenclosure,subblocknumber.get(tid));
						
								twidth=0;theight=0;tdepth=0;
								for (i=0; twidth<=blockwidth.get(currentblock);i++){
									symbolpaint.setTextSize(i+8);
									symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);
									twidth=symbolbounds.width();
									i3=i;};
				      		  
									theight = symbolbounds.height();
									tdepth = symbolbounds.bottom; 
							 
									index2=currentblock;
									index=subblock.get(index2).size()-1;
									subblockwidth.get(index2).set(index,twidth);		
									subblockheight.get(index2).set(index, theight);
									subblockdepth.get(index2).set(index, tdepth);							
									if (Symbol.symboltype.get(key)==5){
										subblockypos.get(index2).set(index, subblockypos.get(index2).get(0)-blockheight.get(currentblock)+blockdepth.get(currentblock)-tdepth);
										blockheight.set(currentblock,blockheight.get(currentblock)+theight);
										blockwidth.set(currentblock, Math.max(blockwidth.get(currentblock),twidth));
										subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0));
									} else if (Symbol.symboltype.get(key)==6){								
										blockheight.set(currentblock,blockheight.get(currentblock)+theight+gap);
										blockdepth.set(currentblock,blockdepth.get(currentblock)+theight+gap);
										subblockypos.get(index2).set(index, subblockypos.get(index2).get(0)+blockdepth.get(currentblock)-tdepth);
										case6xmargin=(symbolpaint.measureText(Symbol.symbolunicode.get(key))-twidth)/2;
										subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0)-case6xmargin);
									}

									sfontsize=Integer.toString(i3+8);
									int is=sfontsize.length();
									if (is==1){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
									} else if (is==2){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
									} else if (is==3){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
									}									     
									parentkey=key; 
									break;
							case 7:
						
								j3=j+key.length()+3;
								key2="!"+key+" ";
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);	

								closeblock.set(currentblock,subblocknumber.get(tid));							
								closeenclosure.set(currentenclosure,subblocknumber.get(tid));
						
								twidth=0;theight=0;tdepth=0;
								if (Symbol.symbolsubtype.get(key)==1){
									i3=thisfontsize-8; 
									symbolpaint.setTextSize(i3+8);
									symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);
									twidth=symbolbounds.width();
								} else if (Symbol.symbolsubtype.get(key)==2){
									for (i=0; twidth<=blockwidth.get(currentblock) ;i++){
										symbolpaint.setTextSize(i+8);
										symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);
										twidth=symbolbounds.width();
										i3=i;};			
								};
								theight = symbolbounds.height();
								tdepth = symbolbounds.bottom; 

								case7xmargin=(blockwidth.get(currentblock)-twidth)/2;
				      		
								index2=currentblock;
								index=subblock.get(index2).size()-1;
								subblockwidth.get(index2).set(index,twidth);		
								subblockheight.get(index2).set(index, theight);
								subblockdepth.get(index2).set(index, tdepth);	
								if (!key.equals("not") && !key.equals("bar")){
									subblockypos.get(index2).set(index, subblockypos.get(index2).get(0)-blockheight.get(currentblock)+blockdepth.get(currentblock)-tdepth-gap);
									blockheight.set(currentblock,blockheight.get(currentblock)+theight+gap);
								} else {
									subblockypos.get(index2).set(index,subblockypos.get(index2).get(0));
								}
								if (Symbol.symbolsubtype.get(key)==1){
									subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0)+twidth+case7xmargin);
								} else if (Symbol.symbolsubtype.get(key)==2){
									subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0)+case7xmargin);
								}
								blockwidth.set(currentblock, Math.max(blockwidth.get(currentblock),twidth));
                       
								sfontsize=Integer.toString(i3+8);
								is=sfontsize.length();
								if (is==1){
									subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
								} else if (is==2){
									subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
								} else if (is==3){
									subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
								}									     
								parentkey=key; 
													
								break;
							case 8:
								j3=j+key.length()+3;
								key2="!"+key+" ";
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,key2,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);	

								closeblock.set(currentblock,subblocknumber.get(tid));
								closeenclosure.set(currentenclosure,subblocknumber.get(tid));
						
								twidth=0;theight=0;tdepth=0;
								for (i=0; twidth<=blockwidth.get(currentblock);i++){
									symbolpaint.setTextSize(i3+8); 
									symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);
									twidth=symbolbounds.width();
									i3=i;};
							  
									theight = symbolbounds.height();
									tdepth = symbolbounds.bottom;			
						
									blockheight.set(currentblock,blockheight.get(currentblock)+theight+gap);
									blockdepth.set(currentblock,blockdepth.get(currentblock)+theight+gap);
									blockwidth.set(currentblock, Math.max(blockwidth.get(currentblock),twidth));
					    
									index2=currentblock;
									index=subblock.get(index2).size()-1;
									subblockwidth.get(index2).set(index,blockwidth.get(currentblock));		
									subblockheight.get(index2).set(index, theight);
									subblockdepth.get(index2).set(index, tdepth);
									subblockypos.get(index2).set(index, subblockypos.get(index2).get(0)+blockdepth.get(currentblock)-tdepth);
									subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(0));
									sfontsize=Integer.toString(i3+8);
									is=sfontsize.length();
									if (is==1){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
									} else if (is==2){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
									} else if (is==3){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
									}									     
				                
									parentkey=key;
									break;
					    
							case 9:
								j3=j+key.length()+3;
								strokewidth=(float)thisfontsize/10; if (strokewidth < 1){strokewidth=1;};
								subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringhline,0.0f,strokewidth,0.0f,xpos,ypos,thisattribute);
								homeblock.add(currentblock);	

								closeblock.set(currentblock,subblocknumber.get(tid));
								closeenclosure.set(currentenclosure,subblocknumber.get(tid));

								twidth=0;theight=0;tdepth=0;
								for (i=0; theight<=blockheight.get(currentblock)+gap+1;i++){
									symbolpaint.setTextSize(i+8); 
									symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);					      		  
									theight = symbolbounds.height();
									i3=i;};								  
									twidth =  symbolpaint.measureText(Symbol.symbolunicode.get(key));
									tdepth = symbolbounds.bottom;
									index2=currentblock;
							  
									subblockwidth.get(index2).set(1,twidth);
									subblockheight.get(index2).set(1,theight);
									subblockdepth.get(index2).set(1,tdepth);
						
									index=subblock.get(index2).size()-1;
									subblockwidth.get(index2).set(index,blockwidth.get(currentblock)+1);		
									subblockypos.get(index2).set(index, ypos-blockheight.get(currentblock)-gap+blockdepth.get(currentblock));
									subblockxpos.get(index2).set(index, subblockxpos.get(index2).get(1)+subblockwidth.get(index2).get(1)-1);
                       
									tempy=blockwidth.get(currentblock)+1;
									sfontsize=Integer.toString((int)tempy+1);
									is=sfontsize.length();
									if (is==1){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
									} else if (is==2){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
									} else if (is==3){
										subblockattribute.get(index2).set(index, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
									}	
						
									blockheight.set(currentblock,blockheight.get(currentblock)+gap+strokewidth);				
									subblockypos.get(index2).set(1,  ypos+blockdepth.get(currentblock)-tdepth);			
									blockwidth.set(currentblock,blockwidth.get(currentblock)+subblockwidth.get(index2).get(1));
									for (i=2; i<=subblocknumber.get(tid)-openblock.get(currentblock)-1;i++)
									{subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+subblockwidth.get(index2).get(1));};

									sfontsize=Integer.toString(i3+8);
									is=sfontsize.length();
									if (is==1){
										subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4));
									} else if (is==2){
										subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4));
									} else if (is==3){
										subblockattribute.get(index2).set(1, thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4));
									}									     
						
									parentkey="";
									break;					   		
							}
					
               
							closeblock.set(currentblock, subblocknumber.get(tid));			
							closeenclosure.set(currentenclosure,subblocknumber.get(tid));
							thisenclosurelevel--;
							previousenclosure = currentenclosure;
							for (i=subblocknumber.get(tid);currentenclosure >= 0 && closeenclosure.get(currentenclosure)>=0;i--){
								currentenclosure--;
							}
							thisblocklevel--;
							previousblock=currentblock;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;
							}		

							insert(tid,previousblock, currentblock, blockwidth.get(previousblock), blockheight.get(previousblock),blockdepth.get(previousblock));				                  
 
							j=j+key.length()+3;
							temp = molecule.charAt(j);
							if (temp == charExclam){
								key = "";
								for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
									key = key + molecule.charAt(ii);
								}}
						}   }}
				else if (temp == charExclam && key.equals(stringosp)) {                        // open superscript

					thissuperscriptlevel++;		 
					superscriptnumber++;
					currentsuperscript=superscriptnumber;
					aftersubscript.add(false);

					supparentkey.add(parentkey);

					if (Symbol.symboltype.containsKey(parentkey) && (Symbol.symboltype.get(parentkey)<=3)){
						supparentblock.add(previousblock);
					} else   if (Symbol.symboltype.containsKey(parentkey) && (Symbol.symboltype.get(parentkey)==5 || Symbol.symboltype.get(parentkey)==7  )){
						supparentblock.add(previousblock);
					} else if (supparentkey.get(currentsuperscript).equals("csp")){			
						supparentblock.add(parentblock);
					} else if (supparentkey.get(currentsuperscript).equals("csu")){	
						supparentkey.set(currentsuperscript, subparentkey.get(previoussubscript));
						supparentblock.add(subparentblock.get(previoussubscript));					  
						aftersubscript.set(currentsuperscript, true);
					} else {
						supparentblock.add(currentblock);
					}
		                  
					previousblock=currentblock;
					blocknumber++;			  
					currentblock= blocknumber;
					thisblocklevel++;			
					thisfractionlevel=0;

					thisenclosurelevel = -1;
					synchronized(this){
						create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);
						subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock	 ,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					}
					homeblock.add(currentblock);	 openblock.add(subblocknumber.get(tid)); closeblock.add(-1);

					opensuperscript.add(subblocknumber.get(tid));closesuperscript.add(-1);
					thisfontsize=fontsize*5/12;if (thisfontsize<8){thisfontsize=8;};		    
			    		  
					if (Symbol.symboltype.containsKey(supparentkey.get(currentsuperscript))){
						switch(Symbol.symboltype.get(supparentkey.get(currentsuperscript))){
						case 1 :
						case 6 :
						case 8 :
						case 10 :
						case 11 :
						case 12 :
						case 15 :
						case 17 :
							synchronized(this){
								Block.error.put(tid, true);
								Block.errormessage.put(tid, key+" does not have superscript, parse failed!");}
							return;
						case 2 :
						case 3:
							ypos = ypos+blockdepth.get(supparentblock.get(currentsuperscript))-blockheight.get(supparentblock.get(currentsuperscript));
							if (aftersubscript.get(currentsuperscript)){xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(0)+blockwidth.get(supparentblock.get(currentsuperscript));};
							break;
						case 5 :
							xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(subblock.get(supparentblock.get(currentsuperscript)).size()-1);
							break ;
						case 7 :
							xpos=subblockxpos.get(homeblock.get(closeenclosure.get(previousenclosure))).get(0)+blockwidth.get(homeblock.get(closeenclosure.get(previousenclosure)));
							break ;               	   
						case 13 :
						case 14 :
							if (aftersubscript.get(currentsuperscript)){xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(0)+blockwidth.get(supparentblock.get(currentsuperscript))-blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)));};
							break ;       
						case 19 :
						case 20 :
						case 21 :
							if (!aftersubscript.get(currentsuperscript)){
								xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(subblock.get(parentblock).size()-1);
							} else {
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size()-1;
								xpos=Math.min(subblockxpos.get(supparentblock.get(currentsuperscript)).get(index), subblockxpos.get(supparentblock.get(currentsuperscript)).get(index+2));
							}
							break ;
						case 22 :
						case 23 :
						case 24 :
							if (!aftersubscript.get(currentsuperscript)){
    
							} else {
								index=opensubscript.get(previoussubscript)-openblock.get(supparentblock.get(currentsuperscript))-1;
								xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(index)+subblockwidth.get(supparentblock.get(currentsuperscript)).get(index);};             		               
								break ;
						} 
					} else if (supparentkey.get(currentsuperscript).equals("csp")){	                	
						ypos = ypos+blockdepth.get(supparentblock.get(currentsuperscript))-blockheight.get(supparentblock.get(currentsuperscript));
					}else {
						if (aftersubscript.get(currentsuperscript)){xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(0)+blockwidth.get(supparentblock.get(currentsuperscript))-blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)));};
					}				    	   

					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = ""; 
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
					    key = key + molecule.charAt(ii);
						}}	
			  
				} else  if (temp == charExclam && key.equals(stringcsp)) {		                     //  close superscript;
	  			
					index2=currentblock;
					closesuperscript.set(currentsuperscript, subblocknumber.get(tid));
					closeblock.set(currentblock, subblocknumber.get(tid));
					parentkey=supparentkey.get(currentsuperscript);

					if (Symbol.symboltype.containsKey(parentkey) 
							&&  (Symbol.symboltype.get(parentkey)<=7 || (Symbol.symboltype.get(parentkey)>=19 && Symbol.symboltype.get(parentkey)<=24))
							){
						switch(Symbol.symboltype.get(parentkey)){
						case 2    :
						case 3    :
							tempy=(blockheight.get(currentblock)-blockdepth.get(currentblock))/2;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+tempy);
							}
							blockheight.set(currentblock, blockheight.get(supparentblock.get(currentsuperscript))+blockheight.get(currentblock)-blockdepth.get(currentblock)-tempy);
							blockdepth.set(currentblock, blockdepth.get(supparentblock.get(currentsuperscript)));	
		  
							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;
							}		
							if (!aftersubscript.get(currentsuperscript)){ 
								insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock), blockdepth.get(previousblock));				                  
							} else {
								width1=blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)));
								width2=blockwidth.get(previousblock);
								maxwidth=Math.max(width1,width2);
								insert(tid,previousblock, currentblock,maxwidth-width1, blockheight.get(previousblock),blockdepth.get(previousblock));				    
							  }
							index2=+currentblock;
							ypos=subblockypos.get(index2).get(0);
							xpos=subblockxpos.get(index2).get(0)+maxwidth;
	                  
							break;
						case 5 :
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+blockdepth.get(supparentblock.get(currentsuperscript))-blockheight.get(supparentblock.get(currentsuperscript))-blockdepth.get(currentblock));
							}
							index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
							maxwidth=Math.max(subblockwidth.get(supparentblock.get(currentsuperscript)).get(index), blockwidth.get(currentblock));
							tempy=(subblockwidth.get(supparentblock.get(currentsuperscript)).get(index)-blockwidth.get(currentblock))/2;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+tempy);
							}
			                	 
							ypos=subblockypos.get(supparentblock.get(currentsuperscript)).get(0);
							xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(1)+blockwidth.get(supparentblock.get(currentsuperscript));
							blockdepth.set(currentblock, blockdepth.get(supparentblock.get(currentsuperscript)));    
							blockheight.set(currentblock, blockheight.get(supparentblock.get(currentsuperscript))+blockheight.get(currentblock)+gap);

							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;						               
							}		
							index2=+currentblock;
							for (i=1;i<=index;i++){
								subblockxpos.get(index2).set(openblock.get(supparentblock.get(currentsuperscript))-openblock.get(currentblock)+i, subblockxpos.get(supparentblock.get(currentsuperscript)).get(i));
							}
							insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));
	                  
							break ;
	                    	  
						case 7 :
							tempy=blockdepth.get(supparentblock.get(currentsuperscript))-blockheight.get(supparentblock.get(currentsuperscript))-blockdepth.get(currentblock)+blockheight.get(currentblock)/2;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+tempy);
							}
							index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
							maxwidth=Math.max(subblockwidth.get(supparentblock.get(currentsuperscript)).get(index), blockwidth.get(currentblock));
			                 			                	 
							ypos=subblockypos.get(supparentblock.get(currentsuperscript)).get(0);
							xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(1)+blockwidth.get(supparentblock.get(currentsuperscript));
			                	  
							blockdepth.set(currentblock, blockdepth.get(supparentblock.get(currentsuperscript)));    
							blockheight.set(currentblock, blockheight.get(supparentblock.get(currentsuperscript))+blockheight.get(currentblock)/2+gap);
		                	  
							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;						               
							}		
							index2=+currentblock;
							for (i=1;i<=index;i++){
								subblockxpos.get(index2).set(openblock.get(supparentblock.get(currentsuperscript))-openblock.get(currentblock)+i, subblockxpos.get(supparentblock.get(currentsuperscript)).get(i));
							}	                      	                      
							insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock), blockdepth.get(previousblock));
							break ;
	                    	  
						case 19 :
						case 20 :
						case 21 :	                    	  
							if (!aftersubscript.get(currentsuperscript)){
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)
											-subblockheight.get(supparentblock.get(currentsuperscript)).get(index)
											+subblockdepth.get(supparentblock.get(currentsuperscript)).get(index)-gap);
								}						                 
							} else {
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-1-subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size();
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)
											-subblockheight.get(supparentblock.get(currentsuperscript)).get(index)
											+subblockdepth.get(supparentblock.get(currentsuperscript)).get(index)-gap);
								}
							}
							if (!aftersubscript.get(currentsuperscript)){
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
								width1=subblockwidth.get(supparentblock.get(currentsuperscript)).get(index);
								width2=blockwidth.get(currentblock);
								maxwidth=Math.max(width1,width2);
								if (width1 > width2){
									float td=(maxwidth-width2)/2;
									for (i=1;i<=subblock.get(index2).size()-1;i++){
										subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+td);
									}
									ypos=subblockypos.get(supparentblock.get(currentsuperscript)).get(0);
									xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(index)+subblockwidth.get(supparentblock.get(currentsuperscript)).get(index);
								} else {
									float td=(maxwidth-width1)/2;		
									subblockxpos.get(supparentblock.get(currentsuperscript)).set(index, subblockxpos.get(supparentblock.get(currentsuperscript)).get(index)+td);
									ypos=subblockypos.get(supparentblock.get(currentsuperscript)).get(0);
									xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(index)+width1+td;
								}
						                  
								blockdepth.set(currentblock, subblockdepth.get(supparentblock.get(currentsuperscript)).get(index));
								blockheight.set(currentblock, subblockheight.get(supparentblock.get(currentsuperscript)).get(index)+blockheight.get(currentblock)+gap);
							             
							} else {
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size()-1;
								width1=subblockwidth.get(supparentblock.get(currentsuperscript)).get(index);
								width2=blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)));
								width3=blockwidth.get(currentblock);
					                  
								// undo the position shift in subscript
					                  
								if (width1 > width2) {				       
					                	  
									float td=subblockxpos.get(supparentblock.get(currentsuperscript)).get(index+2)-subblockxpos.get(supparentblock.get(currentsuperscript)).get(index);
									for (i=index+2;i<=index+subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size();i++){
										subblockxpos.get(supparentblock.get(currentsuperscript)).set(i, subblockxpos.get(supparentblock.get(currentsuperscript)).get(i)-td);
									}	
								}else {
									subblockxpos.get(supparentblock.get(currentsuperscript)).set(index, subblockxpos.get(supparentblock.get(currentsuperscript)).get(index+2));						                	  
								}
								xpos=subblockxpos.get(supparentblock.get(currentsuperscript)).get(index);
					                  
								maxwidth1=Math.max(width1,width2);maxwidth=Math.max(maxwidth1, width3);
								if (maxwidth > width3){
									float td=(maxwidth-width3)/2;
									for (i=1;i<=subblock.get(index2).size()-1;i++){
										subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+td);
									}	
								} 
								if (maxwidth > width2){
									float td=(maxwidth-width2)/2;			
									for (i=index+2;i<=index+subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size();i++){		
										subblockxpos.get(supparentblock.get(currentsuperscript)).set(i, subblockxpos.get(supparentblock.get(currentsuperscript)).get(i)+td);				                	 
									}			
								}
								if (maxwidth > width1){
									float td=(maxwidth-width1)/2;						               	 
									subblockxpos.get(supparentblock.get(currentsuperscript)).set(index, subblockxpos.get(supparentblock.get(currentsuperscript)).get(index)+td);						                	  
								}
								xpos=xpos+maxwidth;
								blockdepth.set(currentblock, blockdepth.get(homeblock.get(opensubscript.get(previoussubscript))));
								blockheight.set(currentblock, blockheight.get(homeblock.get(opensubscript.get(previoussubscript)))+blockheight.get(currentblock)+gap);
							}
							ypos=subblockypos.get(supparentblock.get(currentsuperscript)).get(0);	                 
							             
							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;		
							}		
	 		              
							if (!aftersubscript.get(currentsuperscript)){
								if (subblockwidth.get(supparentblock.get(currentsuperscript)).get(index)<blockwidth.get(previousblock)){
									float td=(maxwidth-subblockwidth.get(supparentblock.get(currentsuperscript)).get(index));
									insert(tid,previousblock, currentblock,td, blockheight.get(previousblock),blockdepth.get(previousblock));
								} else {
									insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));			                  
								}} else {
									if (maxwidth1 > maxwidth){
										insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));
									} else {									  
										insert(tid,previousblock, currentblock,maxwidth-maxwidth1, blockheight.get(previousblock), blockdepth.get(previousblock));
									}						    	  
								}
							break ;
		                 
						case 22 :
						case 23 :
						case 24 :
							if (!aftersubscript.get(currentsuperscript)){
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)-subblockheight.get(supparentblock.get(currentsuperscript)).get(index)+subblockdepth.get(supparentblock.get(currentsuperscript)).get(index));
								}
							}else {
								index=subblock.get(supparentblock.get(currentsuperscript)).size()-1-subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size();
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)-subblockheight.get(supparentblock.get(currentsuperscript)).get(index)+subblockdepth.get(supparentblock.get(currentsuperscript)).get(index));
								}
							}
							blockheight.set(currentblock, subblockheight.get(supparentblock.get(currentsuperscript)).get(index)+blockheight.get(currentblock)-blockdepth.get(currentblock));
							blockdepth.set(currentblock, subblockdepth.get(supparentblock.get(currentsuperscript)).get(index));	
									  
							thisblocklevel--;
							closeblock.set(currentblock,subblocknumber.get(tid));

							previousblock=currentblock;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;
							}		
							if (!aftersubscript.get(currentsuperscript)){ 
								insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock), blockdepth.get(previousblock));				                  
							} else {
								symbolpaint.setTextSize(Integer.parseInt(subblockattribute.get(supparentblock.get(currentsuperscript)).get(1).substring(1,4)));
								symbolpaint.getTextBounds(Symbol.symbolunicode.get("int"),0,Symbol.symbolunicode.get("int").length(),symbolbounds);
								twidth = symbolbounds.width()/3;
								tempy=Math.max(blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)))-twidth,0);
								tempy=Math.max(blockwidth.get(previousblock),tempy)-tempy;
								insert(tid,previousblock, currentblock,tempy, blockheight.get(previousblock), blockdepth.get(previousblock));				    
							}
							index2=+currentblock;
							ypos=subblockypos.get(index2).get(0);
							xpos=subblockxpos.get(index2).get(0)+blockwidth.get(currentblock);
				                  		                     		  
							break ;
						} 
					}else {
						textpaint.setTextSize(thisfontsize);
						textpaint.setTypeface(tf.get(fontinteger));
						spacewidth=textpaint.measureText(" ")/2;
							
						if (!aftersubscript.get(currentsuperscript)){
							index=subblock.get(supparentblock.get(currentsuperscript)).size()-1;
							tempx=subblockheight.get(supparentblock.get(currentsuperscript)).get(index)-subblockdepth.get(supparentblock.get(currentsuperscript)).get(index);
							tempy=tempx/4-blockdepth.get(currentblock);
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)-tempx+tempy);
								subblockxpos.get(index2).set(i,subblockxpos.get(index2).get(i)+spacewidth);
							}
						}else {
							index=subblock.get(supparentblock.get(currentsuperscript)).size()-1-subblock.get(homeblock.get(opensubscript.get(previoussubscript))).size();
							tempx=subblockheight.get(supparentblock.get(currentsuperscript)).get(index)-subblockdepth.get(supparentblock.get(currentsuperscript)).get(index);
							tempy=tempx/4-blockdepth.get(currentblock);
							for (i=1;i<=subblock.get(currentblock).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)-tempx+tempy);
								subblockxpos.get(index2).set(i,subblockxpos.get(index2).get(i)+spacewidth);
							}
						}
						blockheight.set(currentblock, subblockheight.get(supparentblock.get(currentsuperscript)).get(index)+blockheight.get(currentblock)-blockdepth.get(currentblock)-tempy);
						blockdepth.set(currentblock, subblockdepth.get(supparentblock.get(currentsuperscript)).get(index));	
						blockwidth.set(currentblock, blockwidth.get(currentblock)+spacewidth);
							  
						closeblock.set(currentblock,subblocknumber.get(tid));
						thisblocklevel-=2;
						previousblock=currentblock;
						for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
							currentblock--;
						}				                    	  
						if (!aftersubscript.get(currentsuperscript)){ 
							insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock),blockdepth.get(previousblock));				                  
						} else {
							tempy=Math.max(blockwidth.get(previousblock),blockwidth.get(homeblock.get(opensubscript.get(previoussubscript))))-blockwidth.get(homeblock.get(opensubscript.get(previoussubscript)));
							insert(tid,previousblock, currentblock,tempy, blockheight.get(previousblock), blockdepth.get(previousblock));				    
						}
						index2=+currentblock;
						ypos=subblockypos.get(index2).get(0);
						xpos=subblockxpos.get(index2).get(0)+blockwidth.get(currentblock);
					}
					thisfractionlevel = blockfractionlevel.get(currentblock);
					thisenclosurelevel = blockenclosurelevel.get(currentblock);
	                  
					previoussuperscript=currentsuperscript;thissuperscriptlevel--;
					for (i=subblocknumber.get(tid);currentsuperscript >= 0 && closesuperscript.get(currentsuperscript)>=0;i--){
						currentsuperscript--;
					}

					if (thissubscriptlevel >= 0 || thissuperscriptlevel >= 0){
						thisfontsize=fontsize/3;
					}else if (thisfractionlevel<=2){
						thisfontsize=(int)((double)fontsize*fractionfontfactor[thisfractionlevel]);
					}else {
						thisfontsize=(int)((double)fontsize*fractionfontfactor[2]); 
					};
					if (thisfontsize<8){thisfontsize=8;};	
				      
					j+=5;
					temp = molecule.charAt(j);
					parentkey="csp";parentblock=previousblock;
                     
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
							key = key + molecule.charAt(ii);
						}}
					 
				} else  if (temp == charExclam && key.equals(stringosu)) {                        // open subscript

					thissubscriptlevel++;		 
					subscriptnumber++;
					currentsubscript=subscriptnumber;
					aftersuperscript.add(false);
						  
					subparentkey.add(parentkey);

					if (Symbol.symboltype.containsKey(parentkey) && (Symbol.symboltype.get(parentkey)<=3)){
						subparentblock.add(previousblock);
					} else   if (Symbol.symboltype.containsKey(parentkey) && (Symbol.symboltype.get(parentkey)==6 || Symbol.symboltype.get(parentkey)==8 )){
						subparentblock.add(previousblock);
					} else if (subparentkey.get(currentsubscript).equals("csu")){			
						subparentblock.add(parentblock);
					} else if (subparentkey.get(currentsubscript).equals("csp")){	
						subparentkey.set(currentsubscript, supparentkey.get(previoussuperscript));
						subparentblock.add(supparentblock.get(previoussuperscript));
						aftersuperscript.set(currentsubscript, true);				            	  
					} else {
						subparentblock.add(currentblock);
					}
		                  
					previousblock=currentblock;
					blocknumber++;			  
					currentblock= blocknumber;
					thisblocklevel++;			
					thisfractionlevel=0;
					thisenclosurelevel = -1;
					synchronized(this){
						create(tid,currentblock, thisblocklevel, thisfractionlevel, thisenclosurelevel, thissuperscriptlevel, thissubscriptlevel, thistabularlevel);							  
						subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,0.0f,0.0f,0.0f,xpos,ypos,thisattribute);
					}
					homeblock.add(currentblock);	 openblock.add(subblocknumber.get(tid)); closeblock.add(-1);
					opensubscript.add(subblocknumber.get(tid));closesubscript.add(-1);
					thisfontsize=fontsize*5/12;if (thisfontsize<8){thisfontsize=8;};		    
			    		  
					if (Symbol.symboltype.containsKey(subparentkey.get(currentsubscript))){
						switch(Symbol.symboltype.get(subparentkey.get(currentsubscript))){
						case 1 :
						case 5 :
						case 7 :
						case 10 :
						case 11 :
						case 12 :
						case 17 :
							synchronized(this){
								Block.error.put(tid, true);
								Block.errormessage.put(tid, key+" does not have subscript, parsing failed!");}
							return;
						case 2 :
						case 3 :
							ypos = ypos+blockdepth.get(subparentblock.get(currentsubscript));
							if (aftersuperscript.get(currentsubscript)){xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(0)+blockwidth.get(subparentblock.get(currentsubscript));};
							break;
						case 6 :
						case 8 :
							xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(0);
							break ;             	   
						case 13 :
						case 14 :
							if (aftersuperscript.get(currentsubscript)){xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(0)+blockwidth.get(subparentblock.get(currentsubscript))-blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));};
							break ;             	  
						case 15 :
							xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(subblock.get(parentblock).size()-1);
							break ;          
						case 19 :
						case 20 :
						case 21 :
							if (!aftersuperscript.get(currentsubscript)){
								xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(subblock.get(subparentblock.get(currentsubscript)).size()-1);
							} else {
								index=subblock.get(subparentblock.get(currentsubscript)).size()-subblock.get(homeblock.get(opensuperscript.get(previoussuperscript))).size()-1;
								xpos=Math.min(subblockxpos.get(subparentblock.get(currentsubscript)).get(index), subblockxpos.get(subparentblock.get(currentsubscript)).get(index+2));
							} 
							break;
                  	   
						case 22 :  
						case 23 :
						case 24 :
							symbolpaint.setTextSize(Integer.parseInt(subblockattribute.get(subparentblock.get(currentsubscript)).get(1).substring(1,4)));
							symbolpaint.getTextBounds(Symbol.symbolunicode.get("int"),0,Symbol.symbolunicode.get("int").length(),symbolbounds);
							twidth = symbolbounds.width()/3;
							if (!aftersuperscript.get(currentsubscript)){
								xpos=xpos-twidth;               		   
							} else {
								index=opensuperscript.get(previoussuperscript)-openblock.get(subparentblock.get(currentsubscript))-1;
								xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+subblockwidth.get(subparentblock.get(currentsubscript)).get(index)-twidth;    		     
							}
							ypos = ypos+blockdepth.get(subparentblock.get(currentsubscript));              		   
           	   
							break ;  
						} 
					} else if (subparentkey.get(currentsubscript).equals("csu")){	                	
						ypos = ypos+blockdepth.get(subparentblock.get(currentsubscript));
					}else {
						if (aftersuperscript.get(currentsubscript)){xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(0)+blockwidth.get(subparentblock.get(currentsubscript))-blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));};
					}
                  			    	  
					j+=5;
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = ""; 
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
							key = key + molecule.charAt(ii);
						}}	
	  		    				  
				} else  if (temp == charExclam && key.equals(stringcsu)) {		                    // close subscript
					index2=currentblock;
					closesubscript.set(currentsubscript, subblocknumber.get(tid));
					closeblock.set(currentblock, subblocknumber.get(tid));
					parentkey=subparentkey.get(currentsubscript);

					if (Symbol.symboltype.containsKey(parentkey)
							&& (Symbol.symboltype.get(parentkey)<=8 || Symbol.symboltype.get(parentkey)==15 || (Symbol.symboltype.get(parentkey)>=19 && Symbol.symboltype.get(parentkey)<=24))
							){
						switch(Symbol.symboltype.get(parentkey)){
						case 2 :
						case 3 :
							blockheight.set(currentblock, blockheight.get(subparentblock.get(currentsubscript))+blockdepth.get(currentblock));
							blockdepth.set(currentblock, blockdepth.get(subparentblock.get(currentsubscript))+blockdepth.get(currentblock));	

							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;
							}		
							index2=+currentblock;
							if (!aftersuperscript.get(currentsubscript)){ 
								insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock),blockdepth.get(previousblock));				                  
							} else {
								width1=blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));
								width2=blockwidth.get(previousblock);
								maxwidth=Math.max(width1,width2);
								insert(tid,previousblock, currentblock,maxwidth-width1, blockheight.get(previousblock), blockdepth.get(previousblock));				    		    
							}

							ypos=subblockypos.get(index2).get(0);
							xpos=subblockxpos.get(index2).get(0)+maxwidth;
	                  
							break;
						case 6 :
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+blockdepth.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)-blockdepth.get(currentblock));
							}
							index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
							maxwidth=Math.max(subblockwidth.get(subparentblock.get(currentsubscript)).get(index), blockwidth.get(currentblock));
			                 
							tempy=(subblockwidth.get(subparentblock.get(currentsubscript)).get(index)-blockwidth.get(currentblock))/2;
							for (i=1;i<=subblock.get(currentblock).size()-1;i++){
								subblockxpos.get(currentblock).set(i, subblockxpos.get(currentblock).get(i)+tempy-case6xmargin);
							}
							ypos=subblockypos.get(subparentblock.get(currentsubscript)).get(0);
							xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(1)+blockwidth.get(subparentblock.get(currentsubscript));

							blockdepth.set(currentblock, blockdepth.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)+gap);    
							blockheight.set(currentblock, blockheight.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)+gap);

							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;						               
							}		
							index2=+currentblock;
							for (i=1;i<=index;i++){
								subblockxpos.get(index2).set(openblock.get(subparentblock.get(currentsubscript))-openblock.get(currentblock)+i, subblockxpos.get(subparentblock.get(currentsubscript)).get(i));
							}
							insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));
	                  
							break ;
	                    	  
						case 8 :
							float thisgap=gap*fontsize/thisfontsize;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+blockdepth.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)-blockdepth.get(currentblock)+thisgap);
							}
							index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
							maxwidth=Math.max(subblockwidth.get(subparentblock.get(currentsubscript)).get(index), blockwidth.get(currentblock));
			                 
							tempy=(subblockwidth.get(subparentblock.get(currentsubscript)).get(index)-blockwidth.get(currentblock))/2;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+tempy);
							}
							ypos=subblockypos.get(subparentblock.get(currentsubscript)).get(0);
							xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(1)+blockwidth.get(subparentblock.get(currentsubscript));

							blockdepth.set(currentblock, blockdepth.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)+gap);    
							blockheight.set(currentblock, blockheight.get(subparentblock.get(currentsubscript))+blockheight.get(currentblock)+gap);

							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;						               
							}		
							index2=+currentblock;
							for (i=1;i<=index;i++){
								subblockxpos.get(index2).set(openblock.get(subparentblock.get(currentsubscript))-openblock.get(currentblock)+i, subblockxpos.get(subparentblock.get(currentsubscript)).get(i));
							}
							insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));

							break ;
						case 19 :
						case 20 :
						case 21 :

							if (!aftersuperscript.get(currentsubscript)){                                   	
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)
											+subblockdepth.get(subparentblock.get(currentsubscript)).get(index)
											+blockheight.get(currentblock)-blockdepth.get(currentblock)+gap);
								}
							} else {
								index=subblock.get(subparentblock.get(currentsubscript)).size()-1-subblock.get(homeblock.get(opensuperscript.get(previoussuperscript))).size();
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)
											+subblockdepth.get(subparentblock.get(currentsubscript)).get(index)
											+blockheight.get(currentblock)-blockdepth.get(currentblock)+gap);
								}
							}
							if (!aftersuperscript.get(currentsubscript)){
								index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
								width1=subblockwidth.get(subparentblock.get(currentsubscript)).get(index);
								width2=blockwidth.get(currentblock);
								maxwidth=Math.max(width1,width2);
								if (width1 > width2){
									float td=(maxwidth-width2)/2;
									for (i=1;i<=subblock.get(index2).size()-1;i++){
										subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+td);
									}					                	  
									xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+subblockwidth.get(subparentblock.get(currentsubscript)).get(index);
								} else {
									float td=(maxwidth-width1)/2;		
									subblockxpos.get(subparentblock.get(currentsubscript)).set(index, subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+td);					                	  
									xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+width1+td; 			
								}
								blockdepth.set(currentblock, subblockdepth.get(subparentblock.get(currentsubscript)).get(index)+blockheight.get(currentblock)+gap);
								blockheight.set(currentblock, subblockheight.get(subparentblock.get(currentsubscript)).get(index)+blockheight.get(currentblock)+gap);
							} else {					                	  
								index=subblock.get(subparentblock.get(currentsubscript)).size()-subblock.get(homeblock.get(opensuperscript.get(previoussuperscript))).size()-1;
								width1=subblockwidth.get(subparentblock.get(currentsubscript)).get(index);
								width2=blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));
								width3=blockwidth.get(currentblock);
 						                  
 						            // undo the position shift in superscript
 						                  
								if (width1 > width2) {
									float td=subblockxpos.get(subparentblock.get(currentsubscript)).get(index+2)-subblockxpos.get(subparentblock.get(currentsubscript)).get(index);
									for (i=index+2;i<=index+subblock.get(homeblock.get(opensuperscript.get(previoussuperscript))).size();i++){
										subblockxpos.get(subparentblock.get(currentsubscript)).set(i, subblockxpos.get(subparentblock.get(currentsubscript)).get(i)-td);
									}	
								}else {
									subblockxpos.get(subparentblock.get(currentsubscript)).set(index, subblockxpos.get(subparentblock.get(currentsubscript)).get(index+2));						                	  
								}
								xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index);
								maxwidth1=Math.max(width1,width2);maxwidth=Math.max(maxwidth1, width3);
								if (maxwidth > width3){
									float td=(maxwidth-width3)/2;
									for (i=1;i<=subblock.get(index2).size()-1;i++){
										subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+td);
									}	
								} 
								if (maxwidth > width2){
									float td=(maxwidth-width2)/2;
									for (i=index+2;i<=index+subblock.get(homeblock.get(opensuperscript.get(previoussuperscript))).size();i++){
										subblockxpos.get(subparentblock.get(currentsubscript)).set(i, subblockxpos.get(subparentblock.get(currentsubscript)).get(i)+td);
									}	
								}
								if (maxwidth > width1){
									float td=(maxwidth-width1)/2;						               	 
									subblockxpos.get(subparentblock.get(currentsubscript)).set(index, subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+td);						                	  
								}
								xpos=xpos+maxwidth;
								blockdepth.set(currentblock, blockdepth.get(homeblock.get(opensuperscript.get(previoussuperscript)))+blockheight.get(currentblock)+gap);
								blockheight.set(currentblock, blockheight.get(homeblock.get(opensuperscript.get(previoussuperscript)))+blockheight.get(currentblock)+gap);
							}
 					                  
							ypos=subblockypos.get(subparentblock.get(currentsubscript)).get(0); 					                
 						             
							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;		
							}		
  		              
							if (!aftersuperscript.get(currentsubscript)){
								if (subblockwidth.get(subparentblock.get(currentsubscript)).get(index)<blockwidth.get(previousblock)){
									float td=(maxwidth-subblockwidth.get(subparentblock.get(currentsubscript)).get(index));
									insert(tid,previousblock, currentblock,td, blockheight.get(previousblock),blockdepth.get(previousblock));
								}  else {
									insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));
								}
							} else {
								if (maxwidth1 > maxwidth){
									insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock),blockdepth.get(previousblock));
								} else {									  
									insert(tid,previousblock, currentblock,maxwidth-maxwidth1, blockheight.get(previousblock),blockdepth.get(previousblock));
								}
							}
							break ;
						case 22 :
						case 23 :
						case 24 :

							symbolpaint.setTextSize(Integer.parseInt(subblockattribute.get(subparentblock.get(currentsubscript)).get(1).substring(1,4)));
							symbolpaint.getTextBounds(Symbol.symbolunicode.get("int"),0,Symbol.symbolunicode.get("int").length(),symbolbounds);
							twidth = symbolbounds.width()/3;
	  						   
							tempy=(blockheight.get(currentblock)-blockdepth.get(currentblock))/2;
							index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+tempy);
							}
		                    	   
							blockheight.set(currentblock, subblockheight.get(subparentblock.get(currentsubscript)).get(index)+blockdepth.get(currentblock)+tempy);
							blockdepth.set(currentblock, subblockdepth.get(subparentblock.get(currentsubscript)).get(index)+blockdepth.get(currentblock)+tempy);	
							closeblock.set(currentblock,subblocknumber.get(tid));
							thisblocklevel--;
							previousblock=currentblock;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;
							}				                    	
							if (!aftersuperscript.get(currentsubscript)){ 
								tempy=Math.max(blockwidth.get(previousblock)-twidth, 0);
								insert(tid,previousblock, currentblock,tempy, blockheight.get(previousblock),blockdepth.get(previousblock));				                  
							} else {
								tempy=Math.max(blockwidth.get(previousblock)-twidth,blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript))))-blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));
								insert(tid,previousblock, currentblock,tempy, blockheight.get(previousblock),blockdepth.get(previousblock));				    
							}
							index2=+currentblock;
							ypos=subblockypos.get(index2).get(0);
							xpos=subblockxpos.get(index2).get(0)+blockwidth.get(currentblock);
							break ;
						case 15 :
							for (i=1;i<=subblock.get(index2).size()-1;i++){
								subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)
										+subblockdepth.get(subparentblock.get(currentsubscript)).get(subblock.get(subparentblock.get(currentsubscript)).size()-1)
										+blockheight.get(currentblock)-blockdepth.get(currentblock)+gap);
							}
							index=subblock.get(subparentblock.get(currentsubscript)).size()-1;
							width1=subblockwidth.get(subparentblock.get(currentsubscript)).get(index);
							width2=blockwidth.get(currentblock);
							maxwidth=Math.max(width1,width2);
							if (width1 > width2){
								float td=(maxwidth-width2)/2;
								for (i=1;i<=subblock.get(index2).size()-1;i++){
									subblockxpos.get(index2).set(i, subblockxpos.get(index2).get(i)+td);
								}
								ypos=subblockypos.get(subparentblock.get(currentsubscript)).get(0);
								xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+subblockwidth.get(subparentblock.get(currentsubscript)).get(index);
							} else {
								float td=(maxwidth-width1)/2;		
								subblockxpos.get(subparentblock.get(currentsubscript)).set(index, subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+td);
								ypos=subblockypos.get(subparentblock.get(currentsubscript)).get(0);
								xpos=subblockxpos.get(subparentblock.get(currentsubscript)).get(index)+width1+td;
							}
				                 
							blockdepth.set(currentblock, subblockdepth.get(subparentblock.get(currentsubscript)).get(index)+blockheight.get(currentblock));
							blockheight.set(currentblock, subblockheight.get(subparentblock.get(currentsubscript)).get(index)+blockheight.get(currentblock)+gap);
					             
							closeblock.set(currentblock,subblocknumber.get(tid));
							previousblock=currentblock;thisblocklevel--;
							for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
								currentblock--;		
							}		

							if (subblockwidth.get(subparentblock.get(currentsubscript)).get(index)<blockwidth.get(previousblock)){
								float td=(maxwidth-subblockwidth.get(subparentblock.get(currentsubscript)).get(index))/2;
								insert(tid,previousblock, currentblock,td, blockheight.get(previousblock),blockdepth.get(previousblock));
							}
							else {
								insert(tid,previousblock, currentblock,0.0f, blockheight.get(previousblock), blockdepth.get(previousblock));
							}			                  			                  
							break ;		                     	  
						} 
					}else {
						tempy=(blockheight.get(currentblock)-blockdepth.get(currentblock))/2;
						index=subblock.get(subparentblock.get(currentsubscript)).size()-1;	                    	 
						for (i=1;i<=subblock.get(index2).size()-1;i++){
							subblockypos.get(index2).set(i,subblockypos.get(index2).get(i)+tempy);
						}
						tempy=Math.max(subblockdepth.get(subparentblock.get(currentsubscript)).get(index),(blockdepth.get(currentblock)+ blockheight.get(currentblock))/2);	 
						maxtop=subblockheight.get(subparentblock.get(currentsubscript)).get(index)-subblockdepth.get(subparentblock.get(currentsubscript)).get(index);
						blockdepth.set(currentblock, tempy);	
						blockheight.set(currentblock,maxtop+blockdepth.get(currentblock));

						closeblock.set(currentblock,subblocknumber.get(tid));
						thisblocklevel-=2;
						previousblock=currentblock;
						for (i=subblocknumber.get(tid);currentblock >=0 && closeblock.get(currentblock)>=0;i--){
							currentblock--;
						}				                    	  
						if (!aftersuperscript.get(currentsubscript)){ 								  
							insert(tid,previousblock, currentblock,blockwidth.get(previousblock), blockheight.get(previousblock), blockdepth.get(previousblock));				                  				                  
						} else {
							tempy=Math.max(blockwidth.get(previousblock),blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript))))-blockwidth.get(homeblock.get(opensuperscript.get(previoussuperscript)));
							insert(tid,previousblock, currentblock,tempy, blockheight.get(previousblock),blockdepth.get(previousblock));				    
						}
						index2=+currentblock;
						ypos=subblockypos.get(index2).get(0);
						xpos=subblockxpos.get(index2).get(0)+blockwidth.get(currentblock);
					}
					thisfractionlevel = blockfractionlevel.get(currentblock);
					thisenclosurelevel = blockenclosurelevel.get(currentblock);
	                  
					previoussubscript=currentsubscript;thissubscriptlevel--;
					for (i=subblocknumber.get(tid);currentsubscript >= 0 && closesubscript.get(currentsubscript)>=0;i--){
						currentsubscript--;
					}

					if (thissubscriptlevel >= 0 || thissuperscriptlevel >= 0){
						thisfontsize=fontsize/3;
					}else if (thisfractionlevel<=2){
						thisfontsize=(int)((double)fontsize*fractionfontfactor[thisfractionlevel]);
					}else {
						thisfontsize=(int)((double)fontsize*fractionfontfactor[2]); 
					};
					if (thisfontsize<8){thisfontsize=8;};	
					j+=5;
					temp = molecule.charAt(j);
					parentkey="csu";parentblock=previousblock;
                      
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
							key = key + molecule.charAt(ii);
						}}
						
				} else if (temp == charExclam && key.equals("hsp")){                                                   // hspace
		              
					j+=5;
					key=molecule.substring(j,molecule.indexOf("}",j));j=j+key.length()+1;
					twidth=Float.parseFloat(key); 
					subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stringdnot,twidth,0.0f,0.0f,xpos,ypos,thisattribute);
					homeblock.add(currentblock);
					xpos=xpos+twidth;
			    		  
					temp = molecule.charAt(j);
					if (temp == charExclam){
						key = "";
						for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
							key = key + molecule.charAt(ii);
						}}
						
				}else if (temp == charExclam && key.equals("vsp")){                                                   // vspace

					synchronized(this){
						Block.error.put(tid, true);
						Block.errormessage.put(tid, "vspace inserted in wrong place, parse failed!");}
					return;					
					
				}  else  {                                                                    
								
					for (i = 0 ;   (temp != charExclam) || (temp == charExclam && Symbol.symboltype.containsKey(key) 
							&& Symbol.symboltype.get(key) >= 10 ) ; i++) {

					if (temp != charExclam) {                                                                           // italic text								                   
						sfontsize=Integer.toString(thisfontsize);
						ij=sfontsize.length();
						if (ij==1){
							thisattribute=thisattribute.substring(0,1)+"00"+sfontsize+thisattribute.substring(4);
						} else if (ij==2){
							thisattribute=thisattribute.substring(0,1)+"0"+sfontsize+thisattribute.substring(4);
						} else if (ij==3){
							thisattribute=thisattribute.substring(0,1)+sfontsize+thisattribute.substring(4);
						}			
						textpaint.setTextSize(thisfontsize);
						textpaint.setTypeface(tf.get(Integer.parseInt(thisattribute.substring(4,7))));
							    	
						ii=molecule.indexOf('!',j);
						String stemp=molecule.substring(j,ii);
						textpaint.getTextBounds(stemp,0,stemp.length(),textbounds);				
						subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stemp,textpaint.measureText(stemp),(float)textbounds.height(),(float)textbounds.bottom, xpos,ypos,thisattribute);
						homeblock.add(currentblock);
						xpos=xpos+textpaint.measureText(stemp);
						parentkey=stemp.substring(stemp.length()-1); parentblock=currentblock;
						j=ii;
						temp = molecule.charAt(j);
						if (temp == charExclam){
							key = "";
							for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
								key = key + molecule.charAt(ii);
							}}							
							 
					} else if (temp == charExclam){                                                                                       // symbol
			    	
						if (Symbol.symboltype.get(key)==20 || Symbol.symboltype.get(key)==23){
							sfontsize=Integer.toString((int) ((float)thisfontsize*Header.bigopsize));
							symbolpaint.setTextSize((int)(float)thisfontsize*Header.bigopsize);
						} else if (Symbol.symboltype.get(key)==21 || Symbol.symboltype.get(key)==24){
							sfontsize=Integer.toString((int) ((float)thisfontsize*Header.bigbigopsize));
							symbolpaint.setTextSize((int)(float)thisfontsize*Header.bigbigopsize);
						} else {
							sfontsize=Integer.toString(thisfontsize);	
							symbolpaint.setTextSize(thisfontsize);
						}							    
							textpaint.setTextSize(thisfontsize);
							textpaint.setTypeface(tf.get(fontinteger));
							String stemp="a";
							textpaint.getTextBounds(stemp,0,stemp.length(),textbounds);
							Float sizeofa=(float) textbounds.height();								  
							
							if (Symbol.symboltype.get(key)==15 || Symbol.symboltype.get(key)==14) {
								ij=sfontsize.length();
								if (ij==1){
									attribute2=thisattribute.substring(0,1)+"00"+sfontsize+"005"+thisattribute.substring(7);
								} else if (ij==2){
									attribute2=thisattribute.substring(0,1)+"0"+sfontsize+"005"+thisattribute.substring(7);
									} else if (ij==3){
										attribute2=thisattribute.substring(0,1)+sfontsize+"005"+thisattribute.substring(7);
									}				
							  
								textpaint5.setTextSize(thisfontsize);
								textpaint5.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),textbounds5);
								twidth = textpaint5.measureText(Symbol.symbolunicode.get(key));
								theight = textbounds5.height();
								tdepth = textbounds5.bottom;
							}else {
								ij=sfontsize.length();
								if (ij==1){
									attribute2=thisattribute.substring(0,1)+"00"+sfontsize+"004"+thisattribute.substring(7);
								} else if (ij==2){
									attribute2=thisattribute.substring(0,1)+"0"+sfontsize+"004"+thisattribute.substring(7);
								} else if (ij==3){
									attribute2=thisattribute.substring(0,1)+sfontsize+"004"+thisattribute.substring(7);
								}				
								symbolpaint.getTextBounds(Symbol.symbolunicode.get(key),0,Symbol.symbolunicode.get(key).length(),symbolbounds);
								twidth = symbolpaint.measureText(Symbol.symbolunicode.get(key));
								theight = symbolbounds.height();
								tdepth = symbolbounds.bottom;
							}
							parentkey=key; parentblock=currentblock;
						  
							theight=Math.max(theight, sizeofa);
							ii=j+key.length()+1;
							stemp=molecule.substring(j,ii).trim()+" ";
							subblocknumber.put(tid, subblocknumber.get(tid)+1); add(tid,currentblock,stemp,twidth,theight,tdepth,xpos,ypos,attribute2);
							homeblock.add(currentblock);					      

							xpos=xpos+twidth;
				      
							j=j+key.length()+1;
							temp = molecule.charAt(j);
							if (temp == charExclam){
								key = "";
								for (ii=j+1;!(molecule.charAt(ii)==' ' ||molecule.charAt(ii)=='}' || molecule.charAt(ii)=='{'|| molecule.charAt(ii)=='!');ii++){
									key = key + molecule.charAt(ii);
								}}		
								if(molecule.charAt(ii)==' ' && molecule.charAt(ii+1)!='!'){j=j+1;}                  
					};   
					};					                  			 
				}
		}
		synchronized(this){
			block.result(tid, blocknumber, subblock, subblockwidth, subblockheight, subblockdepth, subblockxpos, subblockypos, subblockattribute, blockwidth, blockheight, blockdepth);}
	}
	
		public void add(int tid, int blocknumber, String block,  
			Float width, Float height, Float depth, Float xpos, Float ypos, String attribute) {
        
			int index=blocknumber;
			subblock.get(index).add(block);
			subblockwidth.get(index).add(width);
			subblockheight.get(index).add(height);
			subblockdepth.get(index).add(depth);
			subblockxpos.get(index).add(xpos);
			subblockypos.get(index).add(ypos);
			subblockattribute.get(index).add(attribute);
        
			blockwidth.set(blocknumber, blockwidth.get(blocknumber)+width);
			float maxtop=Math.max(blockheight.get(blocknumber)-blockdepth.get(blocknumber), height-depth);
			blockdepth.set(blocknumber, Math.max(blockdepth.get(blocknumber),depth)); 
			blockheight.set(blocknumber,maxtop+blockdepth.get(blocknumber));
			return;
		}

		public void create(int tid, int blocknumber, int thisblocklevel, int thisfractionlevel, int thisenclosurelevel, int thissuperscriptlevel, int thissubscriptlevel, int thistabularlevel) {		
			
			int index=blocknumber;
			subblock.add(index,new ArrayList<String>());
			subblockwidth.add(index,new ArrayList<Float>());
			subblockheight.add(index,new ArrayList<Float>());
			subblockdepth.add(index,new ArrayList<Float>());
			subblockxpos.add(index,new ArrayList<Float>());
			subblockypos.add(index,new ArrayList<Float>());
			subblockattribute.add(index,new ArrayList<String>());

			blocklevel.add(thisblocklevel);     
			blockfractionlevel.add(thisfractionlevel);
			blockenclosurelevel.add(thisenclosurelevel);
			blocksuperscriptlevel.add(thissuperscriptlevel);
			blocksubscriptlevel.add(thissubscriptlevel);
			blocktabularlevel.add(thistabularlevel);
        
			blockwidth.add(0.0f);
			blockheight.add(0.0f);
			blockdepth.add(0.0f); 

			return;
			}
		
		public void insert(int tid, int blocknumber1, int blocknumber2 , Float width, Float height, Float depth) {

			int index1=blocknumber1;
			int index2=blocknumber2;
			int l=subblock.get(index1).size();
			for (int i=0;i<=l-1;i++){ 
				subblock.get(index2).add(subblock.get(index1).get(i));
				subblockwidth.get(index2).add(subblockwidth.get(index1).get(i));
				subblockheight.get(index2).add(subblockheight.get(index1).get(i));
				subblockdepth.get(index2).add(subblockdepth.get(index1).get(i));
				subblockxpos.get(index2).add(subblockxpos.get(index1).get(i));
				subblockypos.get(index2).add(subblockypos.get(index1).get(i));
				subblockattribute.get(index2).add(subblockattribute.get(index1).get(i));
			}
			
			float maxtop=Math.max(blockheight.get(blocknumber2)-blockdepth.get(blocknumber2), height-depth);		                  
			blockdepth.set(blocknumber2, Math.max(blockdepth.get(blocknumber2),depth));
			blockheight.set(blocknumber2, maxtop+blockdepth.get(blocknumber2));
			blockwidth.set(blocknumber2, blockwidth.get(blocknumber2)+width);
			return;
		}
	
		public void adjustfraction(int tid, int blocknumber, int maxblocknumber, ArrayList<Integer> blocklist, ArrayList<Integer> openblock,ArrayList<Integer> closeblock,int thisfractionlevel, int thisblocklevel, int thisenclosurelevel, int thissuperscriptlevel, int thissubscriptlevel, Float off, Float linewidth) {
		
			ArrayList<Float> liney= new ArrayList<Float>();
			ArrayList<Integer> line = new ArrayList<Integer>();
			int numfrac=0;

			int index2=blocknumber;
			int index = openblock.get(blocknumber);
			for (int i=index;i<=closeblock.get(blocknumber);i++){
				if(blockenclosurelevel.get(blocklist.get(i)) == thisenclosurelevel &&
						blocksuperscriptlevel.get(blocklist.get(i)) == thissuperscriptlevel &&
						blocksubscriptlevel.get(blocklist.get(i)) == thissubscriptlevel &&
						blockfractionlevel.get(blocklist.get(i))==thisfractionlevel+1 &&
						subblock.get(index2).get(i-index).equals("!hlin ")){
					numfrac++;
					liney.add(subblockypos.get(index2).get(i-index));
					line.add(i-index); 	 
				}
			}
 
			ArrayList<Integer> adjustedblock = new ArrayList<Integer>();
			ArrayList<Integer> adjustedfrac = new ArrayList<Integer>();
			int numblock=0;
			for (int i=0;i<=numfrac-1;i++){
				adjustedblock.add(blocklist.get(line.get(i)+index)-1);
				adjustedfrac.add(i);
				numblock++;
			}
        
			float minliney=10000;
			for (int i=0;i<=numfrac-1;i++){
				minliney=Math.min(minliney, liney.get(i));
			}
     
			Float maxtop1=0.0f;
			Float maxbottom1=0.0f;
			int i=0;
			Float top1=0.0f;
        		Float bottom1 =0.0f;
        		for (i=0;i<numblock;i++){
        			float diff = liney.get(adjustedfrac.get(i))-minliney;
        			bottom1=blockdepth.get(adjustedblock.get(i))-diff;
        			top1=blockheight.get(adjustedblock.get(i))-bottom1;
        			maxtop1=Math.max(maxtop1, top1);
        			maxbottom1=Math.max(maxbottom1, bottom1);
        			blockfractionlevel.set(adjustedfrac.get(i), 0);
        		}
 
        		int lengthofblock=closeblock.get(blocknumber)-openblock.get(blocknumber);
        		ArrayList<Boolean> adjusted = new ArrayList<Boolean>();
        		for (i=0;i<=lengthofblock;i++){
        			adjusted.add(false);
        		}
        	
        		for (i=0;i<numblock;i++){
        			float diff = liney.get(adjustedfrac.get(i))-minliney;
        			for (int ii=openblock.get(adjustedblock.get(i));ii<=closeblock.get(adjustedblock.get(i));ii++){
        				index=ii-openblock.get(blocknumber);
        				subblockypos.get(index2).set(index,subblockypos.get(index2).get(index)-diff);
        				adjusted.set(index, true);
        			}
        		}
        		Float diff=subblockypos.get(index2).get(0)-minliney-off;
        		Float maxtop2=0.0f;
        		Float maxbottom2=0.0f;
        		for (i=1;i<=lengthofblock;i++){
        			Float top2=0.0f;
        			Float bottom2 = 0.0f;
        			if(!adjusted.get(i)){       		
        				subblockypos.get(index2).set(i, subblockypos.get(index2).get(i)-diff);
        				bottom2=subblockdepth.get(index2).get(i)-diff;
        				top2=subblockheight.get(index2).get(i)-bottom2;
        				maxtop2=Math.max(maxtop2, top2);
        				maxbottom2=Math.max(maxbottom2, bottom2);
        			}
        		}
        		Float maxtop=Math.max(maxtop1, maxtop2);
        		Float maxbottom=Math.max(maxbottom1, maxbottom2);
        		blockheight.set(blocknumber, maxtop+maxbottom);
        		blockdepth.set(blocknumber, maxbottom);

        		maxtop1=0.0f;maxbottom1=0.0f;maxtop2=0.0f;maxbottom2=0.0f;maxtop=0.0f;maxbottom=0.0f;
        		liney.clear();line.clear();
        		return;
			}
	}