diff options
author | Tor Lillqvist <tlillqvist@suse.com> | 2012-06-05 17:05:56 +0300 |
---|---|---|
committer | Tor Lillqvist <tlillqvist@suse.com> | 2012-06-05 17:17:41 +0300 |
commit | 8ae077379edcdbf7bf106121593361d2486aacb7 (patch) | |
tree | 207e4b9d516a56e2ebbf500cd80baca2d275894c /android/experimental | |
parent | 92f23297c93dc105e2ffd9ff09c0dafff1ee0fd3 (diff) |
Use 32bpp bitmaps on Android (and iOS)
Modify DocumentLoader correspondingly. Take Android bug 32588 into
account.
Ideal would be to extend the XDevice stuff, or something, so that one
could hand it a pre-allocated RGBA buffer into which the
drawing/rendering would go. Then one could get rid of the silly
convert-to-BMP phase, which prefixes the bitmap data with BMP and DIB
headers (and thus, I guess, has to copy and allocate another
copy). Will see.
Change-Id: I4597cd933db8faa8105dc8f19638d712d5d2238a
Diffstat (limited to 'android/experimental')
-rw-r--r-- | android/experimental/DocumentLoader/Makefile | 2 | ||||
-rw-r--r-- | android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java | 195 |
2 files changed, 113 insertions, 84 deletions
diff --git a/android/experimental/DocumentLoader/Makefile b/android/experimental/DocumentLoader/Makefile index 1e9cebcbe8be..8129948b2e76 100644 --- a/android/experimental/DocumentLoader/Makefile +++ b/android/experimental/DocumentLoader/Makefile @@ -262,8 +262,10 @@ uninstall: $(ANDROID_SDK_HOME)/platform-tools/adb uninstall $(APP_PACKAGE) run: +# /data/local/tmp/sample-document.odt adb shell am start -n org.libreoffice.android.examples/.DocumentLoader -e input /assets/test1.odt + clean: properties $(ANT) clean rm -rf assets libs $(SODEST) $(OBJLOCAL) diff --git a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java b/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java index 8ead7a96240d..4f027ecf7c1a 100644 --- a/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java +++ b/android/experimental/DocumentLoader/src/org/libreoffice/android/examples/DocumentLoader.java @@ -150,18 +150,21 @@ public class DocumentLoader Log.i(TAG, " " + t.getTypeName()); } - static void dumpBytes(String imageName, byte[] image) + static void dumpBytes(String name, byte[] bytes, int offset) { - if (image == null) { - Log.i(TAG, imageName + " is null"); + if (bytes == null) { + Log.i(TAG, name + " is null"); return; } - Log.i(TAG, imageName + " is " + image.length + " bytes"); + Log.i(TAG, name + ":"); - for (int i = 0; i < Math.min(image.length, 160); i += 16) { + if (offset != 0) + Log.i(TAG, " (offset " + offset + ")"); + + for (int i = offset; i < Math.min(bytes.length, offset+160); i += 16) { String s = ""; - for (int j = i; j < Math.min(image.length, i+16); j++) - s = s + String.format(" %02x", image[j]); + for (int j = i; j < Math.min(bytes.length, i+16); j++) + s = s + String.format(" %02x", bytes[j]); Log.i(TAG, s); } @@ -185,8 +188,8 @@ public class DocumentLoader Bootstrap.dlopen("libswdlo.so"); Bootstrap.dlopen("libswlo.so"); - Log.i(TAG, "Sleeping NOW"); - Thread.sleep(20000); + // Log.i(TAG, "Sleeping NOW"); + // Thread.sleep(20000); XComponentContext xContext = null; @@ -225,113 +228,137 @@ public class DocumentLoader Log.i(TAG, "xCompLoader is" + (xCompLoader!=null ? " not" : "") + " null"); - // Load the wanted document(s) - String[] inputs = input.split(":"); - for (int i = 0; i < inputs.length; i++) { - PropertyValue loadProps[] = new PropertyValue[3]; - loadProps[0] = new PropertyValue(); - loadProps[0].Name = "Hidden"; - loadProps[0].Value = new Boolean(true); - loadProps[1] = new PropertyValue(); - loadProps[1].Name = "ReadOnly"; - loadProps[1].Value = new Boolean(true); - loadProps[2] = new PropertyValue(); - loadProps[2].Name = "Preview"; - loadProps[2].Value = new Boolean(true); + // Load the wanted document - String sUrl = "file://" + inputs[i]; + PropertyValue loadProps[] = new PropertyValue[3]; + loadProps[0] = new PropertyValue(); + loadProps[0].Name = "Hidden"; + loadProps[0].Value = new Boolean(true); + loadProps[1] = new PropertyValue(); + loadProps[1].Name = "ReadOnly"; + loadProps[1].Value = new Boolean(true); + loadProps[2] = new PropertyValue(); + loadProps[2].Name = "Preview"; + loadProps[2].Value = new Boolean(true); - Log.i(TAG, "Attempting to load " + sUrl); + String sUrl = "file://" + input; - Object oDoc = - xCompLoader.loadComponentFromURL - (sUrl, "_blank", 0, loadProps); + Log.i(TAG, "Attempting to load " + sUrl); - dumpUNOObject("oDoc", oDoc); + Object oDoc = + xCompLoader.loadComponentFromURL + (sUrl, "_blank", 0, loadProps); - Object toolkit = xMCF.createInstanceWithContext - ("com.sun.star.awt.Toolkit", xContext); + dumpUNOObject("oDoc", oDoc); - dumpUNOObject("toolkit", toolkit); + Object toolkit = xMCF.createInstanceWithContext + ("com.sun.star.awt.Toolkit", xContext); - XToolkit xToolkit = (XToolkit) - UnoRuntime.queryInterface(XToolkit.class, toolkit); + dumpUNOObject("toolkit", toolkit); - XDevice device = xToolkit.createScreenCompatibleDevice(1024, 1024); + XToolkit xToolkit = (XToolkit) + UnoRuntime.queryInterface(XToolkit.class, toolkit); - dumpUNOObject("device", device); + XDevice device = xToolkit.createScreenCompatibleDevice(1024, 1024); - // I guess the XRenderable thing might be what we want to use, - // having the code pretend it is printing? + dumpUNOObject("device", device); - XRenderable renderBabe = (XRenderable) - UnoRuntime.queryInterface(XRenderable.class, oDoc); + XRenderable renderBabe = (XRenderable) + UnoRuntime.queryInterface(XRenderable.class, oDoc); - PropertyValue renderProps[] = - new PropertyValue[3]; - renderProps[0] = new PropertyValue(); - renderProps[0].Name = "IsPrinter"; - renderProps[0].Value = new Boolean(true); - renderProps[1] = new PropertyValue(); - renderProps[1].Name = "RenderDevice"; - renderProps[1].Value = device; - renderProps[2] = new PropertyValue(); - renderProps[2].Name = "View"; - renderProps[2].Value = new MyXController(); + PropertyValue renderProps[] = + new PropertyValue[3]; + renderProps[0] = new PropertyValue(); + renderProps[0].Name = "IsPrinter"; + renderProps[0].Value = new Boolean(true); + renderProps[1] = new PropertyValue(); + renderProps[1].Name = "RenderDevice"; + renderProps[1].Value = device; + renderProps[2] = new PropertyValue(); + renderProps[2].Name = "View"; + renderProps[2].Value = new MyXController(); - Log.i(TAG, "getRendererCount: " + renderBabe.getRendererCount(oDoc, renderProps)); + Log.i(TAG, "getRendererCount: " + renderBabe.getRendererCount(oDoc, renderProps)); - renderBabe.render(0, oDoc, renderProps); + renderBabe.render(0, oDoc, renderProps); - XBitmap bitmap = device.createBitmap(0, 0, 1024, 1024); + XBitmap bitmap = device.createBitmap(0, 0, 1024, 1024); - byte[] image = bitmap.getDIB(); + byte[] image = bitmap.getDIB(); - dumpBytes("image", image); + dumpBytes("image", image, 0); - byte[] mask = bitmap.getMaskDIB(); + if (image[0] != 'B' || image[1] != 'M') { + Log.wtf(TAG, "getDIB() didn't return a BMP file"); + return; + } - dumpBytes("mask", mask); + ByteBuffer imagebb = ByteBuffer.wrap(image); + imagebb.order(ByteOrder.LITTLE_ENDIAN); - if (image[0] != 'B' || image[1] != 'M') { - Log.e(TAG, "getDIB() didn't return a BMP file"); - return; - } + if (imagebb.getInt(0x0e) != 40) { + Log.wtf(TAG, "getDIB() didn't return a DIB with BITMAPINFOHEADER"); + return; + } - ByteBuffer imagebb = ByteBuffer.wrap(image); - imagebb.order(ByteOrder.LITTLE_ENDIAN); + if (imagebb.getShort(0x1c) != 32) { + Log.wtf(TAG, "getDIB() didn't return a 32 bpp DIB"); + return; + } - if (imagebb.getInt(0x0e) != 40) { - Log.e(TAG, "getDIB() didn't return a DIB with BITMAPINFOHEADER"); - return; - } + if (imagebb.getInt(0x1e) != 3) { + Log.wtf(TAG, "getDIB() didn't return a BI_BITFIELDS DIB"); + return; + } - if (imagebb.getShort(0x1c) != 24) { - Log.e(TAG, "getDIB() didn't return a 24 bpp DIB"); - return; - } + int offset = imagebb.getInt(0x0a); + int width = imagebb.getInt(0x12); + int height = imagebb.getInt(0x16); + + Log.i(TAG, String.format("offset: %d (%x), width: %d, height: %d", offset, offset, width, height)); + + Bootstrap.force_full_alpha(image, offset, width * height * 4); - if (imagebb.getInt(0x1e) != 0) { - Log.e(TAG, "getDIB() didn't return a BI_RGB DIB"); - return; + Log.i(TAG, "after force_full_alpha:"); + dumpBytes("image", image, 0); + + for (int i = offset; i < offset + width * height * 4; i++) { + if (image[i] != -1) { + int o = offset + (((i-offset) - 4) / 4) * 4; + dumpBytes("First non-ones bytes", image, o); + o += 160; + dumpBytes("...", image, o); + o += 160; + dumpBytes("...", image, o); + o += 160; + dumpBytes("...", image, o); + break; } + } - int width = imagebb.getInt(0x12); - int height = imagebb.getInt(0x16); + ImageView imageView = new GestureImageView(this); + imageView.setScaleY(-1); - ByteBuffer argb = ByteBuffer.allocateDirect(width * height * 4); + Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + imagebb.position(offset); - Bootstrap.twiddle_BGR_to_RGBA(image, imagebb.getInt(0x0a), width, height, argb); + // Thanks to Android bug 32588, the above is not enough to get the + // below copyPixelsFromBuffer() to start copying at offset, it + // will (as of Android 4.0.3) copy from position zero anyway. So + // instead have to shift (compact) the bloody buffer. + imagebb.compact(); - ImageView imageView = new GestureImageView(this); + // I don't understand what the compact() documentation says about + // the new position; so explicitly put it at zero, in case + // runnning on an Android where copyPixelsFromBuffer() *does* take + // the position into account. + imagebb.position(0); - Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bm.copyPixelsFromBuffer(argb); + bm.copyPixelsFromBuffer(imagebb); - imageView.setImageBitmap(bm); + imageView.setImageBitmap(bm); - setContentView(imageView); - } + setContentView(imageView); } catch (Exception e) { e.printStackTrace(System.err); |