package jsyntaxpane;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.text.Segment;
import javax.swing.text.TabExpander;
import javax.swing.text.Utilities;
import javax.swing.text.View;
/**
*
* @author JPEXS
*/
public class UniTools {
private static List<String> backupFonts =new ArrayList<String>();
private static boolean fontExists(String name){
GraphicsEnvironment g=GraphicsEnvironment.getLocalGraphicsEnvironment();
List<String> availFonts=Arrays.asList(g.getAvailableFontFamilyNames());
for(int i=0;i<availFonts.size();i++){
availFonts.set(i, availFonts.get(i).toLowerCase());
}
return availFonts.contains(name.toLowerCase());
}
private static String backupCandidates[] = new String[]{"Unifont","Arial Unicode MS"};
private static Font defaultUniFont=null;
static {
for(String bc:backupCandidates){
if(fontExists(bc)){
defaultUniFont = new Font(bc,Font.PLAIN,10);
}
}
if(defaultUniFont==null){
defaultUniFont = new JLabel().getFont();
}
}
public static int getTabbedTextOffset(Segment segment, FontMetrics metrics, int tabBase,int x,TabExpander e, int startOffset){
List<Segment> segments=new ArrayList<Segment>();
List<Boolean> unis=new ArrayList<Boolean>();
Font origFont=metrics.getFont();
getSegments(origFont, segment, segments, unis);
Graphics g=new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getGraphics();
Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D());
int ofs=0;
int totalto = 0;
for(int i=0;i<segments.size();i++){
Segment seg=segments.get(i);
FontMetrics fm=unis.get(i)?g.getFontMetrics(uniFont):metrics;
int to = Utilities.getTabbedTextOffset(seg, fm, tabBase+ofs,x, e, startOffset);
totalto += to;
ofs+=fm.stringWidth(seg.toString());
if(to<seg.length()){
break;
}
}
return totalto;
}
private static void getSegments(Font f,Segment segment,List<Segment> segments,List<Boolean> unis){
int start=0;
int len=0;
boolean uni=false;
for(int i=0;i<segment.length();i++){
boolean newuni=false;
if(!f.canDisplay(segment.charAt(i))){
newuni=true;
}
if(i>0 && uni!=newuni){
Segment s =new Segment(segment.array, segment.offset+start, len);
segments.add(s);
unis.add(uni);
start = i;
len=0;
}
uni=newuni;
len++;
}
if(len>0){
Segment s =new Segment(segment.array, segment.offset+start, len);
segments.add(s);
unis.add(uni);
}
}
public static int getTabbedTextWidth(Segment segment,FontMetrics f,int x,TabExpander e, int startOffset){
Graphics g=new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getGraphics();
g.setFont(f.getFont());
return getTabbedTextWidth(g,segment,x,e,startOffset);
}
public static int getTabbedTextWidth(Graphics g,Segment segment,int x,TabExpander e, int startOffset){
List<Segment> segments=new ArrayList<Segment>();
List<Boolean> unis=new ArrayList<Boolean>();
getSegments(g.getFont(), segment, segments, unis);
Font origFont=g.getFont();
Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D());
int ret=0;
int pos=0;
for(int i=0;i<segments.size();i++){
Segment seg=segments.get(i);
ret += Utilities.getTabbedTextWidth(seg, g.getFontMetrics(unis.get(i)?uniFont:origFont), 0, e, startOffset+pos);
pos += seg.length();
}
return ret;
}
public static int drawTabbedText(Segment segment, int x, int y, Graphics g, TabExpander e, int startOffset){
List<Segment> segments=new ArrayList<Segment>();
List<Boolean> unis=new ArrayList<Boolean>();
getSegments(g.getFont(), segment, segments, unis);
Font origFont=g.getFont();
Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D());
int ret=x;
int pos=0;
for(int i=0;i<segments.size();i++){
Segment seg=segments.get(i);
if(unis.get(i)){
g.setFont(uniFont);
}else{
g.setFont(origFont);
}
ret = Utilities.drawTabbedText(seg, ret, y, g, e, startOffset+pos);
pos += seg.length();
}
g.setFont(origFont);
return ret;
}
public static int stringWidth(Graphics g,String string){
List<Segment> segments=new ArrayList<Segment>();
List<Boolean> unis=new ArrayList<Boolean>();
Segment segment=new Segment(string.toCharArray(), 0, string.length());
getSegments(g.getFont(), segment, segments, unis);
Font origFont=g.getFont();
Font uniFont = defaultUniFont.deriveFont(origFont.getStyle(),origFont.getSize2D());
int ret=0;
for(int i=0;i<segments.size();i++){
Segment seg=segments.get(i);
ret+=g.getFontMetrics(unis.get(i)?uniFont:origFont).stringWidth(seg.toString());
}
return ret;
}
}