Large SWT Image is not printed properly - printing

Hei, SWT Gurus, I have a pretty weird situation. The thing is, that I am trying to print gantt chart in my Eclipse RCP application. Gantt chart is quite long and sometimes high as well. Its dimensions are following: height=3008px (2 vertical pages), width > 20000px. My print area can fit something like 1400x2000 px. First of all, I am creating image out with my chart (image is OK, I can save it separately and see, that everything is there). However, in order to print it on the paper, I am printing it piece by piece (moving source X and Y positions respectively). This algorithm was working fine for some time, but now something strange happened:
When chart is not high enough and can fit on 1 vertical page, then it is printed normally, but when it is 2 vertical pages, then only second vertical page is printed and first one is left out. There are no errors, nor anything, that could help me. I thought, may be there is not enough heap memory, so I allocated -Xmx1014m space to my application, but it didn't helped. So, I am really lost, and can not find any solution or even an explanation to this problem. I was trying to simply print image by gc.drwImage(image, x, y), but is also printed me only the second half of it. I am also printing some text after every try of printing an image, and it is printed
The code, that is responsible for printing an image is following:
for (int verticalPageNumber = 0; verticalPageNumber <= pageCount.vGanttChartPagesCount; verticalPageNumber++) {
// horizontal position needs to be reset to 0 before printing next bunch of horizontal pages
int imgPieceSrcX = 0;
for (int horizontalPageNumber = 0; horizontalPageNumber <= pageCount.hGanttChartPagesCount; horizontalPageNumber++) {
// Calculate bounds for the next page
final Rectangle printBounds = PrintingUtils.calculatePrintBounds(printerClientArea, scaleFactor, verticalPageNumber, horizontalPageNumber);
if (shouldPrint(printer.getPrinterData(), currentPageNr)
&& nextPageHasSomethingToPrint(imgPieceSrcX, imgPieceSrcY, totalGanttChartArea.width, totalGanttChartArea.height)) {
printer.startPage();
final Transform printerTransform = PrintingUtils.setUpTransform(printer, printerClientArea, scaleFactor, gc, printBounds);
printHeader(gc, currentPageNr, printBounds);
imgPieceSrcY = printBounds.y;
final int imgPieceSrcHeight =
imgPieceSrcY + printBounds.height < ganttChartImage.getBounds().height ? printBounds.height : ganttChartImage.getBounds().height
- imgPieceSrcY;
final int imgPieceSrcWidth =
imgPieceSrcX + printBounds.width < ganttChartImage.getBounds().width ? printBounds.width : ganttChartImage.getBounds().width
- imgPieceSrcX;
if (imgPieceSrcHeight > 0 && imgPieceSrcWidth > 0) {
// gantt chart is printed as image, piece by piece
gc.drawImage(ganttChartImage,
imgPieceSrcX, imgPieceSrcY,
imgPieceSrcWidth, imgPieceSrcHeight,
printBounds.x, printBounds.y,
imgPieceSrcWidth, imgPieceSrcHeight); // destination width and height equal to source width and height to prevent
// stretching/shrinking of image
// move x and y to print next image piece
gc.drawText("Text " + currentPageNr, imgPieceSrcX, imgPieceSrcY);
imgPieceSrcX += printBounds.width;
}
currentPageNr++;
printer.endPage();
printerTransform.dispose();
}
}
Thanks in advance.

Related

Google Lighthouse Speed Index 100% visually completed frame definition

I'm looking for a way to optimize our website's Speed Index metric on Lighthouse
I found this helpful article describe Speed Index metric very well, and help me understand how Speed Index is calculated.
https://calendar.perfplanet.com/2016/speed-index-tips-and-tricks/
But there is a key concept not being described clear on the article, and I search for a lot of other Speed Index related blogs still can't found the answer.
What is the 100% visual completeness frame?
We all know the First Frame is 0% VC because it's blank, but the VC keep increasing during the page load process, so what frame will be consider as 100% visual completeness?
The definition of 100% VC frame is important because it's the baseline for calculate all other frame's visual completeness.
If I have a page that simply print from 1 to 100 with interval 100ms and just enough to fill in the viewport, will the 100% VC frame be the frame that number 100 is printed?
Lighthouse
According to Google's description of the Lighthouse "Speed Index" audit:
Lighthouse uses a node module called Speedline to generate the Speed Index score.
sends Speedline
Speedline's Github readme says
The Speed Index, introduced by WebpageTest.org, aims to solve this issue. It measures how fast the page content is visually displayed. The current implementation is based on the Visual Progress from Video Capture calculation method described on the Speed Index page. The visual progress is calculated by comparing the distance between the histogram of the current frame and the final frame.
(Italics mine.)
a timeline of paints
The Speed Index page goes into painful detail about how visual progress is calculated. Here's a snippet:
In the case of Webkit-based browsers, we collect the timeline data which includes paint rects as well as other useful events.
I believe "timeline data" refers to a JSON object retrieved via the Performance Timeline API.
It seems Lighthouse passes the JSON timeline to Speedline, which then extracts an array of "frames," describing the page load's paint events:
/**
* #param {string|Array<TraceEvent>|{traceEvents: Array<TraceEvent>}} timeline
* #param {Options} opts
*/
function extractFramesFromTimeline(timeline, opts) {
which calculates histograms
Speedline converts the image data from each paint event to an image histogram, interestingly excluding pixels that are "close enough" to pass as white:
/**
* #param {number} i
* #param {number} j
* #param {ImageData} img
*/
function isWhitePixel(i, j, img) {
return getPixel(i, j, 0, img.width, img.data) >= 249 &&
getPixel(i, j, 1, img.width, img.data) >= 249 &&
getPixel(i, j, 2, img.width, img.data) >= 249;
}
A lot of math goes into calculating and comparing histograms. The project maintainer is the right person to ask about that. But this is where the eventual determination of the "visually complete" happens:
// find visually complete
for (let i = 0; i < frames.length && !visuallyCompleteTs; i++) {
if (frames[i][progressToUse]() >= 100) {
visuallyCompleteTs = frames[i].getTimeStamp();
}
}
and infers "progress",
The "progress" of a given frame seems to be calculated by this function:
/**
* #param {Frame} current
* #param {Frame} initial
* #param {Frame} target
*/
function calculateFrameProgress(current, initial, target) {
let total = 0;
let match = 0;
const currentHist = current.getHistogram();
const initialHist = initial.getHistogram();
const targetHist = target.getHistogram();
for (let channel = 0; channel < 3; channel++) {
for (let pixelVal = 0; pixelVal < 256; pixelVal++) {
const currentCount = currentHist[channel][pixelVal];
const initialCount = initialHist[channel][pixelVal];
const targetCount = targetHist[channel][pixelVal];
const currentDiff = Math.abs(currentCount - initialCount);
const targetDiff = Math.abs(targetCount - initialCount);
match += Math.min(currentDiff, targetDiff);
total += targetDiff;
}
}
let progress;
if (match === 0 && total === 0) { // All images are the same
progress = 100;
} else { // When images differs
progress = Math.floor(match / total * 100);
}
return progress;
}
and "visually complete" is the first frame with 100% progress.
Without fully auditing the code, my interpretation is that the "visually complete frame" is the first frame calculated to have the same total difference from the initial frame as the final frame (which is determined by which frames Lighthouse chooses to send to Speedline).
Or, in other words, it's complicated.
Visually complete is when the page in the viewport stops changing. I.e. the visuals are not changing.
It is calculated by taking screenshots throughout the load and comparing them to each other and to the final end state. So yes in your example when all numbers 1-100 are printed and the page stops changing you are “visually complete”.
So if a page loads the data in view quickly but renders “below the fold” content (e.g. off screen images) more slowly then you will get a quick visually complete, even if the page overall load time is still long.
Similarly if most of the on screen content is drawn early on but one small part is drawn later (perhaps a “click to chat” option) you will get mostly visually complete early on and so a good speed index, even if not as good as the above example.
On the other hand if you load fonts, or perhaps a large hero image, last and it redraws large parts of the page in view you will get a slow visual complete time and also a slow speed index score.
More details here: https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index
I just got the answer from Lighthouse repo contributor, pls check this link guys.
https://github.com/GoogleChrome/lighthouse/issues/8148

How to hide value labels when zooming out in MPAndroidChart?

I'm using Swift version of MPAndroidChart and trying to figure out how to hide value labels when a few of them are located too close together and start to overlap on a line chart.
Hiding all the value labels when zoomed out to a certain point works too(still don't know how to do it), but hiding only the ones that are overlapping would be the best.
I know that I can manually call setDrawValues = false, but I want it to be called automatically on zoom.
enter image description here
In Android, I use the same as iOS
1: Find the difference between 1st and 2nd index y-axis label(YAxisRenderer)
for (int i = from; i < to; i++)
{
String text = mYAxis.getFormattedLabel(i);
double value1=Double.parseDouble(mYAxis.getFormattedLabel(1).replace(",",""));
double value2=Double.parseDouble(mYAxis.getFormattedLabel(2).replace(",",""));
result=(value2-value1)-40;
//POPreferences.setDifference(String.valueOf(result));
c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint);
}
2: Use result variable when text draws on bar or line(BarChartRenderer.java):
if (result >= vals[k / 2])
{
drawValue(c,dataSet.getValueFormatter(),vals[k / 2], entry, i, x, y,color);
}

How do i resize an object created in actionscript with the point of origin staying central

widthEssentially, i am creating objects in Flash using actionscript. I currently have a problem where i am resizing the object in actionscript but as the point of reference seems to be the top left hand corner, the object when shrinking seems to also move towards the top left of the screen.
Is there a way to either code the point of origin for an object to the center of the object using code or to have it resize without seemingly moving?
my code for creating and resizing an object is like this (it will grow and shrink but at moment im just tryint to fix this problem before i move on):
var blob1:Loader = new Loader();
blob1.x = 1000;
blob1.y = 450;
blob1.load(new URLRequest("blob1.png"));
addChild(blob1);
blob1.addEventListener(Event.ENTER_FRAME, blobTween);
function blobTween(event:Event)
{
var size = 0;
if (size == 0){
blob1.width += 5;
blob1.height += 5;
}else if (size == 1){
}
Can't you update x and y while you change width and height ?
blob1.x += deltaWidth / 2
blob1.y += deltaHeight / 2
You increment width and height by 5, so deltaWidth = 5 and deltaHeight = 5 .
NOTE: deltaWidth / 2 doesn't divide equally, so you'll have slight shift. I suggest having deltaWidth = 6 and deltaHeight = 6 , or something similar.
GreenSock has a great library for doing just that; TransformManager.
http://www.greensock.com/transformmanageras3/
my solution in the end was a bit strange. I took the shape, divided it into 4 quarters and reattached them in flash by placing the objects in the same place and rotating them (as it rotates from the top left corner, the 4 quarters form a complete shape with each quarter having their top left corner in the centre of the "object"). I then resized them all at once to do it properly.
Whats weird is that the top right and bottom left corners required different math from the other two corners. Which makes no sense whatsoever. 2 corners required width and height to be adjusted. The other two corners required just width to be adjusted. very strange but worked :/

thin border when printing pdf

We use Version 8.1 from ABCPDF to generate some nice PDF documents from html.
Now we discovered that printing from within Adobe Reader, will add some thin borders at the top and bottom of the page, that are not visible when the document is displayed. Also when printing to XPS, those lines are not visible.
I guess we must have missed some setting that avoids that?
At the moment we print pages like that:
using (var doc = new WebSupergoo.ABCpdf8.Doc())
{
doc.HtmlOptions.DoMarkup = false;
doc.HtmlOptions.AddLinks = false;
doc.HtmlOptions.FontEmbed = true;
doc.HtmlOptions.Engine = EngineType.Gecko;
//in case that we need to create more than 1 page, we need go get the PageId and use it
int pdfPageId = doc.AddImageHtml(html);
while (true)
{
doc.FrameRect();
if (!doc.Chainable(pdfPageId))
break;
doc.Page = doc.AddPage();
pdfPageId = doc.AddImageToChain(pdfPageId);
}
for (int i = 1; i <= doc.PageCount; i++)
{
doc.PageNumber = i;
doc.Flatten();
}
doc.Save(pathToSave);
}
I know the websupergoo guys are very friendly and reply fast.
But I think this could help other people as well, so I write it here instead of sending them an email.
Update:
I tried to get rid of the linex by changing the size of the printed document. I actually try to print for A4 Papersize. I added a line of code to change the setting for the MediaBox (the documentation suggested that this should be possible "doc.MediaBox = "A4"", but it's not directly assignable):
//set the printed area to A4
doc.MediaBox.String = "A4";
Result: The lines got thicker and can now even be seen before printing in both AdobeReader and Foxit Reader. this is not yet the solution.
Update2:
I need to set the Rect of the document as well:
//set the printed area to A4
doc.Rect.String ="A4";
doc.MediaBox.String = "A4";
Result: the lines are now drawn on the sides and can only be seen when printing. That's still not the complete solution.
Well well, copy pasting code from the web has it's dangers!
This line adds the Frame around the content:
doc.FrameRect();
all I had to do was remove it.. and no more lines are displayed.
I completely overlooked that until now.
Before I also tried the following, which didn't work as expected:
//set the width to 0, so Rectancles have no width
doc.Width = 0;
// set the color to white, so borders of Rectangles should not be black
doc.Color.String = "255 255 255"; //Edited based on the comments.

XNA isometric tiles rendering issue

I'm currently working on a XNA game prototype. I'm trying to achieve a isometric view of the game world (or is it othographic?? I'm not sure which is the right term for this projection - see pictures).
The world should a tile-based world made of cubic tiles (e.g. similar to Minecraft's world), and I'm trying to render it in 2D by using sprites.
So I have a sprite sheet with the top face of the cube, the front face and the side (visible side) face. I draw the tiles using 3 separate calls to drawSprite, one for the top, one for the side, one for the front, using a source rectangle to pick the face I want to draw and a destination rectangle to set the position on the screen according to a formula to convert from 3D world coordinates to isometric (orthographic?).
(sample sprite:
)
This works good as long as I draw the faces, but if I try to draw fine edges of each block (as per a tile grid) I can see that I get a random rendering pattern in which some lines are overwritten by the face itself and some are not.
Please note that for my world representation, X is left to right, Y is inside screen to outside screen, and Z is up to down.
In this example I'm working only with top face-edges. Here is what I get (picture):
I don't understand why some of the lines are shown and some are not.
The rendering code I use is (note in this example I'm only drawing the topmost layers in each dimension):
/// <summary>
/// Draws the world
/// </summary>
/// <param name="spriteBatch"></param>
public void draw(SpriteBatch spriteBatch)
{
Texture2D tex = null;
// DRAW TILES
for (int z = numBlocks - 1; z >= 0; z--)
{
for (int y = 0; y < numBlocks; y++)
{
for (int x = numBlocks - 1; x >=0 ; x--)
{
myTextures.TryGetValue(myBlockManager.getBlockAt(x, y, z), out tex);
if (tex != null)
{
// TOP FACE
if (z == 0)
{
drawTop(spriteBatch, x, y, z, tex);
drawTop(spriteBatch, x, y, z, outlineTexture);
}
// FRONT FACE
if(y == numBlocks -1)
drawFront(spriteBatch, x, y, z, tex);
// SIDE FACE
if(x == 0)
drawSide(spriteBatch, x, y, z, tex);
}
}
}
}
}
private void drawTop(SpriteBatch spriteBatch, int x, int y, int z, Texture2D tex)
{
int pX = OffsetX + (int)(x * TEXTURE_TOP_X_OFFRIGHT + y * TEXTURE_SIDE_X);
int pY = OffsetY + (int)(y * TEXTURE_TOP_Y + z * TEXTURE_FRONT_Y);
topDestRect.X = pX;
topDestRect.Y = pY;
spriteBatch.Draw(tex, topDestRect, TEXTURE_TOP_RECT, Color.White);
}
I tried using a different approach, creating a second 3-tiers nested for loop after the first one, so I keep the top face drawing in the first loop and the edge highlight in the second loop (I know, this is inefficient, I should also probably avoid having a method call for each tile to draw it, but I'm just trying to get it working for now).
The results are somehow better but still not working as expected, top rows are missing, see picture:
Any idea of why I'm having this problem? In the first approach it might be a sort of z-fighting, but I'm drawing sprites in a precise order so shouldn't they overwrite what's already there?
Thanks everyone
Whoa, sorry guys I'm an idiot :) I started the batch with SpriteBatch.begin(SpriteSortMode.BackToFront) but I didn't use any z-value in the draw.
I should have used SpriteSortMode.Deferred! It's now working fine. Thanks everyone!
Try tweaking the sizes of your source and destination rectangles by 1 or 2 pixels. I have a sneaking suspicion this has something to do with the way these rectangles are handled as sort of 'outlines' of the area to be rendered and a sort of off-by-one problem. This is not expert advice, just a fellow coder's intuition.
Looks like a sub pixel precision or scaling issue. Also try to ensure your texture/tile width/height is a power of 2 (32, 64, 128, etc.) as that could make the effect less bad as well. It's really hard to tell just from those pictures.
I don't know how/if you scale everything, but you should try to avoid rounding wherever possible (especially inside your drawTop() method). Every time you round some position/coordinate chances are good you might increase the error/random offsets. Try to use double (or better: float) coordinates instead of integer.

Resources