How to pixel perfect align text-element - vue.js

I want my vue Konva Text element to completely fill the given height, like i expect of a rectangle.
This is issue becomes obvious when pairing with text images, (converting svg text to canvas) that properly match the given dimension
<v-text :config={
x: 50,
y: 50,
width: 1000,
height: 60,
fontSize: 60,
fontStyle: 'bold',
fontFamily 'Campton Book'
text: 'WELT'
}
/>
<v-rect
:config="{ x: 50, y: 50, fill: 'black', height: 60, width: 200 }"
/>
Second Part, is there any way to always pixel perfectly align the left side with the border? the x coordinate matches the border
Is this due to font constraints? What am I missing?
I tried to get the height of the text node to fix this positioning but this is the given height passed down as props

Text is defined as having parts above and below the baseline. Above is termed 'ascenders' amd below is 'descenders', which are required for lower case letters like j y g.
Setting the text fontSize to 60 does not say 'whatever the string, make it fill a space 60px high'. Instead it says 'Make text in a 60px font', which makes space for the descenders because they will generally be required.
If you know for sure that the text will be all caps, then a solution is to measure the height used and increase the font size by a computed factor so that the font fills the line height.
To do this you'll need to get the glyph measurements as follows:
const lineHeight = 60; // following your code
// make your text shape here...left out for brevity
const metrics = ctx.measureText('YOUR CAPS TEXT');
capsHeight = Math.abs(metrics.actualBoundingBoxAscent)
fontSize = lineHeight * lineHeight / capsHeight;
If I got that right, your 60px case should give a value around 75. That's based on the convention that ascenders are 80% of the line height. Now you set the font size of your shape to this new value and you should be filling the entire line height.
Regarding the left-alignment, this relies on what the font gurus call the a-b-c widths. The left gap is the a-space, the b is the character width (where the ink falls) and the c-space is the same as the a-space but on the right hand side.
Sadly unless someone else can tell me I am wrong, you don't get a-b-c widths in the canvas TextMetric. There is a workaround which is rather convoluted but viable. You would draw the text in black on an off-screen canvas filled with a transparent background. Then get the canvas pixel data and walk horizontal lines from the left of the canvas inspecting pixels and looking for the first colored pixel. Once you find it you have the measurement to offset the text shape horizontally.

Related

pdfbox extract text by area units

I need to extract the address zip code from a pdf and I use the PDFTextStripperByArea class from pdfbox like in this example ExtractTextByArea. But what are the units of parameters in Rectangle rect = new Rectangle( 10, 280, 275, 60 ); From where must measure and to what units? If they are pixels then it is not convenient to measure pdf page component positions in pixels.
The y-coordinates are java coordinates (y == 0 is top), not PDF coordinates (y == 0 is bottom).
The units are 1/72 inch which is identical to pixels when you render the PDF at 100%.

iOS Core Graphics how to optimize incremental drawing of very large image?

I have an app written with RXSwift which processes 500+ days of HealthKit data to draw a chart for the user.
The chart image is drawn incrementally using the code below. Starting with a black screen, previous image is drawn in the graphics context, then a new segment is drawn over this image with certain offset. The combined image is saved and the process repeats around 70+ times. Each time the image is saved, so the user sees the update. The result is a single chart image which the user can export from the app.
Even with autorelease pool, I see spikes of memory usage up to 1Gb, which prevents me from doing other resource intensive processing.
How can I optimize incremental drawing of very large (1440 × 5000 pixels) image?
When image is displayed or saved at 3x scale, it is actually 4320 × 15360.
Is there a better way than trying to draw over an image?
autoreleasepool {
//activeEnergyCanvas is custom data processing class
let newActiveEnergySegment = activeEnergyCanvas.draw(in: CGRect(x: 0, y: 0, width: 1440, height: days * 10), with: energyPalette)
let size = CGSize(width: 1440, height: height)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
//draw existing image
self.activeEnergyImage.draw(in: CGRect(origin: CGPoint(x: 0, y: 0),
size: size))
//calculate where to draw smaller image over larger one
let offsetRect = CGRect(origin: CGPoint(x: 0, y: offset * 10),
size: newActiveEnergySegment.size)
newActiveEnergySegment.draw(in: offsetRect)
//get the combined image
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//assign combined image to be displayed
if let unwrappedImage = newImage {
self.activeEnergyImage = unwrappedImage
}
}
Turns out my mistake was in passing invalid drawing scale (0.0) when creating graphics context, which defaulted to drawing at the device's native screen scale.
In case of iPhone 8 it was 3.0 The result is needing extreme amounts of memory to draw, zoom and export these images. Even if all debug logging prints that image is 1440 pixels wide, the actual canvas ends up being 1440 * 3.0 = 4320.
Passing 1.0 as the drawing scale makes the image more fuzzy, but reduces memory usage to less than 200mb.
// UIGraphicsBeginImageContext() <- also uses #3x scale, even when all display size printouts show
let drawingScale: CGFloat = 1.0
UIGraphicsBeginImageContextWithOptions(size, true, drawingScale)

