mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-06 03:50:19 +02:00
images support in native code (in progress)
This commit is contained in:
parent
e33d26bc6c
commit
cd7c0f3c45
16 changed files with 99 additions and 121 deletions
|
@ -1,4 +1,4 @@
|
|||
#APP_ABI := armeabi
|
||||
APP_ABI := armeabi
|
||||
#APP_ABI := armeabi armeabi-v7a x86 mips mips-r2 mips-r2-sf
|
||||
APP_ABI := all
|
||||
#APP_ABI := all
|
||||
APP_STL := stlport_static
|
||||
|
|
|
@ -214,16 +214,16 @@ void BookReader::insertEndOfTextParagraph() {
|
|||
insertEndParagraph(ZLTextParagraph::END_OF_TEXT_PARAGRAPH);
|
||||
}
|
||||
|
||||
void BookReader::addImageReference(const std::string &id, short vOffset) {
|
||||
void BookReader::addImageReference(const std::string &id, short vOffset, bool isCover) {
|
||||
if (myCurrentTextModel != 0) {
|
||||
mySectionContainsRegularContents = true;
|
||||
if (myTextParagraphExists) {
|
||||
flushTextBufferToParagraph();
|
||||
myCurrentTextModel->addImage(id, vOffset);
|
||||
myCurrentTextModel->addImage(id, vOffset, isCover);
|
||||
} else {
|
||||
beginParagraph();
|
||||
myCurrentTextModel->addControl(IMAGE, true);
|
||||
myCurrentTextModel->addImage(id, vOffset);
|
||||
myCurrentTextModel->addImage(id, vOffset, isCover);
|
||||
myCurrentTextModel->addControl(IMAGE, false);
|
||||
endParagraph();
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
void addHyperlinkLabel(const std::string &label, int paragraphNumber);
|
||||
void addFixedHSpace(unsigned char length);
|
||||
|
||||
void addImageReference(const std::string &id, short vOffset = 0);
|
||||
void addImageReference(const std::string &id, short vOffset, bool isCover);
|
||||
void addImage(const std::string &id, shared_ptr<const ZLImage> image);
|
||||
|
||||
void beginContentsParagraph(int referenceNumber = -1);
|
||||
|
|
|
@ -120,7 +120,7 @@ void RtfBookReader::switchDestination(DestinationType destination, bool on) {
|
|||
void RtfBookReader::insertImage(const std::string &mimeType, const std::string &fileName, size_t startOffset, size_t size) {
|
||||
std::string id;
|
||||
ZLStringUtil::appendNumber(id, myImageIndex++);
|
||||
myBookReader.addImageReference(id);
|
||||
myBookReader.addImageReference(id, 0, false);
|
||||
//myBookReader.addImage(id, new RtfImage(mimeType, fileName, startOffset, size));
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include <ZLUnicodeUtil.h>
|
||||
|
||||
class ZLCachedMemoryAllocator {
|
||||
|
||||
public:
|
||||
|
@ -33,8 +35,9 @@ public:
|
|||
|
||||
void flush();
|
||||
|
||||
static void writeUInt16(char *ptr, uint16_t value);
|
||||
static void writeUInt32(char *ptr, uint32_t value);
|
||||
static char *writeUInt16(char *ptr, uint16_t value);
|
||||
static char *writeUInt32(char *ptr, uint32_t value);
|
||||
static char *writeString(char *ptr, const ZLUnicodeUtil::Ucs2String &str);
|
||||
static uint16_t readUInt16(const char *ptr);
|
||||
static uint32_t readUInt32(const char *ptr);
|
||||
|
||||
|
@ -69,18 +72,28 @@ inline const std::string &ZLCachedMemoryAllocator::fileExtension() const { retur
|
|||
inline size_t ZLCachedMemoryAllocator::blocksNumber() const { return myPool.size(); }
|
||||
inline size_t ZLCachedMemoryAllocator::currentBytesOffset() const { return myOffset; }
|
||||
|
||||
inline void ZLCachedMemoryAllocator::writeUInt16(char *ptr, uint16_t value) {
|
||||
inline char *ZLCachedMemoryAllocator::writeUInt16(char *ptr, uint16_t value) {
|
||||
*ptr++ = value;
|
||||
*ptr = value >> 8;
|
||||
*ptr++ = value >> 8;
|
||||
return ptr;
|
||||
}
|
||||
inline void ZLCachedMemoryAllocator::writeUInt32(char *ptr, uint32_t value) {
|
||||
inline char *ZLCachedMemoryAllocator::writeUInt32(char *ptr, uint32_t value) {
|
||||
*ptr++ = value;
|
||||
value >>= 8;
|
||||
*ptr++ = value;
|
||||
value >>= 8;
|
||||
*ptr++ = value;
|
||||
*ptr = value >> 8;
|
||||
value >>= 8;
|
||||
*ptr++ = value;
|
||||
return ptr;
|
||||
}
|
||||
inline char *ZLCachedMemoryAllocator::writeString(char *ptr, const ZLUnicodeUtil::Ucs2String &str) {
|
||||
const size_t size = str.size();
|
||||
writeUInt16(ptr, size);
|
||||
memcpy(ptr + 2, &str.front(), size * 2);
|
||||
return ptr + size * 2 + 2;
|
||||
}
|
||||
|
||||
inline uint16_t ZLCachedMemoryAllocator::readUInt16(const char *ptr) {
|
||||
const uint8_t *tmp = (const uint8_t*)ptr;
|
||||
return *tmp + ((uint16_t)*(tmp + 1) << 8);
|
||||
|
|
|
@ -45,65 +45,26 @@ void ZLImageMapWriter::addImage(const std::string &id, const ZLImage &image) {
|
|||
}
|
||||
|
||||
void ZLImageMapWriter::addSingleImageEntry(const ZLSingleImage &image) {
|
||||
ZLUnicodeUtil::Ucs2String ucs2mime;
|
||||
ZLUnicodeUtil::utf8ToUcs2(ucs2mime, image.mimeType());
|
||||
const size_t mimeSize = ucs2mime.size() * 2;
|
||||
const ZLFileImage &fileImage = (const ZLFileImage&)image;
|
||||
|
||||
const size_t len = 4 + mimeSize;
|
||||
char *address = myAllocator.allocate(len);
|
||||
ZLUnicodeUtil::Ucs2String mime;
|
||||
ZLUnicodeUtil::utf8ToUcs2(mime, image.mimeType());
|
||||
ZLUnicodeUtil::Ucs2String path;
|
||||
ZLUnicodeUtil::utf8ToUcs2(path, fileImage.file().path());
|
||||
ZLUnicodeUtil::Ucs2String encoding;
|
||||
|
||||
char *ptr = address;
|
||||
*ptr++ = image.kind();
|
||||
const size_t len = 16 + mime.size() * 2 + path.size() * 2 + encoding.size() * 2;
|
||||
char *ptr = myAllocator.allocate(len);
|
||||
|
||||
*ptr++ = 0;//image.kind();
|
||||
*ptr++ = 0; // multi ? 1 : 0
|
||||
ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2mime.size());
|
||||
memcpy(ptr + 2, &ucs2mime.front(), mimeSize);
|
||||
|
||||
switch (image.kind()) {
|
||||
case ZLSingleImage::BASE64_ENCODED_IMAGE:
|
||||
case ZLSingleImage::REGULAR_IMAGE:
|
||||
{
|
||||
const shared_ptr<std::string> data = image.stringData();
|
||||
size_t length = data.isNull() ? 0 : data->length();
|
||||
size_t dataSize = (length + 1) / 2;
|
||||
ptr = ZLCachedMemoryAllocator::writeString(ptr, mime);
|
||||
ptr = ZLCachedMemoryAllocator::writeString(ptr, path);
|
||||
ptr = ZLCachedMemoryAllocator::writeString(ptr, encoding);
|
||||
|
||||
const size_t newlen = len + 4 + dataSize * 2;
|
||||
address = myAllocator.reallocateLast(address, newlen);
|
||||
ptr = address + len;
|
||||
|
||||
ZLCachedMemoryAllocator::writeUInt32(ptr, dataSize);
|
||||
ptr += 4;
|
||||
if (length > 0) {
|
||||
memcpy(ptr, data->data(), length);
|
||||
ptr += length;
|
||||
if (length % 2) {
|
||||
*ptr++ = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ZLSingleImage::FILE_IMAGE:
|
||||
{
|
||||
const ZLFileImage &fileImage = (const ZLFileImage&)image;
|
||||
|
||||
ZLUnicodeUtil::Ucs2String ucs2path;
|
||||
ZLUnicodeUtil::utf8ToUcs2(ucs2path, fileImage.file().path());
|
||||
const size_t pathSize = ucs2path.size() * 2;
|
||||
|
||||
const size_t newlen = len + 10 + pathSize;
|
||||
address = myAllocator.reallocateLast(address, newlen);
|
||||
ptr = address + len;
|
||||
|
||||
ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.offset());
|
||||
ptr += 4;
|
||||
ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.size());
|
||||
ptr += 4;
|
||||
ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2path.size());
|
||||
ptr += 2;
|
||||
memcpy(ptr, &ucs2path.front(), pathSize);
|
||||
ptr += pathSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.offset());
|
||||
ptr = ZLCachedMemoryAllocator::writeUInt32(ptr, fileImage.size());
|
||||
}
|
||||
|
||||
void ZLImageMapWriter::addMultiImageEntry(const ZLMultiImage &image) {
|
||||
|
|
|
@ -346,7 +346,7 @@ void ZLTextModel::addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyper
|
|||
++myParagraphLengths.back();
|
||||
}
|
||||
|
||||
void ZLTextModel::addImage(const std::string &id, short vOffset) {
|
||||
void ZLTextModel::addImage(const std::string &id, short vOffset, bool isCover) {
|
||||
checkUtf8Text();
|
||||
|
||||
ZLUnicodeUtil::Ucs2String ucs2id;
|
||||
|
@ -354,12 +354,13 @@ void ZLTextModel::addImage(const std::string &id, short vOffset) {
|
|||
|
||||
const size_t len = ucs2id.size() * 2;
|
||||
|
||||
myLastEntryStart = myAllocator.allocate(len + 6);
|
||||
myLastEntryStart = myAllocator.allocate(len + 8);
|
||||
*myLastEntryStart = ZLTextParagraphEntry::IMAGE_ENTRY;
|
||||
*(myLastEntryStart + 1) = 0;
|
||||
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 2, vOffset);
|
||||
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 4, ucs2id.size());
|
||||
memcpy(myLastEntryStart + 6, &ucs2id.front(), len);
|
||||
ZLCachedMemoryAllocator::writeUInt16(myLastEntryStart + 6 + len, isCover ? 1 : 0);
|
||||
myParagraphs.back()->addEntry(myLastEntryStart);
|
||||
++myParagraphLengths.back();
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
void addHyperlinkControl(ZLTextKind textKind, ZLHyperlinkType hyperlinkType, const std::string &label);
|
||||
void addText(const std::string &text);
|
||||
void addText(const std::vector<std::string> &text);
|
||||
void addImage(const std::string &id, short vOffset);
|
||||
void addImage(const std::string &id, short vOffset, bool isCover);
|
||||
void addFixedHSpace(unsigned char length);
|
||||
void addBidiReset();
|
||||
|
||||
|
|
|
@ -68,14 +68,12 @@ public class ImageViewActivity extends Activity {
|
|||
|
||||
final Uri uri = intent.getData();
|
||||
if (ZLFileImage.SCHEME.equals(uri.getScheme())) {
|
||||
final ZLFileImage image = ZLFileImage.byUrlPath(uri.getPath());
|
||||
if (image == null) {
|
||||
// TODO: error message (?)
|
||||
finish();
|
||||
}
|
||||
try {
|
||||
final String[] data = uri.getPath().split("\000");
|
||||
final ZLFileImage image = new ZLFileImage(
|
||||
MimeType.IMAGE_AUTO,
|
||||
ZLFile.createFileByPath(data[0]),
|
||||
Integer.parseInt(data[1]),
|
||||
Integer.parseInt(data[2])
|
||||
);
|
||||
final ZLImageData imageData = ZLImageManager.Instance().getImageData(image);
|
||||
myBitmap = ((ZLAndroidImageData)imageData).getFullSizeBitmap();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -84,9 +84,11 @@ public class NativeFormatPlugin extends FormatPlugin {
|
|||
|
||||
protected native ZLImage readCoverInternal(ZLFile file);
|
||||
|
||||
/*
|
||||
public static ZLImage createImage(String mimeType, String fileName, int offset, int length) {
|
||||
return new ZLFileImage(MimeType.get(mimeType), ZLFile.createFileByPath(fileName), offset, length);
|
||||
}
|
||||
*/
|
||||
|
||||
// FIXME: temporary implementation; implement as a native code
|
||||
@Override
|
||||
|
|
|
@ -182,7 +182,7 @@ public class MobipocketHtmlBookReader extends HtmlReader {
|
|||
if (length <= 0) {
|
||||
break;
|
||||
}
|
||||
addImage("" + (index + 1), new ZLFileImage(MimeType.IMAGE_AUTO, Model.Book.File, offset, length));
|
||||
addImage(String.valueOf(index + 1), new ZLFileImage(MimeType.IMAGE_AUTO, Model.Book.File, ZLFileImage.ENCODING_NONE, offset, length));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ public class MobipocketPlugin extends JavaFormatPlugin {
|
|||
if (start >= 0) {
|
||||
int len = myMobipocketStream.getImageLength(coverIndex);
|
||||
if (len > 0) {
|
||||
return new ZLFileImage(MimeType.IMAGE_AUTO, file, start, len);
|
||||
return new ZLFileImage(MimeType.IMAGE_AUTO, file, ZLFileImage.ENCODING_NONE, start, len);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -61,7 +61,7 @@ public abstract class ZLBase64EncodedImage extends ZLSingleImage {
|
|||
try {
|
||||
decode();
|
||||
final File file = new File(decodedFileName());
|
||||
return ZLFileImage.SCHEME + "://" + decodedFileName() + "\0000\000" + (int)file.length();
|
||||
return ZLFileImage.SCHEME + "://" + decodedFileName() + "\000\0000\000" + (int)file.length();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,23 +28,44 @@ import org.geometerplus.zlibrary.core.util.SliceInputStream;
|
|||
public class ZLFileImage extends ZLSingleImage {
|
||||
public static final String SCHEME = "imagefile";
|
||||
|
||||
public static final String ENCODING_NONE = "";
|
||||
public static final String ENCODING_HEX = "hex";
|
||||
|
||||
public static ZLFileImage byUrlPath(String urlPath) {
|
||||
try {
|
||||
final String[] data = urlPath.split("\000");
|
||||
return new ZLFileImage(
|
||||
MimeType.IMAGE_AUTO,
|
||||
ZLFile.createFileByPath(data[0]),
|
||||
data[1],
|
||||
Integer.parseInt(data[2]),
|
||||
Integer.parseInt(data[3])
|
||||
);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final ZLFile myFile;
|
||||
private final String myEncoding;
|
||||
private final int myOffset;
|
||||
private final int myLength;
|
||||
|
||||
public ZLFileImage(MimeType mimeType, ZLFile file, int offset, int length) {
|
||||
public ZLFileImage(MimeType mimeType, ZLFile file, String encoding, int offset, int length) {
|
||||
super(mimeType);
|
||||
myFile = file;
|
||||
myEncoding = encoding;
|
||||
myOffset = offset;
|
||||
myLength = length;
|
||||
}
|
||||
|
||||
public ZLFileImage(MimeType mimeType, ZLFile file) {
|
||||
this(mimeType, file, 0, (int)file.size());
|
||||
this(mimeType, file, ENCODING_NONE, 0, (int)file.size());
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return SCHEME + "://" + myFile.getPath() + "\000" + myOffset + "\000" + myLength;
|
||||
return SCHEME + "://" + myFile.getPath() + "\000" + myEncoding + "\000" + myOffset + "\000" + myLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,12 +24,6 @@ import java.io.InputStream;
|
|||
import org.geometerplus.zlibrary.core.util.MimeType;
|
||||
|
||||
public abstract class ZLSingleImage implements ZLImage {
|
||||
public interface Kind {
|
||||
byte REGULAR_IMAGE = 1;
|
||||
byte FILE_IMAGE = 2;
|
||||
byte BASE64_ENCODED_IMAGE = 3;
|
||||
};
|
||||
|
||||
private final MimeType myMimeType;
|
||||
|
||||
public ZLSingleImage(final MimeType mimeType) {
|
||||
|
|
|
@ -38,12 +38,11 @@ class ZLImageMapReader {
|
|||
data = myStorage.block(++index);
|
||||
offset = 0;
|
||||
}
|
||||
final byte kind = (byte)data[offset];
|
||||
final boolean multi = ((byte)(data[offset] >> 8)) != 0;
|
||||
if (multi) {
|
||||
return readMultiImage(index, offset + 1, data);
|
||||
} else {
|
||||
return readSingleImage(index, offset + 1, data, kind);
|
||||
return readSingleImage(index, offset + 1, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,37 +51,26 @@ class ZLImageMapReader {
|
|||
return null;
|
||||
}
|
||||
|
||||
private ZLImage readSingleImage(int index, int offset, char[] data, byte kind) {
|
||||
final short mimeLength = (short)data[offset++];
|
||||
final String mime = new String(data, offset, mimeLength);
|
||||
offset += mimeLength;
|
||||
private ZLImage readSingleImage(int index, int offset, char[] data) {
|
||||
short len = (short)data[offset++];
|
||||
final String mime = new String(data, offset, len);
|
||||
offset += len;
|
||||
|
||||
switch (kind) {
|
||||
case ZLSingleImage.Kind.BASE64_ENCODED_IMAGE:
|
||||
case ZLSingleImage.Kind.REGULAR_IMAGE:
|
||||
{
|
||||
final int dataSize = (int)data[offset] + (((int)data[offset + 1]) << 16);
|
||||
offset += 2;
|
||||
final String path = myStorage.fileName(index);
|
||||
return new ZLFileImage(
|
||||
MimeType.get(mime), ZLFile.createFileByPath(path), offset * 2, dataSize * 2
|
||||
);
|
||||
}
|
||||
case ZLSingleImage.Kind.FILE_IMAGE:
|
||||
{
|
||||
final int fileOffset = (int)data[offset] + (((int)data[offset + 1]) << 16);
|
||||
offset += 2;
|
||||
final int fileSize = (int)data[offset] + (((int)data[offset + 1]) << 16);
|
||||
offset += 2;
|
||||
final short pathLength = (short)data[offset++];
|
||||
final String path = new String(data, offset, pathLength);
|
||||
offset += pathLength;
|
||||
return new ZLFileImage(
|
||||
MimeType.get(mime), ZLFile.createFileByPath(path), fileOffset, fileSize
|
||||
);
|
||||
}
|
||||
}
|
||||
len = (short)data[offset++];
|
||||
final String path = new String(data, offset, len);
|
||||
offset += len;
|
||||
|
||||
return null;
|
||||
len = (short)data[offset++];
|
||||
final String encoding = new String(data, offset, len);
|
||||
offset += len;
|
||||
|
||||
final int fileOffset = (int)data[offset] + (((int)data[offset + 1]) << 16);
|
||||
offset += 2;
|
||||
final int fileSize = (int)data[offset] + (((int)data[offset + 1]) << 16);
|
||||
offset += 2;
|
||||
|
||||
return new ZLFileImage(
|
||||
MimeType.get(mime), ZLFile.createFileByPath(path), encoding, fileOffset, fileSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue