1. Summarize the problem:
I'm trying to draw annotations on PdfPage in iOS from a sample JSON data like this:
"annotations": [
{
"id": "1024",
"start_x": 1.60162,
"start_y": 565.139,
"end_x": 131.333,
"end_y": 610.398,
"page": 1
},
]
The API side understands that a pdf page coordinate system always has its origin at the bottom-left corner of the visible page regardless of its rotation angles. Therefore it's expected that with the above JSON the annotation will be drawn near the top-left corner of the page. I've highlighted both the API coordinate system and the expected annotation position in yellow color.
The PDFKit.PdfPage has a rotation property that cause both the page and its coordinate system rotated (highlighted in green color). The rotation property of PdfPage on iOS increase clockwise. As shown in the image, the pdfPage.rotation = 90 and the annotion is drawn rotated. The sample pdf show in the image has 2 pages where page no. 2 (shown near the first section of the image above the red line) has its rotation = 0 so annotions are drawn exactly as expected from JSON data response.
With that being said, I need to adress two main problems to draw an upright annotation on a rotated pdf page:
- Problem #1: The green rectangle annotation need to be rotated and/or translated to its expected position regardless of the page's rotation. In this case the page's rotation is 90 degree and its coordinate origin is at the top-left corner, but it can be 180 degree rotation with origin at top-right corner and 270 degree rotation with origin at bottom right corner. The API side always nail the coordinate origin at the bottom-left of the visible page regardless of the page's rotation and can response annotation positions anywhere on the visible page.
- Problem #2: The text "Sample Anno" also needs to be drawn upright according to API's coordinate system and again, regardless of the page's rotation angles. Currently I'm using a PDFKit.pdfAnnotation to draw a bound of type CGRect, set it background color to green and its contents is "Sample Anno". Inside this annotation I draw a UILabel which fit inside the specified bound and it's drawing upright according to the page's coordinate system.
2. What I've tried:
First thing that come to my mind is set pdfPage.rotation to "0" and run but it also rotate the whole visible page, and this does not qualified to my expected result because the page needs to keep its current rotation angle to match with response from API.
Then I've tried to rotate the annotation bound using this formula, with the rotation of 53 degree (purely random) around the anchor point is A (center of the page's media box) as show in the bottom section of the image, the bound is rotated horizontally but still far from the expected position which is highlighted in yellow color. And this approach also make the text smaller because it still being drawn upright according to page's rotation and needs to fit inside the new bound (problem #2). Now I'm using CGAffineTransform.MakeRotation() and context.RotateCTM() functions from this answer to problem #2 but so far the text disappear.
I also have thought of proposing the API side coordinate system to change according to pdfkit rotation but that would be double the work since this problem is unique to iOS and both the web and Xamarin.Android are drawing annotation the same way.
3. My questions are:
Q1: Are there any general rules or formulas that can convert a point from any pdfPage.rotation coordinate system (be it 90, 180 or 270) to the bottom-left coordinate system?
Q2: If the answer to Q1 is none. How can I draw both annotation bound and text upright in each of the three pdfPage.rotation angle? Because each rotation angle has differnt effect on how the annotation is drawn. For example with 180 degree rotation angle, annotation that expected to be on the top left of the page will be flipped and rotated to the bottom-right area of this page. 270 degree rotation is similar to 90 degree rotation but the difference is that annotation is rotated counter-clockwise.
I'm developing this in Xamarin.iOS so answers in both C# and Swift are great. Thank you guys so much!