示例#1
0
  /**
   * Fix a broken font name table for a TrueType font. Some fonts do not have Microsoft-specific
   * name information, but Java won't work without it (grrr.). This method takes a font and adds the
   * Microsoft data into it.
   *
   * @param ttf the font
   * @param name the font's name table
   * @return true if the table was fixed, or false if it was left as is
   */
  private boolean fixNameTable(TrueTypeFont ttf, NameTable name) {
    // if we didn't find the table, or there was an exception,
    // just create a new one
    if (name == null) {
      name = (NameTable) TrueTypeTable.createTable(ttf, "name");
      ttf.addTable("name", name);
    }

    // first, figure out some info about the font
    String fName = this.getBaseFont();
    String style = "Regular";

    if (fName.indexOf("Italic") > -1 || fName.indexOf("italic") > -1) {
      style = "Italic";
    } else if (fName.indexOf("Bold") > -1 || fName.indexOf("bold") > -1) {
      style = "Bold";
    }

    if (fName.indexOf('-') > -1) {
      fName = fName.substring(0, fName.indexOf('-'));
    }

    short platID = NameTable.PLATFORMID_MICROSOFT;
    short encID = 1;
    short langID = 1033;

    short[] nameIDs = {
      NameTable.NAMEID_COPYRIGHT,
      NameTable.NAMEID_FAMILY,
      NameTable.NAMEID_SUBFAMILY,
      NameTable.NAMEID_SUBFAMILY_UNIQUE,
      NameTable.NAMEID_FULL_NAME,
      NameTable.NAMEID_VERSION,
      NameTable.NAMEID_POSTSCRIPT_NAME,
      NameTable.NAMEID_TRADEMARK
    };

    String[] defaultValues = {
      "No copyright",
      fName,
      style,
      fName + " " + style,
      fName + " " + style,
      "1.0 (Fake)",
      fName,
      "No Trademark"
    };

    boolean changed = false;

    for (int i = 0; i < nameIDs.length; i++) {
      if (name.getRecord(platID, encID, langID, nameIDs[i]) == null) {
        name.addRecord(platID, encID, langID, nameIDs[i], defaultValues[i]);
        changed = true;
      }
    }

    return changed;
  }
示例#2
0
  /**
   * Fix the CMap table. This can be necessary if characters are mapped to control characters (0x9,
   * 0xa, 0xd) Java will not render them, even though they are valid.
   *
   * <p>Also, Java tends to not like it when there is only a Format 0 CMap, which happens frequently
   * when included Format 4 CMaps are broken. Since PDF prefers the Format 0 map, while Java prefers
   * the Format 4 map, it is generally necessary to re-write the Format 0 map as a Format 4 map to
   * make most PDFs work.
   *
   * @param ttf the font
   * @param cmap the CMap table
   * @return true if the font was changed, or false if it was left as-is
   */
  private boolean fixCMapTable(TrueTypeFont ttf, CmapTable cmap) {
    CMapFormat4 fourMap = null;
    CMapFormat0 zeroMap = null;

    for (int i = 0; i < mapIDs.length; i += 2) {
      CMap map = this.cmapTable.getCMap(mapIDs[i], mapIDs[i + 1]);
      if (map != null) {
        if (fourMap == null && map instanceof CMapFormat4) {
          fourMap = (CMapFormat4) map;
        } else if (zeroMap == null && map instanceof CMapFormat0) {
          zeroMap = (CMapFormat0) map;
        }
      }
    }

    // if there were no maps, we could have problems.  Just try creating
    // an identity map
    if (zeroMap == null && fourMap == null) {
      fourMap = (CMapFormat4) CMap.createMap((short) 4, (short) 0);
      fourMap.addSegment((short) getFirstChar(), (short) getLastChar(), (short) 0);
    }

    // create our map based on the type 0 map, since PDF seems
    // to prefer a type 0 map (Java prefers a unicode map)
    if (zeroMap != null) {
      fourMap = (CMapFormat4) CMap.createMap((short) 4, (short) 0);

      // add the mappings from 0 to null and 1 to notdef
      fourMap.addSegment((short) 0, (short) 1, (short) 0);

      for (int i = getFirstChar(); i <= getLastChar(); i++) {
        short value = (short) (zeroMap.map((byte) i) & 0xff);
        if (value != 0) {
          fourMap.addSegment((short) i, (short) i, (short) (value - i));
        }
      }
    }

    // now that we have a type four map, remap control characters
    for (int i = 0; i < controlChars.length; i++) {
      short idx = (short) (0xf000 | controlChars[i]);
      short value = (short) fourMap.map(controlChars[i]);

      fourMap.addSegment(idx, idx, (short) (value - idx));
    }

    // create a whole new table with just our map
    cmap = (CmapTable) TrueTypeTable.createTable(ttf, "cmap");
    cmap.addCMap((short) 3, (short) 1, fourMap);

    // replace the table in the font
    ttf.addTable("cmap", cmap);

    // change the stored table
    this.cmapTable = cmap;

    return true;
  }
示例#3
0
  /**
   * Set the font
   *
   * @param f the font to use
   */
  protected void setFont(Font f) {
    this.f = f;

    // if it's an OpenType font, parse the relevant tables to get
    // glyph name to code mappings
    if (f instanceof OpenType) {
      OpenType ot = (OpenType) f;

      byte[] cmapData = ot.getFontTable(OpenType.TAG_CMAP);
      byte[] postData = ot.getFontTable(OpenType.TAG_POST);

      TrueTypeFont ttf = new TrueTypeFont(0x10000);

      this.cmapTable =
          (CmapTable) TrueTypeTable.createTable(ttf, "cmap", ByteBuffer.wrap(cmapData));
      ttf.addTable("cmap", this.cmapTable);

      this.postTable =
          (PostTable) TrueTypeTable.createTable(ttf, "post", ByteBuffer.wrap(postData));
      ttf.addTable("post", this.postTable);
    }
  }