diff options
-rw-r--r-- | src/net/java/dev/typecast/cff/T2Interpreter.java | 53 | ||||
-rw-r--r-- | src/net/java/dev/typecast/edit/GlyphEdit.java | 73 | ||||
-rw-r--r-- | src/net/java/dev/typecast/ot/T2Glyph.java | 29 | ||||
-rw-r--r-- | src/net/java/dev/typecast/render/GlyphPathFactory.java | 36 |
4 files changed, 163 insertions, 28 deletions
diff --git a/src/net/java/dev/typecast/cff/T2Interpreter.java b/src/net/java/dev/typecast/cff/T2Interpreter.java index a8cb5a5..ace1fd6 100644 --- a/src/net/java/dev/typecast/cff/T2Interpreter.java +++ b/src/net/java/dev/typecast/cff/T2Interpreter.java @@ -52,6 +52,8 @@ public class T2Interpreter { private final Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; private int _stemCount = 0; + private ArrayList<Integer> _hstems; + private ArrayList<Integer> _vstems; private ArrayList<Point> _points; private Index _localSubrIndex; @@ -65,6 +67,16 @@ public class T2Interpreter { public T2Interpreter() { } + public Integer[] getHStems() { + Integer[] array = new Integer[_hstems.size()]; + return _hstems.toArray(array); + } + + public Integer[] getVStems() { + Integer[] array = new Integer[_vstems.size()]; + return _vstems.toArray(array); + } + /** * Moves the current point to a position at the relative coordinates * (dx1, dy1). @@ -637,23 +649,53 @@ public class T2Interpreter { } private void _hstem() { + if (getArgCount() % 2 == 1) { + + // This will be the width value + popArg(); + } - clearArg(); + while (getArgCount() > 0) { + _hstems.add(popArg().intValue()); + } } private void _vstem() { + if (getArgCount() % 2 == 1) { + + // This will be the width value + popArg(); + } - clearArg(); + while (getArgCount() > 0) { + _vstems.add(popArg().intValue()); + } } private void _hstemhm() { + if (getArgCount() % 2 == 1) { + + // This will be the width value + popArg(); + } + _stemCount += getArgCount() / 2; - clearArg(); + while (getArgCount() > 0) { + _hstems.add(popArg().intValue()); + } } private void _vstemhm() { + if (getArgCount() % 2 == 1) { + + // This will be the width value + popArg(); + } + _stemCount += getArgCount() / 2; - clearArg(); + while (getArgCount() > 0) { + _vstems.add(popArg().intValue()); + } } private void _hintmask() { @@ -950,6 +992,9 @@ public class T2Interpreter { _globalSubrIndex.getDataLength()); _cs = cs; + _hstems = new ArrayList<>(); + _vstems = new ArrayList<>(); + _points = new ArrayList<>(); _ip = _cs.getFirstIndex(); while (_cs.moreBytes(_ip)) { diff --git a/src/net/java/dev/typecast/edit/GlyphEdit.java b/src/net/java/dev/typecast/edit/GlyphEdit.java index 66f76c9..c10ab28 100644 --- a/src/net/java/dev/typecast/edit/GlyphEdit.java +++ b/src/net/java/dev/typecast/edit/GlyphEdit.java @@ -35,6 +35,7 @@ import javax.swing.event.MouseInputListener; import net.java.dev.typecast.ot.Glyph; import net.java.dev.typecast.ot.OTFont; import net.java.dev.typecast.ot.Point; +import net.java.dev.typecast.ot.T2Glyph; import net.java.dev.typecast.render.GlyphPathFactory; /** @@ -68,10 +69,14 @@ public class GlyphEdit extends JPanel implements Scrollable { _tool = new PointTool(this); MouseInputListener mil = new MouseInputListener() { + @Override public void mouseClicked(MouseEvent e) { } + @Override public void mouseEntered(MouseEvent e) { } + @Override public void mouseExited(MouseEvent e) { } + @Override public void mousePressed(MouseEvent e) { if (_tool != null) { if (e.isControlDown()) { @@ -81,22 +86,26 @@ public class GlyphEdit extends JPanel implements Scrollable { } } } + @Override public void mouseReleased(MouseEvent e) { if (_tool != null) { _tool.released(e.getPoint()); } } + @Override public void mouseDragged(MouseEvent e) { if (_tool != null) { _tool.dragged(e.getPoint()); } } + @Override public void mouseMoved(MouseEvent e) { } }; addMouseListener(mil); addMouseMotionListener(mil); } + @Override public void paint(Graphics graphics) { super.paint(graphics); @@ -105,7 +114,7 @@ public class GlyphEdit extends JPanel implements Scrollable { } Graphics2D g2d = (Graphics2D) graphics; - + int unitsPerEmBy2 = _font.getHeadTable().getUnitsPerEm() / 2; _translateX = 2 * unitsPerEmBy2; _translateY = 2 * unitsPerEmBy2; @@ -114,6 +123,7 @@ public class GlyphEdit extends JPanel implements Scrollable { AffineTransform atOriginal = new AffineTransform(at); at.scale(_scaleFactor, _scaleFactor); at.translate(_translateX, _translateY); + at.scale(1.0, -1.0); g2d.setTransform(at); // Draw grid @@ -123,10 +133,64 @@ public class GlyphEdit extends JPanel implements Scrollable { // Draw guides g2d.setPaint(Color.lightGray); - g2d.draw(new Line2D.Float(-unitsPerEmBy2, -_font.getAscent(), unitsPerEmBy2, -_font.getAscent())); - g2d.draw(new Line2D.Float(-unitsPerEmBy2, -_font.getDescent(), unitsPerEmBy2, -_font.getDescent())); + g2d.draw(new Line2D.Float(-unitsPerEmBy2, _font.getAscent(), unitsPerEmBy2, _font.getAscent())); + g2d.draw(new Line2D.Float(-unitsPerEmBy2, _font.getDescent(), unitsPerEmBy2, _font.getDescent())); g2d.draw(new Line2D.Float(_glyph.getLeftSideBearing(), -unitsPerEmBy2, _glyph.getLeftSideBearing(), unitsPerEmBy2)); g2d.draw(new Line2D.Float(_glyph.getAdvanceWidth(), -unitsPerEmBy2, _glyph.getAdvanceWidth(), unitsPerEmBy2)); + + if (_glyph instanceof T2Glyph) { + T2Glyph t2g = (T2Glyph) _glyph; + Rectangle2D bounds = t2g.getBounds(); + +// g2d.setPaint(Color.PINK); +// g2d.fill(bounds); +// +// g2d.setPaint(Color.RED); + + int y = 0; + boolean isWidth = false; + for (Integer horiz : t2g.getHStems()) { + if (isWidth) { + if (horiz == -20) { + + // Top edge + y = (int) bounds.getMaxY(); + } else if (horiz == -21) { + + // Bottom edge + y = (int) bounds.getMinY(); + } else { + y += horiz; + } + } else { + y += horiz; + } +// g2d.draw(new Line2D.Float(0, y, 1000, y)); + isWidth = !isWidth; + } + + int x = 0; + isWidth = false; + for (Integer vert : t2g.getVStems()) { + if (isWidth) { + if (vert == -20) { + + // Right edge + x = (int) bounds.getMaxX(); + } else if (vert == -21) { + + // Left edge + x = (int) bounds.getMinX(); + } else { + x += vert; + } + } else { + x += vert; + } +// g2d.draw(new Line2D.Float(x, 0, x, 1000)); + isWidth = !isWidth; + } + } // Draw contours g2d.setPaint(Color.black); @@ -144,7 +208,8 @@ public class GlyphEdit extends JPanel implements Scrollable { if (_drawControlPoints) { - g2d.setTransform(atOriginal); + AffineTransform at2 = new AffineTransform(atOriginal); + g2d.setTransform(at2); // Draw control points for (int i = 0; i < _glyph.getPointCount(); i++) { diff --git a/src/net/java/dev/typecast/ot/T2Glyph.java b/src/net/java/dev/typecast/ot/T2Glyph.java index be1f573..2b33f3e 100644 --- a/src/net/java/dev/typecast/ot/T2Glyph.java +++ b/src/net/java/dev/typecast/ot/T2Glyph.java @@ -1,7 +1,7 @@ /* * Typecast - The Font Development Environment * - * Copyright (c) 2004-2015 David Schweinsberg + * Copyright (c) 2004-2016 David Schweinsberg * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ */ package net.java.dev.typecast.ot; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; import net.java.dev.typecast.cff.CharstringType2; import net.java.dev.typecast.cff.T2Interpreter; @@ -27,7 +29,9 @@ import net.java.dev.typecast.cff.T2Interpreter; public class T2Glyph extends Glyph { protected short _leftSideBearing; protected int _advanceWidth; - private Point[] _points; + private final Point[] _points; + private final Integer[] _hstems; + private final Integer[] _vstems; /** * Construct a Glyph from a PostScript outline described by a Charstring. @@ -43,6 +47,8 @@ public class T2Glyph extends Glyph { _advanceWidth = advance; T2Interpreter t2i = new T2Interpreter(); _points = t2i.execute(cs); + _hstems = t2i.getHStems(); + _vstems = t2i.getVStems(); } @Override @@ -64,4 +70,23 @@ public class T2Glyph extends Glyph { public int getPointCount() { return _points.length; } + + public Integer[] getHStems() { + return _hstems; + } + + public Integer[] getVStems() { + return _vstems; + } + + public Rectangle2D getBounds() { + Rectangle r = null; + for (Point p : _points) { + if (r == null) { + r = new Rectangle(p.x, p.y, 0, 0); + } + r.add(new java.awt.Point(p.x, p.y)); + } + return r != null ? r : new Rectangle(0, 0, 0, 0); + } } diff --git a/src/net/java/dev/typecast/render/GlyphPathFactory.java b/src/net/java/dev/typecast/render/GlyphPathFactory.java index ff8a1d9..257ba7e 100644 --- a/src/net/java/dev/typecast/render/GlyphPathFactory.java +++ b/src/net/java/dev/typecast/render/GlyphPathFactory.java @@ -77,43 +77,43 @@ public class GlyphPathFactory { Point point_plus1 = glyph.getPoint(startIndex + (offset+1)%count); Point point_plus2 = glyph.getPoint(startIndex + (offset+2)%count); if (point.onCurve && point_plus1.onCurve) { - s = new Line2D.Float(point.x, -point.y, point_plus1.x, -point_plus1.y); + s = new Line2D.Float(point.x, point.y, point_plus1.x, point_plus1.y); offset++; } else if (point.onCurve && !point_plus1.onCurve && point_plus2.onCurve) { s = new QuadCurve2D.Float( point.x, - -point.y, + point.y, point_plus1.x, - -point_plus1.y, + point_plus1.y, point_plus2.x, - -point_plus2.y); + point_plus2.y); offset+=2; } else if (point.onCurve && !point_plus1.onCurve && !point_plus2.onCurve) { s = new QuadCurve2D.Float( point.x, - -point.y, + point.y, point_plus1.x, - -point_plus1.y, + point_plus1.y, midValue(point_plus1.x, point_plus2.x), - -midValue(point_plus1.y, point_plus2.y)); + midValue(point_plus1.y, point_plus2.y)); offset+=2; } else if (!point.onCurve && !point_plus1.onCurve) { s = new QuadCurve2D.Float( midValue(point_minus1.x, point.x), - -midValue(point_minus1.y, point.y), + midValue(point_minus1.y, point.y), point.x, - -point.y, + point.y, midValue(point.x, point_plus1.x), - -midValue(point.y, point_plus1.y)); + midValue(point.y, point_plus1.y)); offset++; } else if (!point.onCurve && point_plus1.onCurve) { s = new QuadCurve2D.Float( midValue(point_minus1.x, point.x), - -midValue(point_minus1.y, point.y), + midValue(point_minus1.y, point.y), point.x, - -point.y, + point.y, point_plus1.x, - -point_plus1.y); + point_plus1.y); offset++; } else { System.out.println("addContourToPath case not catered for!!"); @@ -134,18 +134,18 @@ public class GlyphPathFactory { Point point_plus2 = glyph.getPoint(startIndex + (offset+2)%count); Point point_plus3 = glyph.getPoint(startIndex + (offset+3)%count); if (point.onCurve && point_plus1.onCurve) { - s = new Line2D.Float(point.x, -point.y, point_plus1.x, -point_plus1.y); + s = new Line2D.Float(point.x, point.y, point_plus1.x, point_plus1.y); offset++; } else if (point.onCurve && !point_plus1.onCurve && !point_plus2.onCurve && point_plus3.onCurve) { s = new CubicCurve2D.Float( point.x, - -point.y, + point.y, point_plus1.x, - -point_plus1.y, + point_plus1.y, point_plus2.x, - -point_plus2.y, + point_plus2.y, point_plus3.x, - -point_plus3.y); + point_plus3.y); offset+=3; } else { System.out.println("addContourToPath case not catered for!!"); |