Uneven borders of ellipse annotation when I try to rotate the PDF - itext

I am trying to draw ellipse on a rotated PDF but the border of the ellipse appears thick and thin in center
Sample Code:
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(getColor(annot.getBorderColor()));
// annotation.setBorder(new PdfBorderArray(2, 2, 2));
// annotation.setColor(getColor(annot.getBorderColor()));
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(page);
if ((int) (orientation % 360) == 90 || (int) (orientation % 360) == 270)
{
w = rect.getHeight();
h = rect.getWidth();
}
else
{
w = rect.getWidth();
h = rect.getHeight();
}
PdfAppearance app = cb.createAppearance(w + 3.5f, h + 3.5f);
app.setColorStroke(getColor(annot.getBorderColor()));
app.setLineWidth(3.5);
app.ellipse(rect.getLeft() + 1.5, rect.getBottom() + 1.5, rect.getRight() - 1.5, rect.getTop() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, page);

As already assumed in a comment a feature of iText (for rotated pages it attempts to pretend to the user that he has an upright coordinate system, not a rotated one) gets into your way. This feature unfortunately does only affect the dimensions of the annotation itself, not of the appearances you create for it.
If a page has a 90° or 270° rotation, therefore, you have to use appearance dimensions whose width and height are switched compared to the annotation dimensions you used.
Furthermore, one also has to consider the switched dimensions when drawing the ellipse on the appearance template. The code in the question and in the example code shared via google drive forgot this.
Finally, one shall not override the switched dimensions of the appearance template using PdfAppearance.setBoundingBox. The code in the example code shared via google drive did this.
False Example
If I create an ellipse annotation with appearance on a rotated page like this:
Rectangle rect = new Rectangle(202 + 6f, 300, 200 + 100, 300 + 150);
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(BaseColor.RED);
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(1);
PdfAppearance app = cb.createAppearance(rect.getWidth(), rect.getHeight());
app.setColorStroke(BaseColor.RED);
app.setLineWidth(3.5);
app.ellipse( 1.5, 1.5, rect.getWidth() - 1.5, rect.getHeight() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, 1);
(CreateEllipse test testCreateEllipseAppearanceOnRotated)
I indeed get a funny ellipse:
Correct Example
If I create an ellipse annotation with appearance on a rotated page with switched dimensions like this, though:
Rectangle rect = new Rectangle(202 + 6f, 300, 200 + 100, 300 + 150);
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(BaseColor.RED);
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(1);
// switched appearance dimensions
PdfAppearance app = cb.createAppearance(rect.getHeight(), rect.getWidth());
app.setColorStroke(BaseColor.RED);
app.setLineWidth(3.5);
// draw ellipse using switched appearance dimensions
app.ellipse( 1.5, 1.5, rect.getHeight() - 1.5, rect.getWidth() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, 1);
(CreateEllipse test testCreateCorrectEllipseAppearanceOnRotated)
I get the expected ellipse:

Related

pangocairo text in middle of the circle

I am writing an extension / widgets for gnome-shell.So I want to show some information using text. Actually I want to put text in middle of the circle using pangoCairo but I can't figure out how can I put text using pangoCairo?
here is my code of drawing circles with a function to set text middle of the circles but the text is not showing in the middle.
draw_stuff(canvas, cr, width, height) {
cr.setSourceRGBA(1,1,1,0.2);
cr.save ();
cr.setOperator (Cairo.Operator.CLEAR);
cr.paint ();
cr.restore ();
cr.setOperator (Cairo.Operator.OVER);
cr.scale (width, height);
cr.setLineCap (Cairo.LineCap.BUTT);
//test
cr.setLineWidth (0.08);
cr.translate (0.5, 0.5);
cr.arc (0, 0, 0.4, 0, Math.PI * 2);
cr.stroke ();
cr.setSourceRGBA(1,1,1,0.8);
cr.rotate(-Math.PI/2);
cr.save();
cr.arc (0,0, 0.4, 0, this.currentR /100 * 2 * Math.PI);
cr.stroke();
cr.setSourceRGBA(1,1,1,0.9);
cr.save();
cr.arc (0,0, 0.25, 0, 2 * Math.PI);
cr.fill();
cr.moveTo(0, 0);
cr.setSourceRGBA(0,0,0,0.9);
cr.save();
this.text_show(cr, "WoW");
cr.restore();
return true; }
update() { this.currentR = 60;
this._canvas.connect ("draw", this.draw_stuff.bind(this));
this._canvas.invalidate();}
text_show(cr, showtext, font = "DejaVuSerif Bold 16") {
let pl = PangoCairo.create_layout(cr);
pl.set_text(showtext, -1);
pl.set_font_description(Pango.FontDescription.from_string(font));
PangoCairo.update_layout(cr, pl);
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2, 0);
PangoCairo.show_layout(cr, pl);
cr.relMoveTo(w / 2, 0);}
I dont know what's wrong here?
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2, 0);
You are placing your text something like 1000 pixels off the screen. get_pixel_size() is documented as:
pango_layout_get_size() returns the width and height scaled by PANGO_SCALE.
and PANGO_SCALE has the value 1024:
Thus, you need to change the code above to
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2048, 0);
Bonus points for not hardcoding the value of PANGO_SCALE and instead getting it from your Pango API bindings. However, for that I don't know enough about gnome-shell-extensions. Is this code in Javascript? Dunno.

