Flip tool not working for comments

Forum for the PDF-XChange Editor - Free and Licensed Versions

Moderators: PDF-XChange Support, Daniel - PDF-XChange, Chris - PDF-XChange, Sean - PDF-XChange, Paul - PDF-XChange, Vasyl - PDF-XChange, Ivan - Tracker Software, Stefan - PDF-XChange

User avatar
David.P
User
Posts: 1655
Joined: Thu Feb 28, 2008 8:16 pm

Flip tool not working for comments

Post by David.P »

Hi forum and Tracker support team,

I was going to horizontally mirror a polygon line (comment) in a PDF file using the flip tool, but the tool would not work for some reason.

Image

It actually doesn't seem to work on any type of annotation, it only works on content items.

Thanks for looking into this issue.

Best regards
David
David.P
PDF-XChange Pro
User avatar
Stefan - PDF-XChange
Site Admin
Posts: 19913
Joined: Mon Jan 12, 2009 8:07 am

Re: Flip tool not working for comments

Post by Stefan - PDF-XChange »

Hello David.P,

Yes - the Flip operations currently only work on base content objects and not on annotations.
I believe there is a feature request already for this tool to be improved so that it works on annotations as well, but I do not know when it will be implemented at this time.

Kind regards,
Stefan
User avatar
David.P
User
Posts: 1655
Joined: Thu Feb 28, 2008 8:16 pm

Re: Flip tool not working for comments

Post by David.P »

Thank you Stefan,

judging from the Customize Toolbars dialog box as shown above, the Flip operations should work also on annotations, at least this seems to be intended already. 

Anyway, it would be extremely useful if (comment) drawing objects could be not only rotated and resized/transformed but also flipped.

Best Regards 
David 
:)
David.P
PDF-XChange Pro
Mathew
User
Posts: 645
Joined: Thu Jun 19, 2014 7:30 pm

Re: Flip tool not working for comments

Post by Mathew »

Not sure if this has been updated yet, but it still wasn't working for me, so I made a script. There are two versions in the attached.

"Mirror annotations dialog.js" is the script that can be run from the javascript window,
"mirror annotations menu.js" is the script made into a menuscript (ie put it in the C:\Users\[username]\AppData\Roaming\Tracker Software\PDFXEditor\3.0\Javascripts\ folder) and it adds a menu item to the Comments menu.

It doesn't work for all annotations - I think there's a bug in how tracker reports the gestures for Ink (pencil tool) annotations, and it doesn't mirror stamps. But it's a start.
Mirror annotations.zip
You do not have the required permissions to view the files attached to this post.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11586
Joined: Wed Jan 03, 2018 6:52 pm

Re: Flip tool not working for comments

Post by Daniel - PDF-XChange »

Hello, Mathew

This is not a bug, the trouble here is that technically comments do not contain any property for handling a "flip" according to the PDF specification, so while it is possible to do so, it is potentially problematic, especially when considering items like stamps (which are much more restricted than other comment types), as you mentioned do not work with your script.

I have spoken with the dev team and they are still looking into if whether or not the specification even allows us to implement something like this. The current theory is that we could possibly allow a negative "scale" value to invert the comment, but for the moment the terminology in the flip command is a placeholder for that possibility.

I have made a ticket for tracking this investigation, but I should note that this is not a high priority item.
RT#6375: FR: Investigate "flip" functions for annots

Kind regards,
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 645
Joined: Thu Jun 19, 2014 7:30 pm

Re: Flip tool not working for comments

Post by Mathew »

Thanks Daniel. Yes, the reason I made the script is that I keep running into cases where it would save time to be able to flip (mirror) markup. The script is a workaround, and it does it by moving all the points for polylines and polygons. For the things that it can't transform, it just changes the rotation and position. Here's a slightly updated version. I've attached a zip file with the compiled menu as explained above. Once the problem with gestures gets fixed, I'll post one that also handles them (for now it just rotates them).

Code: Select all

