/** * Add data to the internal collection of data. This function is used by the data: scheme, about: * scheme and http/https schemes. * * @param data A byte array containing the content. * @param length The length of data. IMPORTANT: as this is called from network thread, can't call * native directly */ public void data(byte[] data, int length) { if (Config.LOGV) { Log.v(LOGTAG, "LoadListener.data(): url: " + url()); } if (ignoreCallbacks()) { return; } // Decode base64 data // Note: It's fine that we only decode base64 here and not in the other // data call because the only caller of the stream version is not // base64 encoded. if ("base64".equalsIgnoreCase(mTransferEncoding)) { if (length < data.length) { byte[] trimmedData = new byte[length]; System.arraycopy(data, 0, trimmedData, 0, length); data = trimmedData; } data = Base64.decodeBase64(data); length = data.length; } // Synchronize on mData because commitLoad may write mData to WebCore // and we don't want to replace mData or mDataLength at the same time // as a write. boolean sendMessage = false; synchronized (mDataBuilder) { sendMessage = mDataBuilder.isEmpty(); mDataBuilder.append(data, 0, length); } if (sendMessage) { // Send a message whenever data comes in after a write to WebCore sendMessageInternal(obtainMessage(MSG_CONTENT_DATA)); } }
/** Commit the load. It should be ok to call repeatedly but only before tearDown is called. */ private void commitLoad() { if (mCancelled) return; // Give the data to WebKit now PerfChecker checker = new PerfChecker(); ByteArrayBuilder.Chunk c; while (true) { c = mDataBuilder.getFirstChunk(); if (c == null) break; if (c.mLength != 0) { if (mCacheResult != null) { try { mCacheResult.outStream.write(c.mArray, 0, c.mLength); } catch (IOException e) { mCacheResult = null; } } nativeAddData(c.mArray, c.mLength); } mDataBuilder.releaseChunk(c); checker.responseAlert("res nativeAddData"); } }
/** * http://android-essential-devtopics.blogspot.com/2013/02/sending-bit-image-to-epson-printer.html * * @author Oleg Morozov 02/21/2013 (via public domain) * @author Tres Finocchiaro 10/01/2013 * @param b */ private void appendEpsonSlices(ByteArrayBuilder builder) { // BitSet dots = data.getDots(); // outputStream.write(PrinterCommands.INIT); // So we have our bitmap data sitting in a bit array called "dots." // This is one long array of 1s (black) and 0s (white) pixels arranged // as if we had scanned the bitmap from top to bottom, left to right. // The printer wants to see these arranged in bytes stacked three high. // So, essentially, we need to read 24 bits for x = 0, generate those // bytes, and send them to the printer, then keep increasing x. If our // image is more than 24 dots high, we have to send a second bit image // command to draw the next slice of 24 dots in the image. // Set the line spacing to 24 dots, the height of each "stripe" of the // image that we're drawing. If we don't do this, and we need to // draw the bitmap in multiple passes, then we'll end up with some // whitespace between slices of the image since the default line // height--how much the printer moves on a newline--is 30 dots. builder.append(new byte[] {0x1B, 0x33, 24}); // OK. So, starting from x = 0, read 24 bits down and send that data // to the printer. The offset variable keeps track of our global 'y' // position in the image. For example, if we were drawing a bitmap // that is 48 pixels high, then this while loop will execute twice, // once for each pass of 24 dots. On the first pass, the offset is // 0, and on the second pass, the offset is 24. We keep making // these 24-dot stripes until we've execute past the height of the // bitmap. int offset = 0; while (offset < getHeight()) { // The third and fourth parameters to the bit image command are // 'nL' and 'nH'. The 'L' and the 'H' refer to 'low' and 'high', respectively. // All 'n' really is is the width of the image that we're about to draw. // Since the width can be greater than 255 dots, the parameter has to // be split across two bytes, which is why the documentation says the // width is 'nL' + ('nH' * 256). // builder.append(new byte[] {0x1B, 0x2A, 33, -128, 0}); byte nL = (byte) ((int) (getWidth() % 256)); byte nH = (byte) ((int) (getWidth() / 256)); builder.append(new byte[] {0x1B, 0x2A, (byte) dotDensity, nL, nH}); for (int x = 0; x < getWidth(); ++x) { // Remember, 24 dots = 24 bits = 3 bytes. // The 'k' variable keeps track of which of those // three bytes that we're currently scribbling into. for (int k = 0; k < 3; ++k) { byte slice = 0; // A byte is 8 bits. The 'b' variable keeps track // of which bit in the byte we're recording. for (int b = 0; b < 8; ++b) { // Calculate the y position that we're currently // trying to draw. We take our offset, divide it // by 8 so we're talking about the y offset in // terms of bytes, add our current 'k' byte // offset to that, multiple by 8 to get it in terms // of bits again, and add our bit offset to it. int y = (((offset / 8) + k) * 8) + b; // Calculate the location of the pixel we want in the bit array. // It'll be at (y * width) + x. int i = (y * getWidth()) + x; // If the image (or this stripe of the image) // is shorter than 24 dots, pad with zero. boolean v = false; if (i < getImageAsBooleanArray().length) { v = getImageAsBooleanArray()[i]; } // Finally, store our bit in the byte that we're currently // scribbling to. Our current 'b' is actually the exact // opposite of where we want it to be in the byte, so // subtract it from 7, shift our bit into place in a temp // byte, and OR it with the target byte to get it into there. slice |= (byte) ((v ? 1 : 0) << (7 - b)); } // Phew! Write the damn byte to the buffer builder.append(new byte[] {slice}); } } // We're done with this 24-dot high pass. Render a newline // to bump the print head down to the next line // and keep on trucking. offset += 24; builder.append(new byte[] {10}); } // Restore the line spacing to the default of 30 dots. builder.append(new byte[] {0x1B, 0x33, 30}); }