/**
   * @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));
  }
Example #2
0
  /**
   * Returns the 3D bounding box of the specified glyph code.
   *
   * @param glyphCode the glyphCode from the original 2D Font
   * @param bounds the 3D glyph's bounds
   */
  public void getBoundingBox(int glyphCode, BoundingBox bounds) {
    int[] gCodes = {glyphCode};
    GlyphVector gVec = font.createGlyphVector(frc, gCodes);
    Rectangle2D.Float bounds2d =
        (Rectangle2D.Float) (((GlyphMetrics) (gVec.getGlyphMetrics(0))).getBounds2D());

    Point3d lower = new Point3d(bounds2d.x, bounds2d.y, 0.0);
    Point3d upper;
    if (fontExtrusion != null) {
      upper =
          new Point3d(
              bounds2d.x + bounds2d.width, bounds2d.y + bounds2d.height, fontExtrusion.length);
    } else {
      upper = new Point3d(bounds2d.x + bounds2d.width, bounds2d.y + bounds2d.height, 0.0);
    }
    bounds.setLower(lower);
    bounds.setUpper(upper);
  }
Example #3
0
 private int[] getGlyphMetrics(Font font, int codePoint) {
   // xOffset and xAdvance will be incorrect for unicode characters such as combining marks or
   // non-spacing characters
   // (eg Pnujabi's "\u0A1C\u0A47") that require the context of surrounding glyphs to determine
   // spacing, but thisis the
   // best we can do with the BMFont format.
   char[] chars = Character.toChars(codePoint);
   GlyphVector vector =
       font.layoutGlyphVector(
           GlyphPage.renderContext, chars, 0, chars.length, Font.LAYOUT_LEFT_TO_RIGHT);
   GlyphMetrics metrics = vector.getGlyphMetrics(0);
   int xOffset = vector.getGlyphPixelBounds(0, null, 0, 0).x - unicodeFont.getPaddingLeft();
   int xAdvance =
       (int)
           (metrics.getAdvanceX()
               + unicodeFont.getPaddingAdvanceX()
               + unicodeFont.getPaddingLeft()
               + unicodeFont.getPaddingRight());
   return new int[] {xOffset, xAdvance};
 }
 private void parseProblemGlyphs() {
   myCheckedForProblemGlyphs = true;
   BufferedImage buffer = UIUtil.createImage(20, 20, BufferedImage.TYPE_INT_RGB);
   final Graphics graphics = buffer.getGraphics();
   if (!(graphics instanceof Graphics2D)) {
     return;
   }
   final FontRenderContext context = ((Graphics2D) graphics).getFontRenderContext();
   char[] charBuffer = new char[1];
   for (char c = 0; c < 128; c++) {
     if (!myFont.canDisplay(c)) {
       continue;
     }
     charBuffer[0] = c;
     final GlyphVector vector = myFont.createGlyphVector(context, charBuffer);
     final float y = vector.getGlyphMetrics(0).getAdvanceY();
     if (Math.round(y) != 0) {
       mySymbolsToBreakDrawingIteration.add(c);
     }
   }
   myHasGlyphsToBreakDrawingIteration = !mySymbolsToBreakDrawingIteration.isEmpty();
 }
Example #5
0
  private TessOutput tesselateString(String s) {
    GlyphVector gv = _font.createGlyphVector(_frc, s);

    Shape shape = gv.getOutline();
    //
    AffineTransform at = new AffineTransform();
    at.scale(1, -1);
    PathIterator pIt = shape.getPathIterator(at, _font.getSize() / 200.0);

    // Create a GLU tesselator
    GLUtessellator tess = GLU.gluNewTess();
    CharTesselator tessAdapt = new CharTesselator();

    GLU.gluTessCallback(tess, GLU.GLU_TESS_VERTEX, tessAdapt);
    GLU.gluTessCallback(tess, GLU.GLU_TESS_BEGIN, tessAdapt);
    GLU.gluTessCallback(tess, GLU.GLU_TESS_END, tessAdapt);
    GLU.gluTessCallback(tess, GLU.GLU_TESS_COMBINE, tessAdapt);
    GLU.gluTessCallback(tess, GLU.GLU_TESS_ERROR, tessAdapt);

    int winding = pIt.getWindingRule();

    if (winding == PathIterator.WIND_EVEN_ODD)
      GLU.gluTessProperty(tess, GLU.GLU_TESS_WINDING_RULE, GLU.GLU_TESS_WINDING_ODD);
    else if (winding == PathIterator.WIND_NON_ZERO)
      GLU.gluTessProperty(tess, GLU.GLU_TESS_WINDING_RULE, GLU.GLU_TESS_WINDING_NONZERO);
    else assert (false); // PathIterator should only return these two winding rules

    GLU.gluBeginPolygon(tess);
    GLU.gluTessNormal(tess, 0, 0, 1);
    double[] first = null;
    double[] v;
    while (!pIt.isDone()) {
      v = new double[3];
      int type = pIt.currentSegment(v);
      v[2] = 0.0;
      if (type == PathIterator.SEG_MOVETO) {
        first = v;
        GLU.gluNextContour(tess, GLU.GLU_UNKNOWN);
        GLU.gluTessVertex(tess, v, 0, v);
      } else if (type == PathIterator.SEG_LINETO) {
        GLU.gluTessVertex(tess, v, 0, v);
      } else if (type == PathIterator.SEG_CLOSE) {
        assert (first != null); // If this is true, there is an error in the AWT path iterator
        GLU.gluTessVertex(tess, first, 0, first);
        first = null;
      } else {
        assert (false); // The path itertor should not return other path types here
      }
      pIt.next();
    }
    GLU.gluEndPolygon(tess);

    int numVerts = tessAdapt.getVerts().size();
    double[] verts = new double[numVerts];
    int count = 0;
    for (double d : tessAdapt.getVerts()) {
      verts[count++] = d;
    }

    TessOutput ret = new TessOutput();
    ret.verts = verts;
    ret.bounds = gv.getVisualBounds();

    ret.advances = new double[s.length()];
    for (int i = 0; i < s.length(); ++i) {
      ret.advances[i] = gv.getGlyphMetrics(i).getAdvance();
    }
    return ret;
  }