mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-17 18:58:07 +00:00
Issue #504 JSyntaxPane using backup fonts for characters not found in standard font (e.g. Japanese/Chinese characters)
This commit is contained in:
Binary file not shown.
@@ -19,7 +19,6 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.text.Segment;
|
||||
import javax.swing.text.TabExpander;
|
||||
import javax.swing.text.Utilities;
|
||||
|
||||
/**
|
||||
* This class represents the Style for a TokenType. This class is responsible
|
||||
@@ -110,14 +109,15 @@ public final class SyntaxStyle {
|
||||
* expanded as a space character.
|
||||
* @param startOffset - starting offset of the text in the document >= 0
|
||||
* @return
|
||||
*/
|
||||
public int drawText(Segment segment, int x, int y,
|
||||
*/
|
||||
public int drawText(Segment segment, int x, int y,
|
||||
Graphics graphics, TabExpander e, int startOffset) {
|
||||
graphics.setFont(graphics.getFont().deriveFont(getFontStyle()));
|
||||
FontMetrics fontMetrics = graphics.getFontMetrics();
|
||||
int a = fontMetrics.getAscent();
|
||||
int h = a + fontMetrics.getDescent();
|
||||
int w = Utilities.getTabbedTextWidth(segment, fontMetrics, 0, e, startOffset);
|
||||
//JPEXS: UniTools for multi fonts
|
||||
int w = UniTools.getTabbedTextWidth(graphics,segment,0, e, startOffset);
|
||||
int rX = x - 1;
|
||||
int rY = y - a;
|
||||
int rW = w + 2;
|
||||
@@ -127,7 +127,8 @@ public final class SyntaxStyle {
|
||||
graphics.fillRect(rX, rY, rW, rH);
|
||||
}
|
||||
graphics.setColor(getColor());
|
||||
x = Utilities.drawTabbedText(segment, x, y, graphics, e, startOffset);
|
||||
//JPEXS: UniTools for multi fonts
|
||||
x = UniTools.drawTabbedText(segment, x, y, graphics, e, startOffset);
|
||||
if ((getFontStyle() & 0x8) != 0) {
|
||||
graphics.setColor(Color.RED);
|
||||
graphics.drawRect(rX, rY, rW, rH);
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Toolkit;
|
||||
@@ -25,8 +26,10 @@ import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.Element;
|
||||
import javax.swing.text.PlainView;
|
||||
import javax.swing.text.Position;
|
||||
import javax.swing.text.Segment;
|
||||
import javax.swing.text.ViewFactory;
|
||||
import jsyntaxpane.util.Configuration;
|
||||
@@ -170,4 +173,98 @@ public class SyntaxView extends PlainView {
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//JPEXS: PlainView adaptation for multi fonts (UniTools)
|
||||
@Override
|
||||
public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
|
||||
// line coordinates
|
||||
Document doc = getDocument();
|
||||
Element map = getElement();
|
||||
int lineIndex = map.getElementIndex(pos);
|
||||
if (lineIndex < 0) {
|
||||
return lineToRect(a, 0);
|
||||
}
|
||||
Rectangle lineArea = lineToRect(a, lineIndex);
|
||||
|
||||
// determine span from the start of the line
|
||||
int tabBase = lineArea.x;
|
||||
Element line = map.getElement(lineIndex);
|
||||
int p0 = line.getStartOffset();
|
||||
Segment s = new Segment();
|
||||
doc.getText(p0, pos - p0, s);
|
||||
int xOffs = UniTools.getTabbedTextWidth(s, metrics, tabBase, this,p0);
|
||||
|
||||
// fill in the results and return
|
||||
lineArea.x += xOffs;
|
||||
lineArea.width = 1;
|
||||
lineArea.height = metrics.getHeight();
|
||||
return lineArea;
|
||||
}
|
||||
|
||||
//JPEXS: PlainView adaptation for multi fonts (UniTools)
|
||||
@Override
|
||||
public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
|
||||
// PENDING(prinz) properly calculate bias
|
||||
bias[0] = Position.Bias.Forward;
|
||||
|
||||
Rectangle alloc = a.getBounds();
|
||||
Document doc = getDocument();
|
||||
int x = (int) fx;
|
||||
int y = (int) fy;
|
||||
if (y < alloc.y) {
|
||||
// above the area covered by this icon, so the the position
|
||||
// is assumed to be the start of the coverage for this view.
|
||||
return getStartOffset();
|
||||
} else if (y > alloc.y + alloc.height) {
|
||||
// below the area covered by this icon, so the the position
|
||||
// is assumed to be the end of the coverage for this view.
|
||||
return getEndOffset() - 1;
|
||||
} else {
|
||||
// positioned within the coverage of this view vertically,
|
||||
// so we figure out which line the point corresponds to.
|
||||
// if the line is greater than the number of lines contained, then
|
||||
// simply use the last line as it represents the last possible place
|
||||
// we can position to.
|
||||
|
||||
Element map = doc.getDefaultRootElement();
|
||||
int fontHeight = metrics.getHeight();
|
||||
int lineIndex = (fontHeight > 0 ?
|
||||
Math.abs((y - alloc.y) / fontHeight) :
|
||||
map.getElementCount() - 1);
|
||||
if (lineIndex >= map.getElementCount()) {
|
||||
return getEndOffset() - 1;
|
||||
}
|
||||
Element line = map.getElement(lineIndex);
|
||||
int dx = 0;
|
||||
if (lineIndex == 0) {
|
||||
//alloc.x += firstLineOffset;
|
||||
// alloc.width -= firstLineOffset;
|
||||
}
|
||||
if (x < alloc.x) {
|
||||
// point is to the left of the line
|
||||
return line.getStartOffset();
|
||||
} else if (x > alloc.x + alloc.width) {
|
||||
// point is to the right of the line
|
||||
return line.getEndOffset() - 1;
|
||||
} else {
|
||||
// Determine the offset into the text
|
||||
try {
|
||||
int p0 = line.getStartOffset();
|
||||
int p1 = line.getEndOffset() - 1;
|
||||
Segment s = new Segment();
|
||||
doc.getText(p0, p1 - p0, s);
|
||||
int tabBase = alloc.x;
|
||||
int offs = p0 + UniTools.getTabbedTextOffset(s, metrics,
|
||||
tabBase, x, this, p0);
|
||||
//SegmentCache.releaseSharedSegment(s);
|
||||
return offs;
|
||||
} catch (BadLocationException e) {
|
||||
// should not happen
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
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 ret=0;
|
||||
int pos=0;
|
||||
for(int i=0;i<segments.size();i++){
|
||||
Segment seg=segments.get(i);
|
||||
ret += Utilities.getTabbedTextOffset(seg, g.getFontMetrics(unis.get(i)?uniFont:origFont), tabBase,x, e, startOffset+pos);
|
||||
pos += seg.length();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import javax.swing.ImageIcon;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import jsyntaxpane.SyntaxView;
|
||||
import jsyntaxpane.UniTools;
|
||||
import jsyntaxpane.actions.ActionUtils;
|
||||
import jsyntaxpane.util.ReflectUtils;
|
||||
|
||||
@@ -76,7 +77,8 @@ abstract class MemberCell extends JPanel {
|
||||
g.setFont(list.getFont());
|
||||
x = drawString(getArguments(), x, y, g);
|
||||
String right = getReturnType();
|
||||
int rw = fm.stringWidth(right);
|
||||
//JPEXS: UniTools for multi fonts
|
||||
int rw = UniTools.stringWidth(g, right);
|
||||
g.drawString(right, getWidth() - rw - 4, fm.getAscent());
|
||||
}
|
||||
|
||||
@@ -87,14 +89,16 @@ abstract class MemberCell extends JPanel {
|
||||
FontMetrics fm = g.getFontMetrics(font);
|
||||
// total text for this component:
|
||||
String total = getMemberName() + getArguments() + getReturnType() + " ";
|
||||
return new Dimension(fm.stringWidth(total) + 20, Math.max(fm.getHeight(), 16));
|
||||
//JPEXS: UniTools for multi fonts
|
||||
return new Dimension(UniTools.stringWidth(g,total) + 20, Math.max(fm.getHeight(), 16));
|
||||
}
|
||||
|
||||
private int drawString(String string, int x, int y, Graphics g) {
|
||||
if(ActionUtils.isEmptyOrBlanks(string)) {
|
||||
return x;
|
||||
}
|
||||
int w = g.getFontMetrics().stringWidth(string);
|
||||
//JPEXS: UniTools for multi fonts
|
||||
int w = UniTools.stringWidth(g, string);
|
||||
g.drawString(string, x, y);
|
||||
return x + w;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user