Example #1
0
  protected static String getKerningPairAsSVG(KerningPair kp, PostTable post) {
    String leftGlyphName = post.getGlyphName(kp.getLeft());
    String rightGlyphName = post.getGlyphName(kp.getRight());

    StringBuffer sb = new StringBuffer();
    // sb.append("<hkern ");
    sb.append(XML_OPEN_TAG_START).append(SVG_HKERN_TAG).append(XML_SPACE);

    if (leftGlyphName == null) {
      sb.append(SVG_U1_ATTRIBUTE).append(XML_EQUAL_QUOT);

      sb.append(kp.getLeft());
    } else {
      // sb.append("g1=\"");
      sb.append(SVG_G1_ATTRIBUTE).append(XML_EQUAL_QUOT);

      sb.append(leftGlyphName);
    }

    // sb.append("\" ");
    sb.append(XML_CHAR_QUOT).append(XML_SPACE);

    if (rightGlyphName == null) {
      // sb.append("u2=\"");
      sb.append(SVG_U2_ATTRIBUTE).append(XML_EQUAL_QUOT);

      sb.append(kp.getRight());
    } else {
      // sb.append("g2=\"");
      sb.append(SVG_G2_ATTRIBUTE).append(XML_EQUAL_QUOT);

      sb.append(rightGlyphName);
    }

    // sb.append("\" k=\"");
    sb.append(XML_CHAR_QUOT).append(XML_SPACE).append(SVG_K_ATTRIBUTE).append(XML_EQUAL_QUOT);

    // SVG kerning values are inverted from TrueType's.
    sb.append(-kp.getValue());
    // sb.append("\"/>");
    sb.append(XML_CHAR_QUOT).append(XML_OPEN_TAG_END_NO_CHILDREN);

    return sb.toString();
  }
