mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-06 03:50:19 +02:00
full-screen cover images
Conflicts: ChangeLog
This commit is contained in:
parent
d30ba1a9d8
commit
9787e2db11
22 changed files with 307 additions and 118 deletions
|
@ -6,6 +6,7 @@
|
|||
* Option for disabling button lights in Android 3/4 has been introduced
|
||||
* Plural forms support in resources has been implemented
|
||||
* Image in image view can be scaled using pinch (Android 2+)
|
||||
* Full-screen cover images
|
||||
|
||||
===== 1.2.6 (Dec 19, 2011) =====
|
||||
* Android 3.*, 4.*: bottom buttons are hidden during book reading
|
||||
|
|
|
@ -238,7 +238,6 @@ public final class FBReader extends ZLAndroidActivity {
|
|||
);
|
||||
|
||||
final TipsManager manager = TipsManager.Instance();
|
||||
System.err.println("TIPS: " + manager.requiredAction());
|
||||
switch (manager.requiredAction()) {
|
||||
case Initialize:
|
||||
startActivity(new Intent(TipsActivity.INITIALIZE_ACTION, null, this, TipsActivity.class));
|
||||
|
|
|
@ -388,21 +388,21 @@ public class BookReader {
|
|||
beginContentsParagraph(-1);
|
||||
}
|
||||
|
||||
public final void addImageReference(String ref) {
|
||||
addImageReference(ref, (short)0);
|
||||
public final void addImageReference(String ref, boolean isCover) {
|
||||
addImageReference(ref, (short)0, isCover);
|
||||
}
|
||||
|
||||
public final void addImageReference(String ref, short vOffset) {
|
||||
public final void addImageReference(String ref, short vOffset, boolean isCover) {
|
||||
final ZLTextWritableModel textModel = myCurrentTextModel;
|
||||
if (textModel != null) {
|
||||
mySectionContainsRegularContents = true;
|
||||
if (myTextParagraphExists) {
|
||||
flushTextBufferToParagraph();
|
||||
textModel.addImage(ref, vOffset);
|
||||
textModel.addImage(ref, vOffset, isCover);
|
||||
} else {
|
||||
beginParagraph(ZLTextParagraph.Kind.TEXT_PARAGRAPH);
|
||||
textModel.addControl(FBTextKind.IMAGE, true);
|
||||
textModel.addImage(ref, vOffset);
|
||||
textModel.addImage(ref, vOffset, isCover);
|
||||
textModel.addControl(FBTextKind.IMAGE, false);
|
||||
endParagraph();
|
||||
}
|
||||
|
|
|
@ -375,9 +375,11 @@ public final class FB2Reader extends ZLXMLReaderAdapter {
|
|||
} catch (NumberFormatException e) {
|
||||
}
|
||||
imgRef = imgRef.substring(1);
|
||||
if (!imgRef.equals(myCoverImageReference) ||
|
||||
myParagraphsBeforeBodyNumber != myBookReader.Model.BookTextModel.getParagraphsNumber()) {
|
||||
myBookReader.addImageReference(imgRef, offset);
|
||||
final boolean isCoverImage =
|
||||
myParagraphsBeforeBodyNumber ==
|
||||
myBookReader.Model.BookTextModel.getParagraphsNumber();
|
||||
if (!imgRef.equals(myCoverImageReference) || !isCoverImage) {
|
||||
myBookReader.addImageReference(imgRef, offset, myInsideCoverpage || isCoverImage);
|
||||
}
|
||||
if (myInsideCoverpage) {
|
||||
myCoverImageReference = imgRef;
|
||||
|
|
|
@ -53,6 +53,7 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespaces {
|
|||
private String myOPFSchemePrefix;
|
||||
private String myFilePrefix;
|
||||
private String myNCXTOCFileName;
|
||||
private String myCoverFileName;
|
||||
|
||||
OEBBookReader(BookModel model) {
|
||||
myModelReader = new BookReader(model);
|
||||
|
@ -86,12 +87,16 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespaces {
|
|||
myModelReader.setMainTextModel();
|
||||
myModelReader.pushKind(FBTextKind.REGULAR);
|
||||
|
||||
int count = 0;
|
||||
for (String name : myHtmlFileNames) {
|
||||
final ZLFile xhtmlFile = ZLFile.createFileByPath(myFilePrefix + name);
|
||||
if (xhtmlFile == null) {
|
||||
// NPE fix: null for bad attributes in .opf XML file
|
||||
return false;
|
||||
}
|
||||
if (count++ == 0 && xhtmlFile.getPath().equals(myCoverFileName)) {
|
||||
continue;
|
||||
}
|
||||
final XHTMLReader reader = new XHTMLReader(myModelReader, myFileNumbers);
|
||||
final String referenceName = reader.getFileAlias(MiscUtil.archiveEntryName(xhtmlFile.getPath()));
|
||||
|
||||
|
@ -175,6 +180,7 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespaces {
|
|||
private static final String ITEMREF = "itemref";
|
||||
private static final String ITEM = "item";
|
||||
|
||||
private static final String COVER = "cover";
|
||||
private static final String COVER_IMAGE = "other.ms-coverimage-standard";
|
||||
|
||||
private static final int READ_NONE = 0;
|
||||
|
@ -225,12 +231,25 @@ class OEBBookReader extends ZLXMLReaderAdapter implements XMLNamespaces {
|
|||
if (title != null) {
|
||||
myGuideTOC.add(new Reference(title, href));
|
||||
}
|
||||
if (type != null && COVER_IMAGE.equals(type)) {
|
||||
myModelReader.setMainTextModel();
|
||||
if (COVER.equals(type)) {
|
||||
final ZLFile imageFile = ZLFile.createFileByPath(myFilePrefix + href);
|
||||
myCoverFileName = imageFile.getPath();
|
||||
final String imageName = imageFile.getLongName();
|
||||
myModelReader.addImageReference(imageName, (short)0);
|
||||
final ZLFileImage image = XHTMLImageFinder.getCoverImage(imageFile);
|
||||
if (image != null) {
|
||||
myModelReader.setMainTextModel();
|
||||
myModelReader.addImageReference(imageName, (short)0, true);
|
||||
myModelReader.addImage(imageName, image);
|
||||
myModelReader.insertEndOfSectionParagraph();
|
||||
}
|
||||
} else if (COVER_IMAGE.equals(type)) {
|
||||
final ZLFile imageFile = ZLFile.createFileByPath(myFilePrefix + href);
|
||||
myCoverFileName = imageFile.getPath();
|
||||
final String imageName = imageFile.getLongName();
|
||||
myModelReader.setMainTextModel();
|
||||
myModelReader.addImageReference(imageName, (short)0, true);
|
||||
myModelReader.addImage(imageName, new ZLFileImage(MimeType.IMAGE_AUTO, imageFile));
|
||||
myModelReader.insertEndOfSectionParagraph();
|
||||
}
|
||||
}
|
||||
} else if (myState == READ_TOUR && SITE == tag) {
|
||||
|
|
|
@ -28,58 +28,15 @@ import org.geometerplus.zlibrary.core.xml.*;
|
|||
import org.geometerplus.fbreader.formats.util.MiscUtil;
|
||||
|
||||
class OEBCoverBackgroundReader extends ZLXMLReaderAdapter implements XMLNamespaces {
|
||||
private class XHTMLImageFinder extends ZLXMLReaderAdapter {
|
||||
@Override
|
||||
public boolean processNamespaces() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startElementHandler(String tag, ZLStringMap attributes) {
|
||||
tag = tag.toLowerCase();
|
||||
String href = null;
|
||||
if ("img".equals(tag)) {
|
||||
href = attributes.getValue("src");
|
||||
} else if ("image".equals(tag)) {
|
||||
href = getAttributeValue(attributes, XLink, "href");
|
||||
}
|
||||
|
||||
if (href != null) {
|
||||
myImage = new ZLFileImage(
|
||||
MimeType.IMAGE_AUTO,
|
||||
ZLFile.createFileByPath(myXHTMLPathPrefix + MiscUtil.decodeHtmlReference(href))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ZLFileImage myImage;
|
||||
private String myPathPrefix;
|
||||
private String myXHTMLPathPrefix;
|
||||
private String myCoverXHTML;
|
||||
private boolean myReadGuide;
|
||||
|
||||
public ZLFileImage readCover(ZLFile file) {
|
||||
myPathPrefix = MiscUtil.htmlDirectoryPrefix(file);
|
||||
myReadGuide = false;
|
||||
myImage = null;
|
||||
myCoverXHTML = null;
|
||||
read(file);
|
||||
if (myCoverXHTML != null) {
|
||||
final ZLFile coverFile = ZLFile.createFileByPath(myCoverXHTML);
|
||||
if (coverFile != null) {
|
||||
final String ext = coverFile.getExtension();
|
||||
if ("gif".equals(ext) || "jpg".equals(ext) || "jpeg".equals(ext)) {
|
||||
myImage = new ZLFileImage(MimeType.IMAGE_AUTO, coverFile);
|
||||
} else {
|
||||
myXHTMLPathPrefix = MiscUtil.htmlDirectoryPrefix(coverFile);
|
||||
new XHTMLImageFinder().read(coverFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return myImage;
|
||||
}
|
||||
|
||||
|
@ -98,7 +55,9 @@ class OEBCoverBackgroundReader extends ZLXMLReaderAdapter implements XMLNamespac
|
|||
if (COVER == type) {
|
||||
final String href = attributes.getValue("href");
|
||||
if (href != null) {
|
||||
myCoverXHTML = myPathPrefix + MiscUtil.decodeHtmlReference(href);
|
||||
final ZLFile coverFile =
|
||||
ZLFile.createFileByPath(myPathPrefix + MiscUtil.decodeHtmlReference(href));
|
||||
myImage = XHTMLImageFinder.getCoverImage(coverFile);
|
||||
return true;
|
||||
}
|
||||
} else if (COVER_IMAGE == type) {
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.formats.oeb;
|
||||
|
||||
import org.geometerplus.zlibrary.core.constants.XMLNamespaces;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
import org.geometerplus.zlibrary.core.image.ZLFileImage;
|
||||
import org.geometerplus.zlibrary.core.util.MimeType;
|
||||
import org.geometerplus.zlibrary.core.xml.*;
|
||||
|
||||
import org.geometerplus.fbreader.formats.util.MiscUtil;
|
||||
|
||||
class XHTMLImageFinder extends ZLXMLReaderAdapter {
|
||||
static ZLFileImage getCoverImage(ZLFile coverFile) {
|
||||
if (coverFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String ext = coverFile.getExtension();
|
||||
if ("gif".equals(ext) || "jpg".equals(ext) || "jpeg".equals(ext)) {
|
||||
return new ZLFileImage(MimeType.IMAGE_AUTO, coverFile);
|
||||
} else {
|
||||
return new XHTMLImageFinder().readImage(coverFile);
|
||||
}
|
||||
}
|
||||
|
||||
private String myXHTMLPathPrefix;
|
||||
private ZLFileImage myImage;
|
||||
|
||||
ZLFileImage readImage(ZLFile file) {
|
||||
myXHTMLPathPrefix = MiscUtil.htmlDirectoryPrefix(file);
|
||||
myImage = null;
|
||||
read(file);
|
||||
return myImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processNamespaces() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startElementHandler(String tag, ZLStringMap attributes) {
|
||||
tag = tag.toLowerCase();
|
||||
String href = null;
|
||||
if ("img".equals(tag)) {
|
||||
href = attributes.getValue("src");
|
||||
} else if ("image".equals(tag)) {
|
||||
href = getAttributeValue(attributes, XMLNamespaces.XLink, "href");
|
||||
}
|
||||
|
||||
if (href != null) {
|
||||
myImage = new ZLFileImage(
|
||||
MimeType.IMAGE_AUTO,
|
||||
ZLFile.createFileByPath(myXHTMLPathPrefix + MiscUtil.decodeHtmlReference(href))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -72,10 +72,10 @@ public class MobipocketHtmlBookReader extends HtmlReader {
|
|||
final int index = Integer.parseInt(recIndex.toString());
|
||||
if (paragraphIsOpen()) {
|
||||
endParagraph();
|
||||
addImageReference("" + index);
|
||||
addImageReference("" + index, false);
|
||||
beginParagraph();
|
||||
} else {
|
||||
addImageReference("" + index);
|
||||
addImageReference("" + index, false);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
|
|
@ -341,7 +341,7 @@ public class PluckerBookReader extends BookReader {
|
|||
break;
|
||||
case 0x1A:
|
||||
safeBeginParagraph();
|
||||
addImageReference(fromNumber(twoBytes(ptr, cur + 1)), (short) 0);
|
||||
addImageReference(fromNumber(twoBytes(ptr, cur + 1)), (short)0, false);
|
||||
break;
|
||||
case 0x22:
|
||||
if (!myParagraphStarted) {
|
||||
|
@ -380,7 +380,7 @@ public class PluckerBookReader extends BookReader {
|
|||
case 0x53: // color setting is ignored
|
||||
break;
|
||||
case 0x5C:
|
||||
addImageReference(fromNumber(twoBytes(ptr, cur + 3)), (short) 0);
|
||||
addImageReference(fromNumber(twoBytes(ptr, cur + 3)), (short)0, false);
|
||||
break;
|
||||
case 0x60: // underlined text is ignored
|
||||
break;
|
||||
|
|
|
@ -48,7 +48,7 @@ class XHTMLTagImageAction extends XHTMLTagAction {
|
|||
modelReader.endParagraph();
|
||||
}
|
||||
final String imageName = imageFile.getLongName();
|
||||
modelReader.addImageReference(imageName, (short)0);
|
||||
modelReader.addImageReference(imageName, (short)0, false);
|
||||
modelReader.addImage(imageName, new ZLFileImage(MimeType.IMAGE_AUTO, imageFile));
|
||||
if (flag) {
|
||||
modelReader.beginParagraph();
|
||||
|
|
|
@ -29,82 +29,104 @@ final class DummyPaintContext extends ZLPaintContext {
|
|||
DummyPaintContext() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(ZLFile wallpaperFile, boolean doMirror) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(ZLColor color) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZLColor getBackgroundColor() {
|
||||
return new ZLColor(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFontInternal(String family, int size, boolean bold, boolean italic, boolean underline) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(ZLColor color) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLineColor(ZLColor color, int style) {
|
||||
}
|
||||
@Override
|
||||
public void setLineWidth(int width) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFillColor(ZLColor color, int alpha, int style) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return 1;
|
||||
}
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStringWidth(char[] string, int offset, int length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSpaceWidthInternal() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStringHeightInternal() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDescentInternal() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(int x, int y, char[] string, int offset, int length) {
|
||||
}
|
||||
|
||||
public int imageWidth(ZLImageData image) {
|
||||
return 1;
|
||||
@Override
|
||||
public Size imageSize(ZLImageData image, Size maxSize, ScalingType scaling) {
|
||||
return null;
|
||||
}
|
||||
public int imageHeight(ZLImageData image) {
|
||||
return 1;
|
||||
}
|
||||
public void drawImage(int x, int y, ZLImageData image) {
|
||||
@Override
|
||||
public void drawImage(int x, int y, ZLImageData image, Size maxSize, ScalingType scaling) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x0, int y0, int x1, int y1) {
|
||||
}
|
||||
@Override
|
||||
public void fillRectangle(int x0, int y0, int x1, int y1) {
|
||||
}
|
||||
@Override
|
||||
public void drawFilledCircle(int x, int y, int r) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon(int[] xs, int ys[]) {
|
||||
}
|
||||
@Override
|
||||
public void drawPolygonalLine(int[] xs, int ys[]) {
|
||||
}
|
||||
@Override
|
||||
public void drawOutline(int[] xs, int ys[]) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String realFontFamilyName(String fontFamily) {
|
||||
return fontFamily;
|
||||
}
|
||||
@Override
|
||||
protected void fillFamiliesList(ArrayList<String> families) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,9 +145,35 @@ abstract public class ZLPaintContext {
|
|||
}
|
||||
abstract public void drawString(int x, int y, char[] string, int offset, int length);
|
||||
|
||||
abstract public int imageWidth(ZLImageData image);
|
||||
abstract public int imageHeight(ZLImageData image);
|
||||
abstract public void drawImage(int x, int y, ZLImageData image);
|
||||
public static final class Size {
|
||||
public final int Width;
|
||||
public final int Height;
|
||||
|
||||
public Size(int w, int h) {
|
||||
Width = w;
|
||||
Height = h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Size)) {
|
||||
return false;
|
||||
}
|
||||
final Size s = (Size)other;
|
||||
return Width == s.Width && Height == s.Height;
|
||||
}
|
||||
}
|
||||
public static enum ScalingType {
|
||||
OriginalSize,
|
||||
IntegerCoefficient,
|
||||
FitMaximum
|
||||
}
|
||||
|
||||
abstract public Size imageSize(ZLImageData image, Size maxSize, ScalingType scaling);
|
||||
abstract public void drawImage(int x, int y, ZLImageData image, Size maxSize, ScalingType scaling);
|
||||
|
||||
abstract public void drawLine(int x0, int y0, int x1, int y1);
|
||||
abstract public void fillRectangle(int x0, int y0, int x1, int y1);
|
||||
|
|
|
@ -26,11 +26,13 @@ public final class ZLImageEntry {
|
|||
private final ZLImageMap myImageMap;
|
||||
public final String Id;
|
||||
public final short VOffset;
|
||||
public final boolean IsCover;
|
||||
|
||||
ZLImageEntry(ZLImageMap imageMap, String id, short vOffset) {
|
||||
ZLImageEntry(ZLImageMap imageMap, String id, short vOffset, boolean isCover) {
|
||||
myImageMap = imageMap;
|
||||
Id = id;
|
||||
VOffset = vOffset;
|
||||
IsCover = isCover;
|
||||
}
|
||||
|
||||
public ZLImage getImage() {
|
||||
|
|
|
@ -162,7 +162,8 @@ public class ZLTextPlainModel implements ZLTextModel {
|
|||
final short len = (short)data[dataOffset++];
|
||||
final String id = new String(data, dataOffset, len);
|
||||
dataOffset += len;
|
||||
myImageEntry = new ZLImageEntry(myImageMap, id, vOffset);
|
||||
final boolean isCover = data[dataOffset++] != 0;
|
||||
myImageEntry = new ZLImageEntry(myImageMap, id, vOffset, isCover);
|
||||
break;
|
||||
}
|
||||
case ZLTextParagraph.Entry.FIXED_HSPACE:
|
||||
|
|
|
@ -28,7 +28,7 @@ public interface ZLTextWritableModel extends ZLTextModel {
|
|||
|
||||
//void addControl(ZLTextForcedControlEntry entry);
|
||||
void addHyperlinkControl(byte textKind, byte hyperlinkType, String id);
|
||||
void addImage(String id, short vOffset);
|
||||
void addImage(String id, short vOffset, boolean isCover);
|
||||
void addFixedHSpace(short length);
|
||||
|
||||
void stopReading();
|
||||
|
|
|
@ -129,16 +129,18 @@ public final class ZLTextWritablePlainModel extends ZLTextPlainModel implements
|
|||
myBlockOffset = blockOffset + labelLength;
|
||||
}
|
||||
|
||||
public void addImage(String id, short vOffset) {
|
||||
public void addImage(String id, short vOffset, boolean isCover) {
|
||||
final int len = id.length();
|
||||
final char[] block = getDataBlock(3 + len);
|
||||
final char[] block = getDataBlock(4 + len);
|
||||
++myParagraphLengths[myParagraphsNumber - 1];
|
||||
int blockOffset = myBlockOffset;
|
||||
block[blockOffset++] = (char)ZLTextParagraph.Entry.IMAGE;
|
||||
block[blockOffset++] = (char)vOffset;
|
||||
block[blockOffset++] = (char)len;
|
||||
id.getChars(0, len, block, blockOffset);
|
||||
myBlockOffset = blockOffset + len;
|
||||
blockOffset += len;
|
||||
block[blockOffset++] = (char)(isCover ? 1 : 0);
|
||||
myBlockOffset = blockOffset;
|
||||
}
|
||||
|
||||
public void addFixedHSpace(short length) {
|
||||
|
|
|
@ -25,10 +25,12 @@ public final class ZLTextImageElement extends ZLTextElement {
|
|||
public final String Id;
|
||||
public final ZLImageData ImageData;
|
||||
public final String URI;
|
||||
public final boolean IsCover;
|
||||
|
||||
ZLTextImageElement(String id, ZLImageData imageData, String uri) {
|
||||
ZLTextImageElement(String id, ZLImageData imageData, String uri, boolean isCover) {
|
||||
Id = id;
|
||||
ImageData = imageData;
|
||||
URI = uri;
|
||||
IsCover = isCover;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ public final class ZLTextParagraphCursor {
|
|||
if (hyperlink != null) {
|
||||
hyperlink.addElementIndex(elements.size());
|
||||
}
|
||||
elements.add(new ZLTextImageElement(imageEntry.Id, data, image.getURI()));
|
||||
elements.add(new ZLTextImageElement(imageEntry.Id, data, image.getURI(), imageEntry.IsCover));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -779,7 +779,15 @@ public abstract class ZLTextView extends ZLTextViewBase {
|
|||
? getSelectedForegroundColor() : getTextColor(getTextStyle().Hyperlink)
|
||||
);
|
||||
} else if (element instanceof ZLTextImageElement) {
|
||||
context.drawImage(areaX, areaY, ((ZLTextImageElement)element).ImageData);
|
||||
final ZLTextImageElement imageElement = (ZLTextImageElement)element;
|
||||
context.drawImage(
|
||||
areaX, areaY,
|
||||
imageElement.ImageData,
|
||||
getTextAreaSize(),
|
||||
imageElement.IsCover
|
||||
? ZLPaintContext.ScalingType.FitMaximum
|
||||
: ZLPaintContext.ScalingType.IntegerCoefficient
|
||||
);
|
||||
} else if (element == ZLTextElement.HSpace) {
|
||||
final int cw = context.getSpaceWidth();
|
||||
/*
|
||||
|
|
|
@ -57,6 +57,10 @@ abstract class ZLTextViewBase extends ZLView {
|
|||
public abstract ZLColor getTextColor(ZLTextHyperlink hyperlink);
|
||||
public abstract ZLColor getHighlightingColor();
|
||||
|
||||
ZLPaintContext.Size getTextAreaSize() {
|
||||
return new ZLPaintContext.Size(getTextAreaWidth(), getTextAreaHeight());
|
||||
}
|
||||
|
||||
int getTextAreaHeight() {
|
||||
return myContext.getHeight() - getTopMargin() - getBottomMargin();
|
||||
}
|
||||
|
@ -116,7 +120,15 @@ abstract class ZLTextViewBase extends ZLView {
|
|||
if (element instanceof ZLTextWord) {
|
||||
return getWordWidth((ZLTextWord)element, charIndex);
|
||||
} else if (element instanceof ZLTextImageElement) {
|
||||
return myContext.imageWidth(((ZLTextImageElement)element).ImageData);
|
||||
final ZLTextImageElement imageElement = (ZLTextImageElement)element;
|
||||
final ZLPaintContext.Size size = myContext.imageSize(
|
||||
imageElement.ImageData,
|
||||
getTextAreaSize(),
|
||||
imageElement.IsCover
|
||||
? ZLPaintContext.ScalingType.FitMaximum
|
||||
: ZLPaintContext.ScalingType.IntegerCoefficient
|
||||
);
|
||||
return size != null ? size.Width : 0;
|
||||
} else if (element == ZLTextElement.IndentElement) {
|
||||
return myTextStyle.getFirstLineIndentDelta();
|
||||
} else if (element instanceof ZLTextFixedHSpaceElement) {
|
||||
|
@ -129,7 +141,15 @@ abstract class ZLTextViewBase extends ZLView {
|
|||
if (element instanceof ZLTextWord) {
|
||||
return getWordHeight();
|
||||
} else if (element instanceof ZLTextImageElement) {
|
||||
return myContext.imageHeight(((ZLTextImageElement)element).ImageData) +
|
||||
final ZLTextImageElement imageElement = (ZLTextImageElement)element;
|
||||
final ZLPaintContext.Size size = myContext.imageSize(
|
||||
imageElement.ImageData,
|
||||
getTextAreaSize(),
|
||||
imageElement.IsCover
|
||||
? ZLPaintContext.ScalingType.FitMaximum
|
||||
: ZLPaintContext.ScalingType.IntegerCoefficient
|
||||
);
|
||||
return (size != null ? size.Height : 0) +
|
||||
Math.max(myContext.getStringHeight() * (myTextStyle.getLineSpacePercent() - 100) / 100, 3);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -23,13 +23,14 @@ import android.graphics.Bitmap;
|
|||
import android.graphics.BitmapFactory;
|
||||
|
||||
import org.geometerplus.zlibrary.core.image.ZLImageData;
|
||||
import org.geometerplus.zlibrary.core.view.ZLPaintContext;
|
||||
|
||||
public abstract class ZLAndroidImageData implements ZLImageData {
|
||||
private Bitmap myBitmap;
|
||||
private int myRealWidth;
|
||||
private int myRealHeight;
|
||||
private int myLastRequestedWidth = -1;
|
||||
private int myLastRequestedHeight = -1;
|
||||
private ZLPaintContext.Size myLastRequestedSize = null;
|
||||
private ZLPaintContext.ScalingType myLastRequestedScaling = ZLPaintContext.ScalingType.OriginalSize;
|
||||
|
||||
protected ZLAndroidImageData() {
|
||||
}
|
||||
|
@ -37,18 +38,23 @@ public abstract class ZLAndroidImageData implements ZLImageData {
|
|||
protected abstract Bitmap decodeWithOptions(BitmapFactory.Options options);
|
||||
|
||||
public Bitmap getFullSizeBitmap() {
|
||||
return getBitmap(0, 0, true);
|
||||
return getBitmap(null, ZLPaintContext.ScalingType.OriginalSize);
|
||||
}
|
||||
|
||||
public Bitmap getBitmap(int maxWidth, int maxHeight) {
|
||||
return getBitmap(maxWidth, maxHeight, false);
|
||||
return getBitmap(new ZLPaintContext.Size(maxWidth, maxHeight), ZLPaintContext.ScalingType.FitMaximum);
|
||||
}
|
||||
|
||||
private synchronized Bitmap getBitmap(int maxWidth, int maxHeight, boolean ignoreSize) {
|
||||
if (!ignoreSize && (maxWidth <= 0 || maxHeight <= 0)) {
|
||||
return null;
|
||||
public Bitmap getBitmap(ZLPaintContext.Size maxSize, ZLPaintContext.ScalingType scaling) {
|
||||
if (scaling != ZLPaintContext.ScalingType.OriginalSize) {
|
||||
if (maxSize == null || maxSize.Width <= 0 || maxSize.Height <= 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (maxWidth != myLastRequestedWidth || maxHeight != myLastRequestedHeight) {
|
||||
if (maxSize == null) {
|
||||
maxSize = new ZLPaintContext.Size(-1, -1);
|
||||
}
|
||||
if (!maxSize.equals(myLastRequestedSize) || scaling != myLastRequestedScaling) {
|
||||
if (myBitmap != null) {
|
||||
myBitmap.recycle();
|
||||
myBitmap = null;
|
||||
|
@ -63,34 +69,67 @@ public abstract class ZLAndroidImageData implements ZLImageData {
|
|||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
int coefficient = 1;
|
||||
if (!ignoreSize) {
|
||||
if (myRealHeight > maxHeight || myRealWidth > maxWidth) {
|
||||
if (scaling == ZLPaintContext.ScalingType.IntegerCoefficient) {
|
||||
if (myRealHeight > maxSize.Height || myRealWidth > maxSize.Width) {
|
||||
coefficient = 1 + Math.max(
|
||||
(myRealHeight - 1) / maxHeight,
|
||||
(myRealWidth - 1) / maxWidth
|
||||
(myRealHeight - 1) / maxSize.Height,
|
||||
(myRealWidth - 1) / maxSize.Width
|
||||
);
|
||||
}
|
||||
}
|
||||
options.inSampleSize = coefficient;
|
||||
myBitmap = decodeWithOptions(options);
|
||||
if (myBitmap != null) {
|
||||
if (!ignoreSize) {
|
||||
final int bWidth = myBitmap.getWidth();
|
||||
final int bHeight = myBitmap.getHeight();
|
||||
if (bWidth > 0 && bHeight > 0 && (bWidth > maxWidth || bHeight > maxHeight)) {
|
||||
final int w, h;
|
||||
if (bWidth * maxHeight > bHeight * maxWidth) {
|
||||
w = maxWidth;
|
||||
h = Math.max(1, bHeight * maxWidth / bWidth);
|
||||
} else {
|
||||
h = maxHeight;
|
||||
w = Math.max(1, bWidth * maxHeight / bHeight);
|
||||
switch (scaling) {
|
||||
case OriginalSize:
|
||||
break;
|
||||
case FitMaximum:
|
||||
{
|
||||
final int bWidth = myBitmap.getWidth();
|
||||
final int bHeight = myBitmap.getHeight();
|
||||
if (bWidth > 0 && bHeight > 0 &&
|
||||
bWidth != maxSize.Width && bHeight != maxSize.Height) {
|
||||
final int w, h;
|
||||
if (bWidth * maxSize.Height > bHeight * maxSize.Width) {
|
||||
w = maxSize.Width;
|
||||
h = Math.max(1, bHeight * w / bWidth);
|
||||
} else {
|
||||
h = maxSize.Height;
|
||||
w = Math.max(1, bWidth * h / bHeight);
|
||||
}
|
||||
final Bitmap scaled =
|
||||
Bitmap.createScaledBitmap(myBitmap, w, h, false);
|
||||
if (scaled != null) {
|
||||
myBitmap = scaled;
|
||||
}
|
||||
}
|
||||
myBitmap = Bitmap.createScaledBitmap(myBitmap, w, h, false);
|
||||
break;
|
||||
}
|
||||
case IntegerCoefficient:
|
||||
{
|
||||
final int bWidth = myBitmap.getWidth();
|
||||
final int bHeight = myBitmap.getHeight();
|
||||
if (bWidth > 0 && bHeight > 0 &&
|
||||
(bWidth > maxSize.Width || bHeight > maxSize.Height)) {
|
||||
final int w, h;
|
||||
if (bWidth * maxSize.Height > bHeight * maxSize.Width) {
|
||||
w = maxSize.Width;
|
||||
h = Math.max(1, bHeight * w / bWidth);
|
||||
} else {
|
||||
h = maxSize.Height;
|
||||
w = Math.max(1, bWidth * h / bHeight);
|
||||
}
|
||||
final Bitmap scaled =
|
||||
Bitmap.createScaledBitmap(myBitmap, w, h, false);
|
||||
if (scaled != null) {
|
||||
myBitmap = scaled;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
myLastRequestedWidth = maxWidth;
|
||||
myLastRequestedHeight = maxHeight;
|
||||
myLastRequestedSize = maxSize;
|
||||
myLastRequestedScaling = scaling;
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -244,6 +244,7 @@ public final class ZLAndroidPaintContext extends ZLPaintContext {
|
|||
return myHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStringWidth(char[] string, int offset, int length) {
|
||||
boolean containsSoftHyphen = false;
|
||||
for (int i = offset; i < offset + length; ++i) {
|
||||
|
@ -266,15 +267,19 @@ public final class ZLAndroidPaintContext extends ZLPaintContext {
|
|||
return (int)(myTextPaint.measureText(corrected, 0, len) + 0.5f);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected int getSpaceWidthInternal() {
|
||||
return (int)(myTextPaint.measureText(" ", 0, 1) + 0.5f);
|
||||
}
|
||||
@Override
|
||||
protected int getStringHeightInternal() {
|
||||
return (int)(myTextPaint.getTextSize() + 0.5f);
|
||||
}
|
||||
@Override
|
||||
protected int getDescentInternal() {
|
||||
return (int)(myTextPaint.descent() + 0.5f);
|
||||
}
|
||||
@Override
|
||||
public void drawString(int x, int y, char[] string, int offset, int length) {
|
||||
boolean containsSoftHyphen = false;
|
||||
for (int i = offset; i < offset + length; ++i) {
|
||||
|
@ -298,23 +303,22 @@ public final class ZLAndroidPaintContext extends ZLPaintContext {
|
|||
}
|
||||
}
|
||||
|
||||
public int imageWidth(ZLImageData imageData) {
|
||||
Bitmap bitmap = ((ZLAndroidImageData)imageData).getBitmap(myWidth, myHeight);
|
||||
return ((bitmap != null) && !bitmap.isRecycled()) ? bitmap.getWidth() : 0;
|
||||
@Override
|
||||
public Size imageSize(ZLImageData imageData, Size maxSize, ScalingType scaling) {
|
||||
final Bitmap bitmap = ((ZLAndroidImageData)imageData).getBitmap(maxSize, scaling);
|
||||
return (bitmap != null && !bitmap.isRecycled())
|
||||
? new Size(bitmap.getWidth(), bitmap.getHeight()) : null;
|
||||
}
|
||||
|
||||
public int imageHeight(ZLImageData imageData) {
|
||||
Bitmap bitmap = ((ZLAndroidImageData)imageData).getBitmap(myWidth, myHeight);
|
||||
return ((bitmap != null) && !bitmap.isRecycled()) ? bitmap.getHeight() : 0;
|
||||
}
|
||||
|
||||
public void drawImage(int x, int y, ZLImageData imageData) {
|
||||
Bitmap bitmap = ((ZLAndroidImageData)imageData).getBitmap(myWidth, myHeight);
|
||||
if ((bitmap != null) && !bitmap.isRecycled()) {
|
||||
@Override
|
||||
public void drawImage(int x, int y, ZLImageData imageData, Size maxSize, ScalingType scaling) {
|
||||
final Bitmap bitmap = ((ZLAndroidImageData)imageData).getBitmap(maxSize, scaling);
|
||||
if (bitmap != null && !bitmap.isRecycled()) {
|
||||
myCanvas.drawBitmap(bitmap, x, y - bitmap.getHeight(), myFillPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x0, int y0, int x1, int y1) {
|
||||
final Canvas canvas = myCanvas;
|
||||
final Paint paint = myLinePaint;
|
||||
|
@ -325,6 +329,7 @@ public final class ZLAndroidPaintContext extends ZLPaintContext {
|
|||
paint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRectangle(int x0, int y0, int x1, int y1) {
|
||||
if (x1 < x0) {
|
||||
int swap = x1;
|
||||
|
@ -338,14 +343,17 @@ public final class ZLAndroidPaintContext extends ZLPaintContext {
|
|||
}
|
||||
myCanvas.drawRect(x0, y0, x1 + 1, y1 + 1, myFillPaint);
|
||||
}
|
||||
@Override
|
||||
public void drawFilledCircle(int x, int y, int r) {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public String realFontFamilyName(String fontFamily) {
|
||||
return AndroidFontUtil.realFontFamilyName(fontFamily);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillFamiliesList(ArrayList<String> families) {
|
||||
AndroidFontUtil.fillFamiliesList(families, false);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue