/** * Get a glyph outline by character code * * <p>Note this method must always return an outline * * @param src the character code of the desired glyph * @return the glyph outline */ @Override protected GeneralPath getOutline(char src, float width) { // some true type fonts put characters in the undefined // region of Unicode instead of as normal characters. if (!this.f.canDisplay(src) && this.f.canDisplay((char) (src + 0xf000))) { src += 0xf000; } // filter out control characters for (int i = 0; i < controlChars.length; i++) { if (controlChars[i] == src) { src = (char) (0xf000 | src); break; } } char[] glyph = new char[1]; glyph[0] = src; GlyphVector gv = this.f.createGlyphVector(this.basecontext, glyph); GeneralPath gp = new GeneralPath(gv.getGlyphOutline(0)); // this should be gv.getGlyphMetrics(0).getAdvance(), but that is // broken on the Mac, so we need to read the advance from the // hmtx table in the font CMap map = this.cmapTable.getCMap(mapIDs[0], mapIDs[1]); int glyphID = map.map(src); float advance = (float) this.hmtxTable.getAdvance(glyphID) / (float) this.unitsPerEm; float widthfactor = width / advance; gp.transform(AffineTransform.getScaleInstance(widthfactor, -1)); return gp; }
/** * @param c * @param font * @return GlyphVector using a default rendering context */ private SVGGlyph createGlyph(int c, Font font) { GlyphVector glyphVector = font.createGlyphVector( // flipping is done by SVGGlyph new FontRenderContext(null, true, true), // unicode to char String.valueOf((char) c)); // create and store the SVG Glyph return new SVGGlyph(glyphVector.getGlyphOutline(0), c, glyphVector.getGlyphMetrics(0)); }