Example #1
0
 boolean isInvalid(StringBlock block, float gap) {
   if (isHead() || isTail()) return false;
   if (x0 == Integer.MIN_VALUE || y0 == Integer.MIN_VALUE) {
     return true;
   }
   Rectangle bound = block.getTextBox();
   if (bound == null) {
     return false;
   }
   return x0 > 0 && bound.x + bound.width - gap < getX1();
 }
Example #2
0
  public static ARSCFile read(IntReader reader) throws IOException {
    ARSCFile arsc = new ARSCFile();
    ReadUtil.readCheckType(reader, ARSC_CHUNK_TYPE);
    /* size */ reader.readInt();
    int groupCount = reader.readInt();

    if (groupCount != 1) {
      throw new IOException("Only one package per file is supported.");
    }

    arsc.strings = StringBlock.read(reader);
    arsc.pkges = new Pkge[1];
    arsc.pkges[0] = readPackage(arsc, reader);

    return arsc;
  }
Example #3
0
 private Rectangle getBound(StringBlock block) {
   if (block.getTextBox() != null) {
     return block.getTextBox();
   }
   return UNBOUNDED;
 }
Example #4
0
  void update(StringBlock block) {
    final float[] tabs = block.getTabPosition();
    final float tabWidth = block.getTabWidth();
    final Rectangle bound = getBound(block);
    sizeScale = block.getSize() / font.getCharSet().getRenderedSize();
    lineY = computeLineY(block);

    if (isHead()) {
      x0 = getBound(block).x;
      y0 = lineY;
      width = 0;
      height = 0;
      xAdvance = 0;
    } else if (isTab()) {
      x0 = previous.getNextX();
      width = tabWidth;
      y0 = lineY;
      height = 0;
      if (tabs != null && x0 < tabs[tabs.length - 1]) {
        for (int i = 0; i < tabs.length - 1; i++) {
          if (x0 > tabs[i] && x0 < tabs[i + 1]) {
            width = tabs[i + 1] - x0;
          }
        }
      }
      xAdvance = width;
    } else if (bitmapChar == null) {
      x0 = getPrevious().getX1();
      y0 = lineY;
      width = 0;
      height = 0;
      xAdvance = 0;
    } else {
      float xOffset = bitmapChar.getXOffset() * sizeScale;
      float yOffset = bitmapChar.getYOffset() * sizeScale;
      xAdvance = bitmapChar.getXAdvance() * sizeScale;
      width = bitmapChar.getWidth() * sizeScale;
      height = bitmapChar.getHeight() * sizeScale;
      float incrScale = rightToLeft ? -1f : 1f;
      float kernAmount = 0f;

      if (previous.isHead() || previous.eol) {
        x0 = bound.x;

        // The first letter quad will be drawn right at the first
        // position... but it does not offset by the characters offset
        // amount.  This means that we've potentially accumulated extra
        // pixels and the next letter won't get drawn far enough unless
        // we add this offset back into xAdvance.. by subtracting it.
        // This is the same thing that's done below because we've
        // technically baked the offset in just like below.  It doesn't
        // look like it at first glance so I'm keeping it separate with
        // this comment.
        xAdvance -= xOffset * incrScale;

      } else {
        x0 = previous.getNextX() + xOffset * incrScale;

        // Since x0 will have offset baked into it then we
        // need to counteract that in xAdvance.  This is better
        // than removing it in getNextX() because we also need
        // to take kerning into account below... which will also
        // get baked in.
        // Without this, getNextX() will return values too far to
        // the left, for example.
        xAdvance -= xOffset * incrScale;
      }
      y0 = lineY + LINE_DIR * yOffset;

      // Adjust for kerning
      BitmapCharacter lastChar = previous.getBitmapChar();
      if (lastChar != null && block.isKerning()) {
        kernAmount = lastChar.getKerning(c) * sizeScale;
        x0 += kernAmount * incrScale;

        // Need to unbake the kerning from xAdvance since it
        // is baked into x0... see above.
        // xAdvance -= kernAmount * incrScale;
        // No, kerning is an inter-character spacing and _does_ affect
        // all subsequent cursor positions.
      }
    }
    if (isEndOfLine()) {
      xAdvance = bound.x - x0;
    }
  }
