I've an Android app that needs to generate a PDF document with various data fetched from a database. Everything is working fine, included tables and checkboxes, that I generate with this snipped of code :
private PdfFormField WriteCheckbox(ref PdfContentByte pcb, float xPos, float yPos, string fldName, bool cbState)
{
yPos = yPos - 2f;
float cbDist = 1f;
Rectangle cbRect = new Rectangle(xPos, yPos, xPos + DEFAULT_CHECKBOX_SIZE, yPos + DEFAULT_CHECKBOX_SIZE);
RadioCheckField checkbox = new RadioCheckField(pcb.PdfWriter, cbRect, "", "");
checkbox.CheckType = RadioCheckField.TYPE_SQUARE;
checkbox.BorderColor = BaseColor.BLACK;
checkbox.BorderStyle = PdfBorderDictionary.STYLE_SOLID;
checkbox.BorderWidth = 0.5f;
checkbox.FieldName = fldName;
if(cbState)
{
pcb.SetLineWidth(1.2f);
pcb.MoveTo(xPos + DEFAULT_CHECKBOX_DISTANCE, yPos + cbDist);
pcb.LineTo(xPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1, yPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1);
pcb.MoveTo(xPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1, yPos + cbDist);
pcb.LineTo(xPos + DEFAULT_CHECKBOX_DISTANCE, yPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1);
}
pcb.Stroke();
return(checkbox.RadioField);
}
The resulting PDF is visualize correctly on the tablet (Nexus 7), but when I copy it con my PC and open if with Acrobat Reader all is at the correct place except the squares I draw to show the checkboxes. I can se the cross I draw inside the squares, but not the surrounding square. What is happening ?
This is the link to the pdf generated :
https://www.dropbox.com/s/p388bw7egjsbi80/curit_2015_2.pdf?dl=0
This is the link to the Nexus 7 screenshot showing the very same file :
Any hint would be very appreciated.
the squares I draw to show the checkboxes
Your code doesn't draw any squares.
What your code does, actually is surprising,
it creates numerous checkbox AcroForm form fields, none of them checked, none of them named, with a square visualization selection, and
it draws a cross in the page content in positions you seem to want to have appear checked.
So even if the created PDF was valid, it could irritate people, as they apparently could not de-select the pre-selected entries, merely select them a second time resulting in two overlapping crosses.
The reason why your checkbox borders only appear on some PDF viewers and not on others, is the same as explained in this answer to the question "iText - Java Android - Adding fields to existing pdf":
AcroForm form fields need to have a non-empty name. AcroForm forms contents are meant to be sent to some service for automatic evaluation, so they must be named and they must be distinguishable by their respective names.
Some PDF viewers recognize early that they couldn't properly handle fields with empty names and, therefore, don't even show them while other viewers recognize that later when trying to save or post the form, or don't recognize it at all, producing broken outputs.
But even after naming the boxes individually, you should decide whether you want to have AcroForm form fields or not. In the former case you would merely add properly named form fields and set them selected or not, and in the latter case you would draw complete checkbox appearances (not merely the check marks) in the page content and not use form fields at all.
Related
By code, I can make a button that inserts these 3 emojis into the text: ⚽️😈🐺
On many phones when the user clicks the button, though, the problem is that ⚽️😈🐺 displays as [X][X][X]. Or even worse, it displays only three empty spaces.
I would like to disable and hide my own built-in emoji-keypad on Android devices that do not display emojis correctly. Does anyone knows or have a tip on how to detect in code if a device has emoji support?
I have read that emoji is supported from android 4.1, but that is not my experience....
I just implemented a solution for this problem myself. The nice thing with Android is that it is open source so that when you come around problems like these, there's a good chance you can find an approach to help you.
In the Android Open Source Project, you can find a method where they use Paint.hasGlyph to detect whether a font exists for a given emoji. However, as this method is not available before API 23, they also do test renders and compare the result against the width of 'tofu' (the [x] character you mention in your post.)
There are some other failings with this approach, but it should be enough to get you started.
Google source:
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/emoji/EmojiCategory.java#441
https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/master/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
Based on Jason Gore answer:
For example create boolean canShowFlagEmoji:
private static boolean canShowFlagEmoji() {
Paint paint = new Paint();
String switzerland = "\uD83C\uDDE8\uD83C\uDDED"; // Here enter Surrogates of Emoji
try {
return paint.hasGlyph(switzerland);
} catch (NoSuchMethodError e) {
// Compare display width of single-codepoint emoji to width of flag emoji to determine
// whether flag is rendered as single glyph or two adjacent regional indicator symbols.
float flagWidth = paint.measureText(switzerland);
float standardWidth = paint.measureText("\uD83D\uDC27"); // U+1F427 Penguin
return flagWidth < standardWidth * 1.25;
// This assumes that a valid glyph for the flag emoji must be less than 1.25 times
// the width of the penguin.
}
}
And then in code whenever when you need to check if emoji is available:
if (canShowFlagEmoji()){
// Code when FlagEmoji is available
} else {
// And when not
}
Surrogates of emoji you can get here, when you click on detail.
An alternative option might be to include the Android "Emoji Compatibility" library, which would detect and add any required Emoji characters to apps running on Android 4.4 (API 19) and later: https://developer.android.com/topic/libraries/support-library/preview/emoji-compat.html
final Paint paint = new Paint();
final boolean isEmojiRendered;
if (VERSION.SDK_INT >= VERSION_CODES.M) {
isEmojiRendered = paint.hasGlyph(emoji);
}
else{
isEmojiRendered = paint.measureText(emoji) > 7;
}
The width > 7 part is particularly hacky, I would expect the value to be 0.0 for non-renderable emoji, but across a few devices, I found that the value actually ranged around 3.0 to 6.0 for non-renderable, and 12.0 to 15.0 for renderable. Your results may vary so you might want to test that. I believe the font size also has an effect on the output of measureText() so keep that in mind.
The second part was answerd by RogueBaneling here how can I check if my device is capable to render Emoji images correctly?
I am creating a PDF document with images and text in Android using iText. Each page has an image at the top followed by some text. On the first page the image is correctly aligned to the top margin of the page, but on subsequent pages there is a gap of approximately 10 points between the top margin and the top of the image.
Here's my code:
// Create PDF document object
float pageMargin = 72;
document = new com.itextpdf.text.Document(PageSize.A4, pageMargin, pageMargin, pageMargin, pageMargin);
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(myFile.getAbsoluteFile()));
document.open();
PdfContentByte cb = pdfWriter.getDirectContent();
for (PicturePage picPage : picPageList)
{
// Draw a border on the page
cb.moveTo(pageMargin, pageMargin);
cb.lineTo(pageMargin, (pageHeight - pageMargin));
cb.lineTo((pageWidth - pageMargin), (pageHeight - pageMargin));
cb.lineTo((pageWidth - pageMargin), pageMargin);
cb.lineTo(pageMargin, pageMargin);
cb.stroke();
// Get an image from the file system and scale to required size
String imgFileName = picPage.getImagePath();
image = Image.getInstance(imgFileName);
float fitWidth = 400;
float fitHeight = 300;
image.scaleToFit(fitWidth, fitHeight);
image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP);
document.add(image);
// Add the text to the page.
String theText = picPage.getText();
String[] arrParagraphs = theText.split("\n");
for (int i=0; i<arrParagraphs.length; i++)
{
String paragraphText = arrParagraphs[i];
Paragraph p = new Paragraph(paragraphText);
document.add(p);
}
// Start a new page
document.newPage();
}
I have tried various combinations of Image.ALIGN... and Image.TEXTWRAP but none of them remove the gap. I tried changing the order of placing the image and the border but no change. I have also tried removing the text and the border but the placement of the image is still the same.
Any ideas how to fix this?
Thanks,
Declan
I hope you won't mind if I share my opinion, but I don't like your code. There are much better ways to render images followed by a caption than the way you do it.
Now let me explain what causes the small gap to appear.
When you first create your document, the value of the leading is zero. (The leading is the distance between the baselines of two consecutive lines). This value changes as soon as you add the first object that defines a leading. In your case, this object is a Paragraph.
Although you do not define a leading explicitly, your paragraph uses a default font (Helvetica) and a default font size (12). The default leading is 1.5 times the font size (18).
Now when you go to the next page, that leading is used, introducing a small gap preceding the image. You could solve this by adding an empty Paragraph with leading 0 before triggering a new page:
document.add(new Paragraph(0));
(Add this before document.newPage();.)
However: if I were you, I'd throw away my code, and I'd add my image and my caption using a PdfPTable with a fixed width and fixed heights for the cells. You can add this table either using document.add(), or using the writeSelectedRows() method. Alternatively I could add the image at an absolute position and add the caption using a ColumnText object. There are many different ways to achieve what you want. The way you do it may work, but it's not optimal.
I want to display random objects on the screen i have one ball but the objects been generated are overlapping with the ball i want to get the coordinated of the ball and according to that only shift the random objects. I am trying like below snippet.
local ballX=ball.x
local ballY=ball.y
local xPos=generate_random(40,600)
local yPos=generate_random(40,920)
if(xPos>=ballX and xPos<=ballX) or (yPos>=ballY and yPos<=ballY) then
objplace.x=xPos+150
objplace.y=yPos+150
else
objplace.x=xPos
objplace.y=yPos
end
You aren't checking if the balls overlap, you are just checking if their centers are at the same position and if so you are shifting them. You need to take into consideration the overall area of the ball (thus its radius). To make this perfect, you would have to use some algebra/geometry (as the radius can be looked at at different angles like a right triangle, where the xPos would be the base length and yPos would be the side height).
Something simple (not perfect) would be like:
while((xPos>=(ballX + ballRadius) || xPos<=(ballX - ballRadius)) ||
(yPos>=(ballY + ballRadius) || yPos<=(ballY - ballRadius))){
xPos = xPos + 150;
yPos = yPos + 150;
}
objplace.x = xPos;
objplace.y = yPos;
Again this is VERY poorly done, there is little on the end of error checking and there are far more parameters that should be taken into account to make things perfect. If you really need me to crunch through it I can, but this would likely be a good project to hone your logical reasoning skills :)
I'm trying to make an epub reader
I want to do the pagination like fbreader does
Now I have source code of fbreader, but I don't know where it implement pagination
I have my implementation on other features
All I need from fbreader is the pagination
Is there anyone who have done the similar thing?
Thanks for your time to read this question.
ps: the pagination is to spit html file to pages, depending on the size of screen and size of font, and language is also in consideration, when changed the font size, the page number also changed. And epub file content is html format
It is fascinating code. I would love to see a translation of the original student project (but I presume the original document is in Russian). As this is a port of a C++ project it has an interesting style of coding in places.
The app keeps track of where you are in the book by using paragraph cursors (ZLTextParagraphCursor). This situation is comparative with database cursors and record pagination. The class that is responsible for serving up the current page and calculating the number of pages is ZLTextView.
As epubs are reflowable documents and not page-oriented there isn't really a concrete definition of a page - it just depends on where in the document you happen to be looking (paragraph, word, character) and with what display settings.
As McLaren says, FBReader doesn't implement pagination: It uses the ZLibrary, which is available from the same website as FBReader.
The original code uses this to calculate the current page number:
size_t ZLTextView::pageNumber() const {
if (textArea().isEmpty()) {
return 0;
}
std::vector<size_t>::const_iterator i = nextBreakIterator();
const size_t startIndex = (i != myTextBreaks.begin()) ? *(i - 1) : 0;
const size_t endIndex = (i != myTextBreaks.end()) ? *i :
textArea().model()->paragraphsNumber();
return (myTextSize[endIndex] - myTextSize[startIndex]) / 2048 + 1;
}
The Java version uses this function to compute the page number:
private synchronized int computeTextPageNumber(int textSize) {
if (myModel == null || myModel.getParagraphsNumber() == 0) {
return 1;
}
final float factor = 1.0f / computeCharsPerPage();
final float pages = textSize * factor;
return Math.max((int)(pages + 1.0f - 0.5f * factor), 1);
}
This is located in org.geometerplus.zlibrary.text.view.TextView
It's so simplistic, though, that you might as well implement your own.
How I understood it is that it uses 3 bitmaps previous current and next. What they have done is written a text which gets stored and read over this 3 bitmaps. Over as what you see on the top they calculate paragraphs data of how long it is for the scroll you see on the others example. You can start reverse engineering at android.view package class bitmapManager. This should explain everything about how they do their paging.
In a similar approach to this question, I am looking for a way to plot data points on to a view in Android. Preferably, a library which will do this for arbitrary-ranged input, as well as allow panning and zooming (via pinch or zoom bar).
Right now, I have subclass-ed a view which does the following normalization:
final int width = View.MeasureSpec.getSize(this.widthMeasureSpec);
final int height = View.MeasureSpec.getSize(this.heightMeasureSpec);
final float factorA = width / (maxA - minA);
final float factorS = height / (maxS - minS);
final float constFactorA = factorA * minA;
final float constFactorS = factorS * minS;
final int dataLength = data.length;
for (int i = 0; i < dataLength; ++i) {
if (i % 2 == 0)
_data[i] = _data[i] * factorA - constFactorA;
else
_data[i] = _data[i] * factorS - constFactorS;
}
and a call in onDraw() to the drawPoints method of a canvas (also, I update this.widthMeasureSpec and this.heightMeasureSpec in onMeasure()).
This is with minA/maxA as the bounds for my independent variable and minS/maxS as the bounds for my dependent variable.
This works fine for displaying the data, but I am hoping someone else has solved the problem of drawing the axes and panning/zooming.
I have ~150,000 data points, and I would prefer to keep these as floats to save half the memory. I don't know how big decimal numbers are in JavaScript, but I really don't want to resort to passing data in through JavaScript for the Google Charts API or an HTML-based solution for memory's sake.
I'm running this on a MyTouch 3g (the original, before 3.5mm jack and it's RAM upgrade), so performance is an issue. I'd like to release the final project under the GPLv3, so this excludes GraphView.
The graphs are of the same type as this, so any optimization by excluding points that are too close together to show up on screen would definitely make a difference.
sargas , do check android-misc-widgets.It contains a widget named PlotView with an example TestInterPolator.
Hope it helps.
Original post: Chart and Graph Library for Android
With the library GraphView it's possible to create a line and bar graphs.
GraphView is a library for Android to programmatically create flexible and nice-looking line and bar diagramms. It is easy to understand, to integrate and to customize it.
First checkout the library and integrate it into your project.
Source code is hosted on github.
GraphView library on github
It's also possible to let the graph be scalable (zooming) and scrollable. More information about this library on Original post: Chart and Graph Library for Android
This is how it will look like:
Then you can easily create it with a few lines of code (see snippet):
// graph with dynamically genereated horizontal and vertical labels
GraphView graphView = new LineGraphView(
this // context
, new GraphViewData[] {
new GraphViewData(1, 2.0d)
, new GraphViewData(2, 1.5d)
, new GraphViewData(2.5, 3.0d) // another frequency
, new GraphViewData(3, 2.5d)
, new GraphViewData(4, 1.0d)
, new GraphViewData(5, 3.0d)
} // data
, "GraphViewDemo" // heading
, null // dynamic labels
, null // dynamic labels
);
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
There is http://www.jfree.org/jfreechart/ which can suit your needs, it is a Java library so it should fit nice to Android. And it is LGPL.
If you can go the JavaScript route, then you could check out ProtoVis http://vis.stanford.edu/protovis/