How set rotation angle a page in itext 7

How can i rotate page at a specified angle(for example 25 degrees)?
PdfCanvas content = new PdfCanvas(pdfDoc.addNewPage());
for (int i =1 ; i <= srcDoc.getNumberOfPages(); i++) {
PdfFormXObject page = srcDoc.getPage(i).copyAsFormXObject(pdfDoc);
content.add(page...);
}
Can i set RotationAngle to work with PdfFormXObject ? Or is there another way?
The easiest way is by using an AffineTransform (from com.itextpdf.kernel.geom):
PdfCanvas content = new PdfCanvas(pdfDoc.addNewPage());
PageSize pageSize = pdfDoc.getDefaultPageSize();
PdfFormXObject page = srcDoc.getPage(1).copyAsFormXObject(pdfDoc);
AffineTransform transform = AffineTransform.getRotateInstance(25 * Math.PI / 180, (pageSize.getLeft() + pageSize.getRight())/2, (pageSize.getBottom() + pageSize.getTop())/2);
content.concatMatrix(transform);
content.addXObject(page, 0, 0);
(RotatePageXObject test testAddPage25Degree)
AffineTransform.getRotateInstance is documented to
* Get an affine transformation representing a counter-clockwise rotation over the passed angle,
* using the passed point as the center of rotation
so we feed it the angle (transformed to radians) and the coordinates of the page center.
Applied to this source PDF it creates this result:

UV mapping a procedural cylinder in Unity

I have a method that creates a cylinder based on variables that contain the height, radius and number of sides.
The mesh generates fine with any number of sides, however I am really struggling with understanding how this should be UV mapped.
Each side of the cylinder is a quad made up of two triangles.
The triangles share vertices.
I think the placement of the uv code is correct, however I have no idea what values would be fitting?
Right now the texture is stretched/crooked on all sides of the mesh.
Please help me understand this.
private void _CreateSegmentSides(float height)
{
if(m_Sides > 2) {
float angleStep = 360.0f / (float) m_Sides;
BranchSegment seg = new BranchSegment(m_NextID++);
Quaternion rotation = Quaternion.Euler(0.0f, angleStep, 0.0f);
int index_tr = 0, index_tl = 3, index_br = 2, index_bl = 1;
float u0 = (float)1 / (float) m_Sides;
int max = m_Sides - 1;
// Make first triangles.
seg.vertexes.Add(rotation * (new Vector3(m_Radius, height, 0f)));
seg.vertexes.Add(rotation * (new Vector3(m_Radius, 0f, 0f)));
seg.vertexes.Add(rotation * seg.vertexes[seg.vertexes.Count - 1]);
seg.vertexes.Add(rotation * seg.vertexes[seg.vertexes.Count - 3]);
// Add triangle indices.
seg.triangles.Add(index_tr); // 0
seg.triangles.Add(index_bl); // 1
seg.triangles.Add(index_br); // 2
seg.triangles.Add(index_tr); // 0
seg.triangles.Add(index_br); // 2
seg.triangles.Add(index_tl); // 3
seg.uv.Add(new Vector2(0, 0));
seg.uv.Add(new Vector2(0, u0));
seg.uv.Add(new Vector2(u0, u0));
seg.uv.Add(new Vector2(u0, 0));
for (int i = 0; i < max; i++)
{
seg.vertexes.Add(rotation * seg.vertexes[seg.vertexes.Count - 2]); // new vertex
seg.triangles.Add(seg.vertexes.Count - 1); // new vertex
seg.triangles.Add(seg.vertexes.Count - 2); // shared
seg.triangles.Add(seg.vertexes.Count - 3); // shared
seg.vertexes.Add(rotation * seg.vertexes[seg.vertexes.Count - 2]); // new vertex
seg.triangles.Add(seg.vertexes.Count - 3); // shared
seg.triangles.Add(seg.vertexes.Count - 2); // shared
seg.triangles.Add(seg.vertexes.Count - 1); // new vertex
// How should I set up the variables for this part??
// I know they are not supposed to be zero.
if (i % 2 == 0) {
seg.uv.Add(new Vector2(0, 0));
seg.uv.Add(new Vector2(0, u0));
} else {
seg.uv.Add(new Vector2(u0, u0));
seg.uv.Add(new Vector2(u0, 0));
}
}
m_Segments.Add(seg);
}
else
{
Debug.LogWarning("Too few sides in the segment.");
}
}
Edit: Added pictures
This is what the cylinder looks like (onesided triangles):
This is what the same shader should look like (on a flat plane):
Edit 2: Wireframe pics
So your wireframe is okey(you linked only wireframe but i asked for shaded wireframe: this is a shaded wireframe buts its okey).
The reason your texture looks like this, is because its trying to strecth your image alongside any height, so it might look good on an 1m height cylinder, but would look stretched on an 1000m height one, so you actually need to dynamically strecth this uv map.
Example for 1m height cylinder, texture is okey cos it is for 1x1 dimension:
Example for 2m height cylinder texture stretched because double the length 2x1 dimension:
So what you can do is if you generate always the same height cylinder you can just adjust it inside unity, at the texture properties its called tiling, just increase the x or y dimension of your texture and dont forget to make the texture repeat itself.
Also your cylinder cap should look like this(it is not a must have thing but yeah):

