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 + -
显示快捷键?