// flip selected annotations
var flipDir; // save dialog response for next time
(function(t) {
var _self;
var flipAnnotations = {
	selAnnots: [],
	initialize: function (anns) {
		if (anns && anns.length>0){
			
			//console.println("Found Annots: "+anns.length);
			this.selAnnots = anns;
			_self = this; // KLUDGE
			if (flipDir == null) {
				flipDir = { horiz: true, vert: false };
			};
			
			return app.execDialog(this.flipDialog);
			
			}else{
			
			return "No Annotations selected.";
		};
		
	},
	doFlip: function () {
		// get bounding box of annotations
		var aRec = this.getBounds(this.selAnnots);
		// get center point of annotations
		var aCtr = [(aRec[0][0]+aRec[1][0])/2,(aRec[0][1]+aRec[1][1])/2];
		// flip the annotations
		this.flipAnns(aCtr,this.selAnnots);		
	},
	// returns array containing [x min, ymin],[x max, y max]
	getBounds: function (anns) {
		var theBounds = [[],[]];
		var aRec = [];
		for (let tAnn in anns) {
			// loop through all selected annotations
			aRec = anns[tAnn].rect; // outer bounds of this annotation
			
			for (let i = 0; i<2; i++) {
				// assign min x value
				if ( typeof theBounds[0][0] == "undefined" || aRec[i*2] < theBounds[0][0] ) {
					theBounds[0][0]=aRec[i*2];
				}
				// assign max x value
				if ( typeof theBounds[1][0] == "undefined" || aRec[i*2] > theBounds[1][0] ) {
					theBounds[1][0]=aRec[i*2];
				}
				// assign min y value
				if ( typeof theBounds[0][1] == "undefined" ||  aRec[i*2+1] < theBounds[0][1] ) {
					theBounds[0][1]=aRec[i*2+1];
				}
				// assign max y value
				if ( typeof theBounds[1][1] == "undefined" ||  aRec[i*2+1] > theBounds[1][1] ) {
					theBounds[1][1]=aRec[i*2+1];
				}
			}
		}
		
		return theBounds;
	},
	// flip a line
	flipLine: function ( flipPt, tPoints) { 
		for (let i=0;i<tPoints.length;i++) {
			tPoints[i] = this.moveLineArray( flipPt, tPoints[i]);
		}
		return tPoints;
	},
	// move points in line array
	moveLineArray ( flipPt, lPoints) {
		// step through array in form [x1,y1,x2,y2,...]
		for (let j=0;j<lPoints.length;j+=2) {
			// flip in x direction
			if (flipDir.horiz) {
				lPoints[j]=flipPt[0]*2-lPoints[j];
				
			}
			// flip in y direction
			if (flipDir.vert) {
				lPoints[j+1]=flipPt[1]*2-lPoints[j+1];
			}
		}
		return lPoints;
	},
	doRotation: function (r) {
		if (flipDir.horiz) r = - r;
		if (flipDir.vert) r = - r;
		return r;
	},
	// flip the annotations
	flipAnns: function (flipPt, anns) {
		var tPoints = [];
		var tRotation = 0;
		for (let tAnn in anns) {
			switch(anns[tAnn].type) {
				case "Line":
					tPoints = this.flipLine(flipPt,anns[tAnn].points);
					 
					// for dimension lines, need to change leaderlength
					if (anns[tAnn].leaderLength && flipDir.vert) {
						anns[tAnn].leaderLength = -anns[tAnn].leaderLength;
					}
					// also, for dimension lines, the point order affects which way up the leader text is

					if ("LineDimension"==anns[tAnn].intent && flipDir.horiz) {
						tPoints = tPoints.slice(1,2).concat(tPoints.slice(0,1));
					}
					anns[tAnn].points = tPoints;
					break;
				case "PolyLine":
				case "Polygon":
					anns[tAnn].vertices = this.flipLine(flipPt,anns[tAnn].vertices);
					anns[tAnn].rotation = this.doRotation( anns[tAnn].rotation );
					break;
				case "FreeText":
					// move callout arrow
					if (anns[tAnn].callout && anns[tAnn].callout.length > 0) {
						anns[tAnn].callout = this.moveLineArray( flipPt, anns[tAnn].callout );
					}
					// no break - need to also move center and rotate, same as other items
				case "Circle":
				case "Stamp":
				case "Text":
				case "Square":
				case "Squiggly":
					// move center
					anns[tAnn].rect = this.moveLineArray( flipPt, anns[tAnn].rect );
					// and rotate
					anns[tAnn].rotation =  this.doRotation( anns[tAnn].rotation );
					break;
				case "Ink":
					console.println("Cannot flip Ink");
				/* BUG: PDF creator reports only the x coordinate as both the x and y coordinate for gestures
					tPoints = anns[tAnn].gestures;
					for (var i in tPoints) {
						tPoints[i] = this.flipLine(flipPt,tPoints[i]);
					}
					anns[tAnn].gestures = tPoints;
				*/
					anns[tAnn].rotation = this.doRotation( anns[tAnn].rotation );
					// get all properties
					for (let i in anns[tAnn]) {
						console.println(i+"  :  "+anns[tAnn][i]);
					}
					break;
			}
			//console.println(anns[tAnn].type);
		}
	},
	// try to figure out up or down based on document rotation
	// I don't know how to determine if the view has been rotated, though, so if view is rotated, this will be wrong
	getUp: function (v, h) {
		var pageDir = {v:v,h:h};
		switch(this.selAnnots[0].doc.getPageRotation( {nPage:this.selAnnots[0].page})) {
			case 90:
			case 270:
				pageDir = {v:h,h:v};
	
		}
		return pageDir;
	},
	// dialog box to ask for mirror direction
	flipDialog: {
		initialize: function (dialog) {
			//var defVert = dialog.store()["vDir"];
			//var defHoriz = dialog.store()["hDir"];
			var dir = _self.getUp(flipDir.vert,flipDir.horiz);
			var defVert = dir.v;
			var defHoriz = dir.h;
			
			dialog.load({ "vDir": defVert, "hDir": defHoriz});
		},
		commit:function (dialog) { // called when OK pressed
			var results = dialog.store();
			// try to figure out which way is up
			var dir = _self.getUp(results["vDir"],results["hDir"]);
			flipDir.vert = dir.v;
			flipDir.horiz = dir.h;
			
			_self.doFlip();	
		},
		description:
		{
			name: "Mirror Annotations", // Dialog box title
			align_children: "align_left",
			width: 350,
			height: 200,
			elements:
			[
				{
					type: "cluster",
					name: "Mirror Direction",
					align_children: "align_left",
					elements:
					[
						{
							type: "check_box",
							name: "Mirror Horizontally",
							//char_width: 25,
							item_id: "hDir"
						},
						{
							type: "check_box",
							name: "Mirror Vertically",
							//char_width: 25,
							item_id: "vDir"
						},
					]
				},
				{
					alignment: "align_right",
					type: "ok_cancel",
					ok_name: "Ok",
					cancel_name: "Cancel"
				}
			]
		}
	}
};

flipAnnotations.initialize(t.selectedAnnots);
})(this);
mirror annotations menu.zip
You do not have the required permissions to view the files attached to this post.
Last edited by Mathew on Tue Jan 17, 2023 11:24 pm, edited 1 time in total.
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11586
Joined: Wed Jan 03, 2018 6:52 pm

Flip tool not working for comments

Post by Daniel - PDF-XChange »

:)
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com
Mathew
User
Posts: 645
Joined: Thu Jun 19, 2014 7:30 pm

Re: Flip tool not working for comments

Post by Mathew »

I posted an updated version of the script here:
viewtopic.php?t=39917
User avatar
Daniel - PDF-XChange
Site Admin
Posts: 11586
Joined: Wed Jan 03, 2018 6:52 pm

Flip tool not working for comments

Post by Daniel - PDF-XChange »

:)
Dan McIntyre - Support Technician
PDF-XChange Co. LTD

+++++++++++++++++++++++++++++++++++
Our Web site domain and email address has changed as of 26/10/2023.
https://www.pdf-xchange.com
Support@pdf-xchange.com