Three.js camera rotation issue

I want to rotate the camera around the x-axis on the y-z plane while looking at the (0, 0, 0) point. It turns out the lookAt function behaves weird. When after rotating 180°, the geometry jump to another side unexpectedly. Could you please explain why this happens, and how to avoid it?
You can see the live demo on jsFiddle: http://jsfiddle.net/ysmood/dryEa/
class Stage
constructor: ->
window.requestAnimationFrame =
window.requestAnimationFrame or
window.webkitRequestAnimationFrame or
window.mozRequestAnimationFrame
#init_scene()
#make_meshes()
init_scene: ->
#scene = new THREE.Scene
# Renderer
width = window.innerWidth;
height = window.innerHeight;
#renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('.scene')
})
#renderer.setSize(width, height)
# Camera
#camera = new THREE.PerspectiveCamera(
45, # fov
width / height, # aspect
1, # near
1000 # far
)
#scene.add(#camera)
make_meshes: ->
size = 20
num = 1
geo = new THREE.CylinderGeometry(0, size, size)
material = new THREE.MeshNormalMaterial()
mesh = new THREE.Mesh(geo, material)
mesh.rotation.z = Math.PI / 2
#scene.add(mesh)
draw: =>
angle = Date.now() * 0.001
radius = 100
#camera.position.set(
0,
radius * Math.cos(angle),
radius * Math.sin(angle)
)
#camera.lookAt(new THREE.Vector3())
#renderer.render(#scene, #camera)
requestAnimationFrame(#draw)
stage = new Stage
stage.draw()
You are rotating the camera around the X-axis in the Y-Z plane. When the camera passes over the "north" and "south" poles, it flips so as to stay right-side-up. The camera's up-vector is (0, 1, 0) by default.
Set the camera x-position to 100 so, and its behavior will appear correct to you. Add some axes to your demo for a frame of reference.
This is not a fault of the library. Have a look at the Camera.lookAt() source code.
If you want to set the camera orientation via its quaternion instead, you can do that.
three.js r.59

How to draw an oval speech bubble programmatically on iPhone?

The technique shown in a similar question is a rectangular bubble. How to draw one in an oval shape? i.e.:
   
I would do it in two iterations.
First get the context and begin a path. Fill an ellipse and then a custom path that encloses a triangle with three lines. I assumed the following dimensions: 70 width, 62 height. Override draw rect in a subclass of UIView and instantiate in a subclassed UIViewController:
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 0.0, 0.0, 1.0, 1.0);
CGContextFillEllipseInRect(ctx, CGRectMake(0.0, 0.0, 70.0, 50.0)); //oval shape
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 8.0, 40.0);
CGContextAddLineToPoint(ctx, 6.0, 50.0);
CGContextAddLineToPoint(ctx, 18.0, 45.0);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
}
Produces this in the iPhone simulator when added against a gray backdrop:
This second code example will almost duplicate what you produced above. I implemented this using flexible sizes that could be supplied to the UIView frame when you instantiate it. Essentially, the white portion of the speech bubble is drawn with a black stroke over lay to follow.
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect aRect = CGRectMake(2.0, 2.0, (self.bounds.size.width * 0.95f), (self.bounds.size.width * 0.60f)); // set the rect with inset.
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); //white fill
CGContextSetRGBStrokeColor(ctx, 0.0, 0.0, 0.0, 1.0); //black stroke
CGContextSetLineWidth(ctx, 2.0);
CGContextFillEllipseInRect(ctx, aRect);
CGContextStrokeEllipseInRect(ctx, aRect);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f));
CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f));
CGContextClosePath(ctx);
CGContextFillPath(ctx);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f));
CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextStrokePath(ctx);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f));
CGContextStrokePath(ctx);
}
I have another way - however I dont have any time to properly explain it.
However, my example was written in .NET for use in a Windows application.
My version creates the entire speach bubble as 2D Polygon Mesh and is partially customizable. It is a single drawn path instead of multiple parts.
While our platforms are not the same - the technique uses common math routines and procedural loop. I believe the technique could be translated to other programming languages or platforms.
Private Sub Generate(ByVal Resolution As Integer, Optional ByVal SpeachPointerAngle As Integer = (45 * 3), Optional ByVal PointerBend As Decimal = 15)
'Generated the same way we create vector (wireframe) mesh for an Ellipse but...
'... at a predefined defined angle we create
'the size of the Pointer TIP/Corner portion of the speach bubble
'in relation to the EDGE of the ELLIPSE (average)
Dim SpeachPointerSize As Integer = 30
If PointerBend > 10 Then PointerBend = 10
If PointerBend < -10 Then PointerBend = -10
'as a variable offset that should be limited to max +/- -15 to 15 degrees relative to current angle as a safe range
'- were speach pointer angle determins which side the the pointer appears
Dim PointerOffsetValue As Decimal = PointerBend
Dim ActualPointerAngle As Decimal
'SpeachPointerAngle = 360 - SpeachPointerAngle ' adjust orientation so that 0 degrees is SOUTH
'Ellipse Size:
Dim Size_X As Decimal = 80
Dim Size_Y As Decimal = 50
If Resolution < 30 Then Resolution = 30
Dim Result As Vector2()
'size of each angle step based on resolution (number of vectors ) - Mesh Quality in otherwords.
Dim _Step As Decimal = 360 / Resolution
'Our current angle as we step through the loop
Dim _CurrentAngle As Decimal = 0
'rounded values
Dim _LastAngle As Decimal = 0
Dim _NextAngle As Decimal = _Step
Dim SpeachDrawn As Boolean = False ' prevent creating more than 1 point to be safe
Dim I2 As Integer = 0 'need a stepper because of skipped IDS
'build the ellipse mesh
For i = 0 To Resolution - 1
_LastAngle = _CurrentAngle - 15
_NextAngle = _CurrentAngle + 15
ActualPointerAngle = _CurrentAngle 'side
ActualPointerAngle += PointerOffsetValue ' acual angle of point
Dim EX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * Size_X
Dim EY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * Size_Y
'Point extrusion size ( trying to be even size all around )
Dim ExtrudeX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * (Size_X + SpeachPointerSize)
Dim ExtrudeY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * (Size_Y + SpeachPointerSize)
'is Pointer angle between Last and Next?
If SpeachPointerAngle > _LastAngle And SpeachPointerAngle < _NextAngle Then
If (SpeachDrawn = False) Then
' the point for the speachbubble tip
Array.Resize(Result, I2 + 1)
Result(I2) = New Vector2(ExtrudeX, ExtrudeY)
SpeachDrawn = True
I2 += 1
Else
'skip
End If
Else
'normal ellipse vector
Array.Resize(Result, I2 + 1)
Result(I2) = New Vector2(EX, EY)
I2 += 1
End If
_CurrentAngle += _Step
Next
_Vectors = Result
End Sub
The above code generated this - drawn to a bitmap using GDI+ [DrawPolygon/FillPolygon]:
https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/380262_10151202393414692_590995900_n.jpg
(Sorry - I can't post the image here directly as I have never posted here before. I don't have the reputation yet )
This is a Primitive in a Graphics Assembly I am developing for .NET which uses my own Vector2.
This speach bubble supports transparency when drawn - as it is a single polygon shape instead of multiple shapes.
Basically we draw an ellipse programatically and then extrude a speach point out on a desired side of the ellipse.
A similar approach could be applied using PointF structures instead.
All shapes in the code are generated around Origin 0,0.
Arrays are also resized incrementally as vectors are added prevent gaps in the array.
EG - the center of the speach bubble is Origin 0.0.
I apologize for not explaining my code properly - I just don't have the time.
But it probably isnt too hard to understand.