Example #2
0
  /**
   * Returns a &lt;font&gt;&#x2e;&#x2e;&#x2e;&lt;/font&gt; block, defining the specified font.
   *
   * @param font The TrueType font to be converted to SVG
   * @param id An XML id attribute for the font element
   * @param first The first character in the output range
   * @param last The last character in the output range
   * @param forceAscii Force the use of the ASCII character map
   */
  protected static void writeFontAsSVGFragment(
      PrintStream ps,
      Font font,
      String id,
      int first,
      int last,
      boolean autoRange,
      boolean forceAscii)
      throws Exception {
    //    StringBuffer sb = new StringBuffer();
    //    int horiz_advance_x = font.getHmtxTable().getAdvanceWidth(
    //      font.getHheaTable().getNumberOfHMetrics() - 1);
    int horiz_advance_x = font.getOS2Table().getAvgCharWidth();

    ps.print(XML_OPEN_TAG_START);
    ps.print(SVG_FONT_TAG);
    ps.print(XML_SPACE);
    // ps.print("<font ");
    if (id != null) {
      ps.print(SVG_ID_ATTRIBUTE);
      ps.print(XML_EQUAL_QUOT);
      // ps.print("id=\"");
      ps.print(id);
      ps.print(XML_CHAR_QUOT);
      ps.print(XML_SPACE);
      // ps.print("\" ");
    }

    ps.print(SVG_HORIZ_ADV_X_ATTRIBUTE);
    ps.print(XML_EQUAL_QUOT);
    // ps.print("horiz-adv-x=\"");
    ps.print(horiz_advance_x);
    ps.print(XML_CHAR_QUOT);
    ps.print(XML_OPEN_TAG_END_CHILDREN);
    // ps.println("\">");

    ps.print(getSVGFontFaceElement(font));

    // Decide upon a cmap table to use for our character to glyph look-up
    CmapFormat cmapFmt = null;
    if (forceAscii) {
      // We've been asked to use the ASCII/Macintosh cmap format
      cmapFmt = font.getCmapTable().getCmapFormat(Table.platformMacintosh, Table.encodingRoman);
    } else {
      // The default behaviour is to use the Unicode cmap encoding
      cmapFmt = font.getCmapTable().getCmapFormat(Table.platformMicrosoft, Table.encodingUGL);
      if (cmapFmt == null) {
        // This might be a symbol font, so we'll look for an "undefined" encoding
        cmapFmt =
            font.getCmapTable().getCmapFormat(Table.platformMicrosoft, Table.encodingUndefined);
      }
    }
    if (cmapFmt == null) {
      throw new Exception("Cannot find a suitable cmap table");
    }

    // If this font includes arabic script, we want to specify
    // substitutions for initial, medial, terminal & isolated
    // cases.
    GsubTable gsub = (GsubTable) font.getTable(Table.GSUB);
    SingleSubst initialSubst = null;
    SingleSubst medialSubst = null;
    SingleSubst terminalSubst = null;
    if (gsub != null) {
      Script s = gsub.getScriptList().findScript(SCRIPT_TAG_ARAB);
      if (s != null) {
        LangSys ls = s.getDefaultLangSys();
        if (ls != null) {
          Feature init = gsub.getFeatureList().findFeature(ls, FEATURE_TAG_INIT);
          Feature medi = gsub.getFeatureList().findFeature(ls, FEATURE_TAG_MEDI);
          Feature fina = gsub.getFeatureList().findFeature(ls, FEATURE_TAG_FINA);

          if (init != null) {
            initialSubst = (SingleSubst) gsub.getLookupList().getLookup(init, 0).getSubtable(0);
          }
          if (medi != null) {
            medialSubst = (SingleSubst) gsub.getLookupList().getLookup(medi, 0).getSubtable(0);
          }
          if (fina != null) {
            terminalSubst = (SingleSubst) gsub.getLookupList().getLookup(fina, 0).getSubtable(0);
          }
        }
      }
    }

    // Include the missing glyph
    ps.println(
        getGlyphAsSVG(
            font,
            font.getGlyph(0),
            0,
            horiz_advance_x,
            initialSubst,
            medialSubst,
            terminalSubst,
            ""));

    try {
      if (first == -1) {
        if (!autoRange) first = DEFAULT_FIRST;
        else first = cmapFmt.getFirst();
      }
      if (last == -1) {
        if (!autoRange) last = DEFAULT_LAST;
        else last = cmapFmt.getLast();
      }

      // Include our requested range
      Set glyphSet = new HashSet();
      for (int i = first; i <= last; i++) {
        int glyphIndex = cmapFmt.mapCharCode(i);
        //        ps.println(String.valueOf(i) + " -> " + String.valueOf(glyphIndex));
        //      if (font.getGlyphs()[glyphIndex] != null)
        //        sb.append(font.getGlyphs()[glyphIndex].toString() + "\n");

        if (glyphIndex > 0) {
          // add glyph ID to set so we can filter later
          glyphSet.add(glyphIndex);

          ps.println(
              getGlyphAsSVG(
                  font,
                  font.getGlyph(glyphIndex),
                  glyphIndex,
                  horiz_advance_x,
                  initialSubst,
                  medialSubst,
                  terminalSubst,
                  (32 <= i && i <= 127)
                      ? encodeEntities(String.valueOf((char) i))
                      : XML_CHAR_REF_PREFIX + Integer.toHexString(i) + XML_CHAR_REF_SUFFIX));
        }
      }

      // Output kerning pairs from the requested range
      KernTable kern = (KernTable) font.getTable(Table.kern);
      if (kern != null) {
        KernSubtable kst = kern.getSubtable(0);
        PostTable post = (PostTable) font.getTable(Table.post);
        for (int i = 0; i < kst.getKerningPairCount(); i++) {
          KerningPair kpair = kst.getKerningPair(i);
          // check if left and right are both in our glyph set
          if (glyphSet.contains(kpair.getLeft()) && glyphSet.contains(kpair.getRight())) {
            ps.println(getKerningPairAsSVG(kpair, post));
          }
        }
      }
    } catch (Exception e) {
      System.err.println(e.getMessage());
    }

    ps.print(XML_CLOSE_TAG_START);
    ps.print(SVG_FONT_TAG);
    ps.println(XML_CLOSE_TAG_END);
    // ps.println("</font>");
  }