vfont.java

来自「Hecl编程语言是一个高层次的脚本语言的Java实现。其用意是要小」· Java 代码 · 共 1,008 行 · 第 1/2 页

JAVA
1,008
字号
/* * Copyright (C) 2005, 2006 data2c GmbH (www.data2c.com) * * Author: Wolfgang S. Kechel - wolfgang.kechel@data2c.com * */package org.graphics;import java.io.EOFException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.IOException;import java.util.Hashtable;/* * Set internal define to make module widely independant of build environment *///#ifndef j2se//#define ISMIDLET//#endif//#ifndef ISMIDLET/* * Control usage of HERSHEY font stuff. Comment next line to disable * creation of vector font from hershey font. *///#define USEHERSHEYimport java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.PrintStream;import java.awt.Graphics;import java.awt.Point;import java.awt.Polygon;import java.awt.Rectangle;import java.net.URL;import java.util.Enumeration;//#ifdef USEHERSHEYimport org.hershey.HersheyFont;//#endif//#elseimport javax.microedition.lcdui.Graphics;import org.awt.Point;import org.awt.Rectangle;//#endifpublic class VFont {    public final static double ITALICS = 0.75;//#ifndef ISMIDLET    public final static int HCENTER = 1;    public final static int VCENTER = 2;    public final static int LEFT = 4;    public final static int RIGHT = 8;    public final static int TOP = 16;    public final static int BOTTOM = 32;    public final static int BASELINE = 64;    //public final static int CAP = 0x80;    protected static double dpi = 100;//#else    public final static int HCENTER = Graphics.HCENTER;    public final static int LEFT = Graphics.LEFT;    public final static int RIGHT = Graphics.RIGHT;    public final static int TOP = Graphics.TOP;    public final static int VCENTER = Graphics.VCENTER;    public final static int BOTTOM = Graphics.BOTTOM;    public final static int BASELINE = Graphics.BASELINE;    //public final static int CAP = 2;    protected static double dpi = 125;//#endif    // Target size of font in point (default: 12pt)    protected static double normsize = 12.0;    // Hold precalculated value to scale font to normsize    // accoring to display resolution in dpi.    protected static double scaling = (normsize * dpi) / 72.0;        public static int getDPI() {	return (int)dpi;    }        public static void setDPI(int dotsperinch) {	dpi = dotsperinch;	scaling = (normsize * dpi) / 72.0;    }        // Class to hold all parameters needed for drawing a string    public static class DrawParams {	public DrawParams() {	    this(BOTTOM|LEFT,1,1,0,0);	}		public DrawParams(int anchorspec,double w,double h,double rot,double italics) {	    anchor = anchorspec;	    width = w;	    height = h;	    theta = rot;	    slant = italics;	}		void setup(double fontheight) {	    scale = scaling / fontheight;	    xscale = width * scale;	    yscale = height * scale;	    if(theta != .0) {		double tmp = (double)(-Math.PI / 180.0 * theta);		costheta = (double)Math.cos(tmp);		sintheta = (double)Math.sin(tmp);	    } else {		costheta = 1.0;		sintheta = .0;	    }	    finalslant = slant * yscale;/*	    System.err.println("fh="+fontheight			       +", w="+width +" / xs="+xscale			       +", h="+height +" / ys="+yscale			       +", sl="+slant +" / fsl="+finalslant);*/	}			public int anchor;	public double width;	public double height;	public double theta;		    // rotation in degrees	public double slant;		    // slant as tan(slantangle)	double costheta = 1.0;	double sintheta = .0;	double finalslant = .0;	double scale;	double xscale;	double yscale;    }        public static class Glyph//#ifndef ISMIDLET    implements Cloneable//#endif    {	// A glyph describes a character.	// The coordinate system has (0,0) in the lower left corner increasing	// to the left (x) and upwards (y).	public Glyph(char ch,int cwidth,char[] strokes) {	    this(ch,cwidth,0,strokes);	}		public Glyph(char ch,int cwidth,int ml,char[] strokes) {	    this.ch = ch;	    this.cwidth = (short)cwidth;	    this.midline = (short)ml;	    this.strokes = strokes;	}	public int draw(int xp, int yp, int rotpx, int rotpy, DrawParams dp,			Rectangle r, Graphics g) {	    int npts = 0;	    Point[] pts = null;	    for(int i=0; i<strokes.length;) {		int what = (int)strokes[i++];		switch(what) {		  case 'v':		  case 'l':		    npts = 2;		    //System.out.println("ex v 2");		    pts = getPoints(npts,i,xp,yp,rotpx,rotpy,dp,r);		    line(pts[0].x,pts[0].y,pts[1].x,pts[1].y,g);		    i += 2 * npts;		    break;		  case 'V':		  case 'p':		  case 'P':		    npts = (int)strokes[i++];		    //System.out.println("ex p "+npts);		    pts = getPoints(npts,i, xp,yp,rotpx,rotpy,dp,r);		    switch(what) {		      case 'V':			lines(pts,g);			break;		      case 'p':			if(g != null)			    Draw.drawPolygon(g,npts,pts,false);			break;		      case 'P':			if(g != null)			    Draw.drawPolygon(g,npts,pts,true);			break;		    }		    i += 2 * npts;		    break;		  default:		    i = strokes.length;		    break;		}	    }	    return round(dp.xscale/*dp.width*/ * cwidth);	}	protected Point[] getPoints(int npts,int startat,				    int xp, int yp, int rotpx, int rotpy,				    DrawParams dp, Rectangle r) {	    int x;	    int y;	    Point[] p = new Point[npts];	    for(int i=0; i<npts; ++i, startat += 2) {		x = xform(xp, strokes[startat], dp.xscale);		if(0.0 != dp.finalslant) {		    //System.out.println("y="+(int)strokes[startat+1] +"corr="+(strokes[startat+1]*finalslant));		    // add italics offset to the "normal" point transformation		    x += strokes[startat+1]*dp.finalslant;		}		// calculate the y coordinate		y = xform(yp, -strokes[startat+1], dp.yscale);				if(dp.theta != .0) {		    // apply the rotation matrix ...		    // transform the coordinate to the rotation center point		    double xd = x - rotpx;		    double yd = y - rotpy;		    		    // rotate		    double xd2 = xd * dp.costheta - yd * dp.sintheta;		    double yd2 = xd * dp.sintheta + yd * dp.costheta;		    		    // transform back		    x = round(xd2) + rotpx;		    y = round(yd2) + rotpy;		}		if(r != null) {		    if(x < r.x) {			r.x = x;		    }		    if(y < r.y) {			r.y = y;		    }		    if(x > r.width) {			r.width = x;		    }		    if(y > r.height) {			r.height = y;		    }		}		p[i] = new Point(x,y);	    }	    return p;	}		protected void lines(Point[] points,Graphics g) {	    if(points == null || g == null)		return;	    for(int i=0; i<points.length-1; ++i) {		line(points[i].x,points[i].y,points[i+1].x,points[i+1].y,g);	    }	}			protected void line(int x1, int y1, int x2, int y2, Graphics g) {	    if(g == null)		return;	    //#ifdef notdef	    if(width > 1) {//#ifndef ISMIDLET		// if the width is greater than one		Polygon filledPolygon = new Polygon();				int offset = width / 2;				// this does not generate a true "wide line" but it seems to		// look OK for font lines		filledPolygon.addPoint(x1 - offset, y1 + offset);		filledPolygon.addPoint(x1 + offset, y1 - offset);		filledPolygon.addPoint(x2 + offset, y2 - offset);		filledPolygon.addPoint(x2 - offset, y2 + offset);		// draw a polygon		g.fillPolygon(filledPolygon);//#else		System.out.println("NO THICK LINES!!!");//#endif	    }//#endif	    // draw a line//#ifdef ISMIDLET	    int oldstroke = g.getStrokeStyle();	    g.setStrokeStyle(Graphics.SOLID);//#endif	    g.drawLine(x1, y1, x2, y2);//#ifdef ISMIDLET	    g.setStrokeStyle(oldstroke);//#endif	}    //#ifndef ISMIDLET	public Glyph(Glyph g) {	    this(g.ch,g.cwidth,g.midline,copyStrokes(g.strokes));	}		public Object clone() {	    return new Glyph(this);	}		public char[] getStrokes() {	    return strokes;	}	public void setStrokes(char[] newstrokes) {	    strokes = newstrokes;	}		public PrintStream storeOn(PrintStream s) {	    s.print("# "+Integer.toString(ch) + " w " + cwidth);	    if(midline != 0 && midline != cwidth/2)		s.print(" m "+midline);	    if(strokes != null) {		for(int i=0; i<strokes.length; ) {		    char ch = strokes[i++];		    s.print(' ');		    s.print(ch);		    switch(ch) {		      case 'v':		      case 'l':			s.print(" "+((int)strokes[i++]));			s.print(" "+((int)strokes[i++]));			s.print(" "+((int)strokes[i++]));			s.print(" "+((int)strokes[i++]));			break;		      case 'V':		      case 'p':		      case 'P':			int n = (int)strokes[i++];			s.print(" " + String.valueOf(n));			while(n-- > 0) {			    s.print(" "+((int)strokes[i++]));			    s.print(" "+((int)strokes[i++]));			}			break;		      default:			i = strokes.length;			break;		    }		}	    }	    s.print(";");	    return s;	}	public int getMidLine() {	    return midline;	}		public void setWidth(int val) {	    if(val >= 0)		cwidth = (short)val;	}    	public void setMidLine(int val) {	    if(val >= 0)		midline = (short)val;	}	private static char[] copyStrokes(char[] strokes) {	    char[] newstrokes = new char[strokes.length];	    System.arraycopy(strokes,0,newstrokes,0,strokes.length);	    return newstrokes;	}//#endif	public int getWidth() {	    return cwidth;	}    	static protected final int xform(int offset, int val, double mag) {	    return round(offset + val * mag);	}		char ch;	short cwidth;	short midline = 0;	char[] strokes = null;    }    public VFont(String name,String resourcename) throws IOException {	this(name,	     new InputStreamReader(		 checkis(resourcename.getClass().getResourceAsStream(resourcename),			 resourcename)));    }    public VFont(String name,InputStreamReader is) throws IOException {	fontname = name;		// read format	int format = getc(is);	int unused = getc(is);	int ch;		while((ch = getc(is)) != '{' && ch != -1)	    ;	if(ch == -1)	    // error: premature eof	    throw new EOFException("Premature EOF in font file.");	if(format != 'A' || unused != 'X')	    // error: unknown format	    throw new IOException("Font file format error.");	while((ch = getc(is)) != '#' && ch != -1) {	    switch (ch) {	      case 'n':		// ignore		readInt(is);		//h.numchars = readInt(is);		/* note that number of characters is one more than max characters */		break;	      case 'h':		fontheight = readInt(is);		break;	      case 'b':		fontbaseline = readInt(is);		break;	      case 'x':		fontxline = readInt(is);		break;	      case 'c':		fontcapline = readInt(is);		break;	      case 'w':		fontcwidth = readInt(is);		break;	      case 'T':		fontthickness = readInt(is);		break;	      case ' ':	      default:		break;	    }	}	if (ch == -1) {	    // error: premature eof	    throw new EOFException("Premature EOF in font file header.");	}	ungetc(is,ch);    	boolean done = false;	while(!done) {	    while((ch = getc(is)) != '#' && ch != '}' && ch != -1) {		//skip to #		;	    }	    	    if(ch == '#') {		readStrokes((char)readInt(is),is);	    } else {		done = true;	    }	}	//if(fontcwidth	makeDefaultGlyph();    }        //#ifndef ISMIDLET    public VFont(File file) throws IOException {	this(file.getName(),new InputStreamReader(makeis(file)));    }        public VFont(String name,File filename) throws IOException {	this(name, new InputStreamReader(makeis(filename)));    }    //#ifdef USEHERSHEY    public VFont(String name,HersheyFont hf) {	fontname = name;		int miny = hf.characterSetMinY;	int maxy = hf.characterSetMaxY;	fontheight = maxy - miny;	fontcwidth = 0;	fontcapline = fontxline = fontthickness = 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?