How do I get the frame of visible content from SKCropNode?

It appears that, in SpriteKit, when I use a mask in a SKCropNode to hide some content, it fails to change the frame calculated by calculateAccumulatedFrame. I'm wondering if there's any way to calculate the visible frame.
A quick example:
import SpriteKit
let par = SKCropNode()
let bigShape = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
bigShape.fillColor = UIColor.redColor()
bigShape.strokeColor = UIColor.clearColor()
par.addChild(bigShape)
let smallShape = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 20, height: 20))
smallShape.fillColor = UIColor.greenColor()
smallShape.strokeColor = UIColor.clearColor()
par.maskNode = smallShape
par.calculateAccumulatedFrame() // returns (x=0, y=0, width=100, height=100)
I expected par.calculateAccumulatedFrame() to return (x=0, y=0, width=20, height=20) based on the crop node mask.
I thought maybe I could code the function myself as an extension that basically reimplements calculateAccumulatedFrame with support for checking for SKCropNodes and their masks, but it occurred to me that I would need to consider the alpha of that mask to determine if there's actual content that grows the frame. Sounds difficult.
Is there an easy way to calculate this?

How do I resize a drawing in a processing applet?

I imported the processing language into Java and I drew a simple house.
Like:
rect (75, 175, 350, 175);
// door
rect (225, 275, 50, 75);
// roof
triangle (250, 100, 75, 175, 425, 175);
// windows
rect (125, 200, 50, 50);
rect (325, 200, 50, 50);
I want to be able to resize the image, or scale that image when I change the window size. Right now the window size is just 500 by 500, but if I expand the window it doesn't expand the drawing with it.
I tried using scale(), but for some reason it scaled the image for like a millisecond and then reverted back to the unscaled version. My java teacher told me the draw method in processing refreshes at something like 60 times per second, but I don't see why it would be different from the first time.
If you want your drawing to scale with the window, you're going to need to base all your coordinates off the width and height variables.
For example, let's say I'm drawing a 200x200 circle inside a 200x200 window:
size(200, 200);
ellipse(100, 100, 200, 200);
If I then change the size of the window to 400x400, then I have to change the parameters I'm passing into the ellipse() function:
size(400, 400);
ellipse(200, 200, 400, 400);
This can be annoying (as you're experiencing), so it's better to just base your parameters off the width and height variables. That way whenever your window size changes, Processing does the calculation for you and the drawing scaled with your window.
size(600, 600);
ellipse(width/2, height/2, width, height);
This is just an example, but the process for you would be the same: go through and change every value to be based off the width and height variables instead of hard-coded numbers.
More info can be found here: Using Variables - HappyCoding.io
(full disclosure: I wrote that tutorial, but I think it explains exactly what you're asking about)
Edit: You asked about the scale() method, so I'll explain that below. But if you're trying to base the size of your drawing off the size of your window, then you should use the above approach! But since this is a homework assignment, you're restricted to doing it the way the teacher says. Anyway...
Let's look at a simple program:
size(100, 100);
ellipse(50, 50, 10, 10);
This code simply creates a 100x100 sized window and then draws a small ellipse in the center:
If we wanted to make the circle bigger, we could use the scale() function. You can think of the scale() function as automatically multiplying every parameter you pass into a drawing function (like ellipse() or rect()) by whatever number(s) you pass into the scale() function.
For example, this code multiplies every number by 2:
size(100, 100);
scale(2);
ellipse(50, 50, 10, 10);
The circle is now twice as large, but it's also no longer in the center. That's because we're also multiplying 50,50 (the center of the window) by 2 to get 100,100 (the bottom-right corner of the window). To fix that, we either need to change the 50,50:
size(100, 100);
scale(2);
ellipse(25, 25, 10, 10);
Or we could use the translate() function to move the coordinates before we do the scale:
size(100, 100);
translate(50, 50);
scale(2);
ellipse(0, 0, 10, 10);
Either approach is fine, so it's really up to which one makes more sense to you. Now we have a big centered circle, even though we're still sizing it to 10,10.

Repositioning of a UIView after CGAffineRotation

I'm drawing a map of hexagons inside a UIView and the next step is to give it in isometric view. To do this, I transformed the map using the CGAffineTransform, rotation and scaling, reaching my goal.
Now, if the map becomes bigger, when i rotate it, the lower left corner goes out my screen, this is the frame before and after the transformation:
2012-03-07 17:08:06.160 PratoFiorito[941:f803] X: 0.000000 - Y: 0.000000 || Width: 1408.734619 - Height: 1640.000000
2012-03-07 17:08:06.163 PratoFiorito[941:f803] X: -373.523132 - Y: 281.054779 || Width: 2155.781006 - Height: 1077.890503
I simply can't understand what is the new point of origin and how I can calculate it to replace the view correctly. Somebody can help me?