Esempio n. 1
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;
  }
Esempio n. 2
0
  /**
   * lookup the outline using the CMAPs, as specified in 32000-1:2008, 9.6.6.4, when an Encoding is
   * specified.
   *
   * @param val
   * @param width
   * @return GeneralPath
   */
  protected synchronized GeneralPath getOutlineFromCMaps(char val, float width) {
    // find the cmaps
    CmapTable cmap = (CmapTable) this.font.getTable("cmap");

    if (cmap == null) {
      return null;
    }

    // try maps in required order of (3, 1), (1, 0)
    CMap map = cmap.getCMap((short) 3, (short) 1);
    if (map == null) {
      map = cmap.getCMap((short) 1, (short) 0);
    }
    int idx = map.map(val);
    if (idx != 0) {
      return getOutline(idx, width);
    }

    return null;
  }
Esempio n. 3
0
  /** Get the outline of a character given the character code */
  @Override
  protected synchronized GeneralPath getOutline(char src, float width) {
    // find the cmaps
    CmapTable cmap = (CmapTable) this.font.getTable("cmap");

    // if there are no cmaps, this is (hopefully) a cid-mapped font,
    // so just trust the value we were given for src
    if (cmap == null) {
      return getOutline((int) src, width);
    }

    CMap[] maps = cmap.getCMaps();

    // try the maps in order
    for (int i = 0; i < maps.length; i++) {
      int idx = maps[i].map(src);
      if (idx != 0) {
        return getOutline(idx, width);
      }
    }

    // not found, return the empty glyph
    return getOutline(0, width);
  }