CMapFormat4(Buffer buffer, int offset) {

      buffer.position(offset);
      buffer.getChar(); // skip, we already know format=4
      int subtableLength = buffer.getChar();
      /* Try to recover from some bad fonts which specify a subtable
       * length that would overflow the byte buffer holding the whole
       * cmap table. If this isn't a recoverable situation an exception
       * may be thrown which is caught higher up the call stack.
       * Whilst this may seem lenient, in practice, unless the "bad"
       * subtable we are using is the last one in the cmap table we
       * would have no way of knowing about this problem anyway.
       */
      if (offset + subtableLength > buffer.capacity()) {
        subtableLength = buffer.capacity() - offset;
      }
      buffer.getChar(); // skip language
      segCount = buffer.getChar() / 2;
      buffer.getChar(); // skip searchRange
      entrySelector = buffer.getChar();
      rangeShift = buffer.getChar() / 2;
      startCount = new char[segCount];
      endCount = new char[segCount];
      idDelta = new short[segCount];
      idRangeOffset = new char[segCount];

      for (int i = 0; i < segCount; i++) {
        endCount[i] = buffer.getChar();
      }
      buffer.getChar(); // 2 bytes for reserved pad
      for (int i = 0; i < segCount; i++) {
        startCount[i] = buffer.getChar();
      }

      for (int i = 0; i < segCount; i++) {
        idDelta[i] = (short) buffer.getChar();
      }

      for (int i = 0; i < segCount; i++) {
        char ctmp = buffer.getChar();
        idRangeOffset[i] = (char) ((ctmp >> 1) & 0xffff);
      }
      /* Can calculate the number of glyph IDs by subtracting
       * "pos" from the length of the cmap
       */
      int pos = (segCount * 8 + 16) / 2;
      buffer.position(pos * 2 + offset); // * 2 for chars
      int numGlyphIds = (subtableLength / 2 - pos);
      glyphIds = new char[numGlyphIds];
      for (int i = 0; i < numGlyphIds; i++) {
        glyphIds[i] = buffer.getChar();
      }
    }