/** Writes out to disk the header, and then all the properties */
  public void writeOut(OutputStream o) throws IOException {
    // First goes the number of characters we affect
    StyleTextPropAtom.writeLittleEndian(charactersCovered, o);

    // Then we have the reserved field if required
    if (reservedField > -1) {
      StyleTextPropAtom.writeLittleEndian(reservedField, o);
    }

    // Then the mask field
    int mask = maskSpecial;
    for (int i = 0; i < textPropList.size(); i++) {
      TextProp textProp = (TextProp) textPropList.get(i);
      // sometimes header indicates that the bitmask is present but its value is 0

      if (textProp instanceof BitMaskTextProp) {
        if (mask == 0) mask |= textProp.getWriteMask();
      } else {
        mask |= textProp.getWriteMask();
      }
    }
    StyleTextPropAtom.writeLittleEndian(mask, o);

    // Then the contents of all the properties
    for (int i = 0; i < textPropList.size(); i++) {
      TextProp textProp = textPropList.get(i);
      int val = textProp.getValue();
      if (textProp.getSize() == 2) {
        StyleTextPropAtom.writeLittleEndian((short) val, o);
      } else if (textProp.getSize() == 4) {
        StyleTextPropAtom.writeLittleEndian(val, o);
      }
    }
  }
  /**
   * For an existing set of text properties, build the list of properties coded for in a given run
   * of properties.
   *
   * @return the number of bytes that were used encoding the properties list
   */
  public int buildTextPropList(
      int containsField, TextProp[] potentialProperties, byte[] data, int dataOffset) {
    int bytesPassed = 0;

    // For each possible entry, see if we match the mask
    // If we do, decode that, save it, and shuffle on
    for (int i = 0; i < potentialProperties.length; i++) {
      // Check there's still data left to read

      // Check if this property is found in the mask
      if ((containsField & potentialProperties[i].getMask()) != 0) {
        if (dataOffset + bytesPassed >= data.length) {
          // Out of data, can't be any more properties to go
          // remember the mask and return
          maskSpecial |= potentialProperties[i].getMask();
          return bytesPassed;
        }

        // Bingo, data contains this property
        TextProp prop = (TextProp) potentialProperties[i].clone();
        int val = 0;
        if (prop.getSize() == 2) {
          val = LittleEndian.getShort(data, dataOffset + bytesPassed);
        } else if (prop.getSize() == 4) {
          val = LittleEndian.getInt(data, dataOffset + bytesPassed);
        } else if (prop.getSize() == 0) {
          // remember "special" bits.
          maskSpecial |= potentialProperties[i].getMask();
          continue;
        }
        prop.setValue(val);
        bytesPassed += prop.getSize();
        textPropList.add(prop);
      }
    }

    // Return how many bytes were used
    return bytesPassed;
  }