Example #5
0
 /**
  * Gets the line height of a StringBlock.
  *
  * @param sb
  * @return
  */
 public float getLineHeight(StringBlock sb) {
   return charSet.getLineHeight() * (sb.getSize() / charSet.getRenderedSize());
 }
  private final void doNext() throws IOException {
    // Delayed initialization.
    if (m_strings == null) {
      ChunkUtil.readCheckType(m_reader, CHUNK_AXML_FILE);
      /* chunkSize */ m_reader.skipInt();
      m_strings = StringBlock.read(m_reader);
      m_namespaces.increaseDepth();
      m_operational = true;
    }

    if (m_event == END_DOCUMENT) {
      return;
    }

    int event = m_event;
    resetEventInfo();

    while (true) {
      if (m_decreaseDepth) {
        m_decreaseDepth = false;
        m_namespaces.decreaseDepth();
      }

      // Fake END_DOCUMENT event.
      if (event == END_TAG && m_namespaces.getDepth() == 1 && m_namespaces.getCurrentCount() == 0) {
        m_event = END_DOCUMENT;
        break;
      }

      int chunkType;
      if (event == START_DOCUMENT) {
        // Fake event, see CHUNK_XML_START_TAG handler.
        chunkType = CHUNK_XML_START_TAG;
      } else {
        chunkType = m_reader.readInt();
      }

      if (chunkType == CHUNK_RESOURCEIDS) {
        int chunkSize = m_reader.readInt();
        if (chunkSize < 8 || (chunkSize % 4) != 0) {
          throw new IOException("Invalid resource ids size (" + chunkSize + ").");
        }
        m_resourceIDs = m_reader.readIntArray(chunkSize / 4 - 2);
        continue;
      }

      if (chunkType < CHUNK_XML_FIRST || chunkType > CHUNK_XML_LAST) {
        throw new IOException("Invalid chunk type (" + chunkType + ").");
      }

      // Fake START_DOCUMENT event.
      if (chunkType == CHUNK_XML_START_TAG && event == -1) {
        m_event = START_DOCUMENT;
        break;
      }

      // Common header.
      /* chunkSize */ m_reader.skipInt();
      int lineNumber = m_reader.readInt();
      /* 0xFFFFFFFF */ m_reader.skipInt();

      if (chunkType == CHUNK_XML_START_NAMESPACE || chunkType == CHUNK_XML_END_NAMESPACE) {
        if (chunkType == CHUNK_XML_START_NAMESPACE) {
          int prefix = m_reader.readInt();
          int uri = m_reader.readInt();
          m_namespaces.push(prefix, uri);
        } else {
          /* prefix */ m_reader.skipInt();
          /* uri */ m_reader.skipInt();
          m_namespaces.pop();
        }
        continue;
      }

      m_lineNumber = lineNumber;

      if (chunkType == CHUNK_XML_START_TAG) {
        m_namespaceUri = m_reader.readInt();
        m_name = m_reader.readInt();
        /* flags? */ m_reader.skipInt();
        int attributeCount = m_reader.readInt();
        m_idAttribute = (attributeCount >>> 16) - 1;
        attributeCount &= 0xFFFF;
        m_classAttribute = m_reader.readInt();
        m_styleAttribute = (m_classAttribute >>> 16) - 1;
        m_classAttribute = (m_classAttribute & 0xFFFF) - 1;
        m_attributes = m_reader.readIntArray(attributeCount * ATTRIBUTE_LENGHT);
        for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length; ) {
          m_attributes[i] = (m_attributes[i] >>> 24);
          i += ATTRIBUTE_LENGHT;
        }
        m_namespaces.increaseDepth();
        m_event = START_TAG;
        break;
      }

      if (chunkType == CHUNK_XML_END_TAG) {
        m_namespaceUri = m_reader.readInt();
        m_name = m_reader.readInt();
        m_event = END_TAG;
        m_decreaseDepth = true;
        break;
      }

      if (chunkType == CHUNK_XML_TEXT) {
        m_name = m_reader.readInt();
        /* ? */ m_reader.skipInt();
        /* ? */ m_reader.skipInt();
        m_event = TEXT;
        break;
      }
    }
  }
Example #7
0
  private static Pkge readPackage(ARSCFile file, IntReader reader) throws IOException {
    Pkge pkge = new Pkge();
    pkge.file = file;

    ReadUtil.readCheckType(reader, PACKAGE_CHUNK_TYPE);
    /* size */ reader.skipInt();
    pkge.id = reader.readInt();
    {
      final int nameLength = 128;
      StringBuilder name = new StringBuilder(16);
      int i = 0;
      for (; i != nameLength; ) {
        ++i;
        int ch = reader.readShort();
        if (ch == 0) {
          break;
        }
        name.append((char) ch);
      }
      reader.skip((nameLength - i) * 2);
      reader.skip((nameLength * 2) % 4);
      pkge.name = name.toString();
    }

    /* signature? */ reader.skipInt();
    int assetCount = reader.readInt();
    /* idNamesOffset */ reader.skipInt();
    /* idNamesCount */ reader.skipInt();

    pkge.assetNames = StringBlock.read(reader);
    pkge.resourceNames = StringBlock.read(reader);
    pkge.assets = new Asset[assetCount];

    ArrayList contents = new ArrayList();
    int assetsRead = 0;
    Asset currentAsset = null;
    while (reader.available() != 0) {
      int chunkType = reader.readInt();
      if (chunkType != CONTENT_CHUNK_TYPE) {
        if (currentAsset != null) {
          currentAsset.contents = new Content[contents.size()];
          contents.toArray(currentAsset.contents);
          contents.clear();
        }
      }
      if (chunkType == ASSET_CHUNK_TYPE) {
        currentAsset = readAsset(reader, pkge);
        pkge.assets[assetsRead] = currentAsset;
        assetsRead += 1;
      } else if (chunkType == CONTENT_CHUNK_TYPE) {
        if (currentAsset == null) {
          throw new IOException("Invalid chunk sequence: content read before asset.");
        }
        contents.add(readContent(reader, currentAsset));
      } else {
        throw new IOException("Unexpected chunk type (" + chunkType + ").");
      }
    }
    if (currentAsset != null) {
      currentAsset.contents = new Content[contents.size()];
      contents.toArray(currentAsset.contents);
      contents.clear();
    }
    if (assetsRead != assetCount) {
      throw new IOException("Not all assets where read (" + (assetCount - assetsRead) + " left).");
    }
    return pkge;
  }