加入收藏 | 网站地图 | | RSS | WAP
你好,游客 登录 注册 搜索

java绘制路径跟随文字效果(文字沿着路径显示)

[日期:2014-04-08] 作者: 来源: [字体: ]

ps中有这种文字跟随路径方向显示的效果,个性化比较强。Java程序如何实现呢?

效果图:

路径跟随文字

以下是Java2D绘图技术实现文字跟随路径显示的源代码:

package com.ew8cn.awt;

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;

public class TextStroke implements Stroke {
	private String text;
	private Font font;
	private boolean stretchToFit = false;
	private boolean repeat = false;
	private AffineTransform t = new AffineTransform();

	private static final float FLATNESS = 1;

	public TextStroke( String text, Font font ) {
		this( text, font, true, false );
	}

	public TextStroke( String text, Font font, boolean stretchToFit, boolean repeat ) {
		this.text = text;
		this.font = font;
		this.stretchToFit = stretchToFit;
		this.repeat = repeat;
	}

	public Shape createStrokedShape( Shape shape ) {
		FontRenderContext frc = new FontRenderContext(null, true, true);
		GlyphVector glyphVector = font.createGlyphVector(frc, text);

		GeneralPath result = new GeneralPath();
		PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
		float points[] = new float[6];
		float moveX = 0, moveY = 0;
		float lastX = 0, lastY = 0;
		float thisX = 0, thisY = 0;
		int type = 0;
		boolean first = false;
		float next = 0;
		int currentChar = 0;
		int length = glyphVector.getNumGlyphs();

		if ( length == 0 )
            return result;

        float factor = stretchToFit ? measurePathLength( shape )/(float)glyphVector.getLogicalBounds().getWidth() : 1.0f;
        float nextAdvance = 0;

		while ( currentChar < length && !it.isDone() ) {
			type = it.currentSegment( points );
			switch( type ){
			case PathIterator.SEG_MOVETO:
				moveX = lastX = points[0];
				moveY = lastY = points[1];
				result.moveTo( moveX, moveY );
				first = true;
                nextAdvance = glyphVector.getGlyphMetrics( currentChar ).getAdvance() * 0.5f;
                next = nextAdvance;
				break;

			case PathIterator.SEG_CLOSE:
				points[0] = moveX;
				points[1] = moveY;
				// Fall into....

			case PathIterator.SEG_LINETO:
				thisX = points[0];
				thisY = points[1];
				float dx = thisX-lastX;
				float dy = thisY-lastY;
				float distance = (float)Math.sqrt( dx*dx + dy*dy );
				if ( distance >= next ) {
					float r = 1.0f/distance;
					float angle = (float)Math.atan2( dy, dx );
					while ( currentChar < length && distance >= next ) {
						Shape glyph = glyphVector.getGlyphOutline( currentChar );
						Point2D p = glyphVector.getGlyPHPosition(currentChar);
						float px = (float)p.getX();
						float py = (float)p.getY();
						float x = lastX + next*dx*r;
						float y = lastY + next*dy*r;
                        float advance = nextAdvance;
                        nextAdvance = currentChar < length-1 ? glyphVector.getGlyphMetrics(currentChar+1).getAdvance() * 0.5f : 0;
						t.setToTranslation( x, y );
						t.rotate( angle );
						t.translate( -px-advance, -py );
						result.append( t.createTransformedShape( glyph ), false );
						next += (advance+nextAdvance) * factor;
						currentChar++;
						if ( repeat )
							currentChar %= length;
					}
				}
                next -= distance;
				first = false;
				lastX = thisX;
				lastY = thisY;
				break;
			}
			it.next();
		}

		return result;
	}

	public float measurePathLength( Shape shape ) {
		PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
		float points[] = new float[6];
		float moveX = 0, moveY = 0;
		float lastX = 0, lastY = 0;
		float thisX = 0, thisY = 0;
		int type = 0;
        float total = 0;

		while ( !it.isDone() ) {
			type = it.currentSegment( points );
			switch( type ){
			case PathIterator.SEG_MOVETO:
				moveX = lastX = points[0];
				moveY = lastY = points[1];
				break;

			case PathIterator.SEG_CLOSE:
				points[0] = moveX;
				points[1] = moveY;
				// Fall into....

			case PathIterator.SEG_LINETO:
				thisX = points[0];
				thisY = points[1];
				float dx = thisX-lastX;
				float dy = thisY-lastY;
				total += (float)Math.sqrt( dx*dx + dy*dy );
				lastX = thisX;
				lastY = thisY;
				break;
			}
			it.next();
		}

		return total;
	}

}

关键词:文字  路径  跟随 

收藏 推荐 打印 | 录入:blue1000 | 阅读:
最新图文
本文评论   查看全部评论 (3)
表情: 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事/刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
第 3 楼
* 匿名 发表于 2016/12/25 13:05:04
http://www.blue1000.com/bkhtml/c70/2010-12/69903.htm 个性网名繁体字 http://www.135995.com/wangming/content138.html 非主流个性网名 http://www.135995.com/wangming/content137.html
第 2 楼
* 匿名 发表于 2016/12/24 13:02:39
http://www.blue1000.com/bkhtml/c70/2010-12/69903.htm 明天你好作文 http://www.135995.com/details/zs905.html 春天 你好 作文 http://www.135995.com/details/zs1119.html
第 1 楼
* 匿名 发表于 2015/6/15 17:05:10
楼主厉害,能不能给留给邮箱,有些问题请教一下,谢谢。