android:pdfdocument:sectioning
sectioning
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판이전 판다음 판 | 이전 판 | ||
android:pdfdocument:sectioning [2024/12/16 11:46] – 이거니맨 | android:pdfdocument:sectioning [2024/12/24 20:00] (현재) – 이거니맨 | ||
---|---|---|---|
줄 17: | 줄 17: | ||
===== 구역화하기 ===== | ===== 구역화하기 ===== | ||
- | ==== 1. 각 구역의 | + | ==== 1. 절대 좌표 |
- | 일단 | + | 다음과 같이 |
<code kotlin> | <code kotlin> | ||
+ | // Rect 좌표와 너비 높이 | ||
+ | data class PNL(private val rect : Rect = Rect(0, 0, 100, 100), private | ||
+ | { | ||
+ | var rectP = rect | ||
+ | var Width = width | ||
+ | var Height = height | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 2. 각 구역의 절대 좌표 기억하기 ==== | ||
+ | |||
+ | A4종이에서 본문을 중심으로 한 각 마진을 구한 후, 이를 기초로 하여 본문 지역의 위치 속성을 다음과 같이 지정했다. | ||
+ | |||
+ | <code kotlin> | ||
+ | // creating a PDF Document instance | ||
+ | val pdfDocument: | ||
+ | // 여백 | ||
+ | val marginTop = 42 | ||
+ | val marginBottom = 50 | ||
+ | val marginLeft = 47 | ||
+ | val marginRight = 48 | ||
+ | |||
// 각 구역 좌표 | // 각 구역 좌표 | ||
- | | + | |
- | val footerSection = Rect(0, PDF_PAGE_HEIGHT - marginBottom, | + | |
- | val bodySection = Rect(marginLeft, | + | |
- | val leftSection = Rect(0, marginTop, | + | |
- | val rightSection = Rect(PDF_PAGE_WIDTH - marginRight, | + | |
</ | </ | ||
+ | ===== 구역화를 할 때 고려해야 할 문제점 ===== | ||
- | ==== 2. 비트맵으로 저장하고 | + | 안드로이드의 기본 PDF API(android.graphics.pdf)를 이용하여 pdf문서를 만들고자 할 때의 가장 큰 문제점은, |
- | ^ 비트맵으로 그린 본문 ^^ | + | pdf의 페이지 작성 및 캔버스 그리기는 모두 일방향이라는 것이었다. |
+ | |||
+ | 즉, 페이지를 먼저 만들면, 그 페이지 안에 canvas가 이미 지정되어 있고, 그 캔버스 안에 그림을 그리는 방식이다. | ||
+ | |||
+ | 예를 들면 다음과 같다((https:// | ||
+ | |||
+ | <code kotlin> | ||
+ | // creating a PDF Document instance | ||
+ | val pdfDocument: | ||
+ | |||
+ | // create a page description | ||
+ | val myPageInfo: PdfDocument.PageInfo = | ||
+ | PdfDocument.PageInfo.Builder(PDF_PAGE_WIDTH, | ||
+ | |||
+ | // start a page | ||
+ | val newPage: PdfDocument.Page = pdfDocument.startPage(a4Paper(pageNum + 1)) | ||
+ | |||
+ | // start canvas | ||
+ | val canvas = newPage.canvas | ||
+ | |||
+ | // draw something on the page | ||
+ | canvas.draw(....) | ||
+ | |||
+ | // finish the page | ||
+ | pdfDocument.finishPage(page); | ||
+ | . . . | ||
+ | |||
+ | // add more pages | ||
+ | . . . | ||
+ | // write the document content | ||
+ | pdfDocument.writeTo(getOutputStream()); | ||
+ | |||
+ | // close the document | ||
+ | pdfDocument.close(); | ||
+ | </ | ||
+ | |||
+ | |||
+ | 위와 같이 | ||
+ | |||
+ | 따라서 어떤 식으로 하든, 이미 만들어진 canvas를 pdf page에 복사할 수가 없다. | ||
+ | |||
+ | |||
+ | 그래서 고민끝에 생각해낸 해결책은 다음의 세가지이다. | ||
+ | |||
+ | 첫째, 안드로이드에서 제공하는 pdf graphics api가 아닌, | ||
+ | |||
+ | 둘째, canvas는 비단 pdf page로만 만들 필요가 없다. | ||
+ | |||
+ | |||
+ | 셋째, 본문 영역에 대한 pdf를 만든 후에, 이 작업을 모두 기억했다가 다시 헤더와 푸터가 포함되어 있는 [[android: | ||
+ | |||
+ | |||
+ | |||
+ | ===== 비트맵으로 저장하고 그리기 ===== | ||
+ | |||
+ | ==== 1. 비트맵 파일 배열 만들기 ==== | ||
+ | |||
+ | 다음과 같이 비트맵 그림으로 저장할 배열을 만들 수 있다. | ||
+ | |||
+ | <code kotlin> | ||
+ | // 비트맵 및 캔버스 리스트 만들기 | ||
+ | val bitmapList : ArrayList< | ||
+ | val canvasList : ArrayList< | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== 2. 페이지가 바뀔 때마다 비트맵을 새로 만들고 배열에 추가하기 ==== | ||
+ | |||
+ | 이런 식으로 페이지가 바뀔 때마다 비트맵을 배열에 추가하는 것이다. | ||
+ | |||
+ | <code kotlin> | ||
+ | // 캔버스 시작하기 | ||
+ | fun beginCanvas() { | ||
+ | bitmapList.add(Bitmap.createBitmap(body.Width, | ||
+ | canvasList.add(Canvas(bitmapList[0])) | ||
+ | |||
+ | pageNum = 0; | ||
+ | totalPOS = POS(0, 0) | ||
+ | currentPOS = POS(0, 0) | ||
+ | } | ||
+ | |||
+ | // Next Page | ||
+ | fun nextPage() { | ||
+ | |||
+ | val newNum = totalPOS.Y / body.Height | ||
+ | |||
+ | if (newNum > pageNum) { | ||
+ | pageNum = newNum | ||
+ | currentPOS.Y = 20 | ||
+ | |||
+ | bitmapList.add(Bitmap.createBitmap(body.Width, | ||
+ | canvasList.add(Canvas(bitmapList[pageNum])) | ||
+ | |||
+ | |||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 3. 그리기 함수들 ==== | ||
+ | |||
+ | 각 그리기 함수에는 캔버스의 배열 번호를 지정해주면 될 것이다. | ||
+ | |||
+ | 예를들면 다음과 같다. | ||
+ | |||
+ | <code kotlin> | ||
+ | // Draw Title Text | ||
+ | fun titleText(text : String) { | ||
+ | |||
+ | nextPage() | ||
+ | linefeedBig() | ||
+ | canvasList[pageNum].drawText(text, | ||
+ | linefeedBig() | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === 4. PDF 페이지 만들기 ==== | ||
+ | |||
+ | 이렇게 만든 그림들을 canvas의 drawbitmap을 이용하여 본문 부분을 비트맵으로 그리면 된다. | ||
+ | |||
+ | <code kotlin> | ||
+ | // PDF 페이지 만들기 | ||
+ | fun makePDFDocument() { | ||
+ | |||
+ | for (i in 0 until canvasList.size) { | ||
+ | val newPage: PdfDocument.Page = pdfDocument.startPage(a4Paper(pageNum + 1)) | ||
+ | |||
+ | val canvas = newPage.canvas | ||
+ | |||
+ | drawPageHeader(canvas) | ||
+ | canvas.drawBitmap(bitmapList[i], | ||
+ | drawPageFooter(canvas, | ||
+ | pdfDocument.finishPage(newPage) | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== 5. 헤더와 푸터 ==== | ||
+ | |||
+ | 참고로, 머리말과 꼬리말은 다음과 같이 만들었다. | ||
+ | |||
+ | <code kotlin> | ||
+ | private fun drawPageHeader(canvas: | ||
+ | canvas.drawText(" | ||
+ | canvas.drawLine(20f, | ||
+ | } | ||
+ | |||
+ | private fun drawPageFooter(canvas: | ||
+ | canvas.drawLine(20f, | ||
+ | canvas.drawText( i.toString() + " / " + canvasList.size , (PDF_PAGE_WIDTH - 30).toFloat(), | ||
+ | canvas.drawText(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | === 6. 결론 ==== | ||
+ | |||
+ | 이렇게 하면 머릿말과 꼬릿말은 pdf로 그린 것이지만, | ||
+ | |||
+ | 그래서 머릿말과 꼬릿말은 확대를 해도 글자가 깨지지 않지만 본문 부분은 확대를 하면 깨지는 것을 볼 수 있다. | ||
+ | |||
+ | |||
+ | ^ 비트맵으로 그린 본문 | ||
| {{: | | {{: | ||
+ | |||
+ | |||
+ | |||
+ | 따라서 이러한 방식이 그다지 좋은 것은 아님을 알 수 있다. | ||
+ | |||
+ | 이에 지금까지 했던 일을 기억 한 후에 다시 벡터로 그리는 방식을 채택하기로 했다. | ||
+ | |||
+ | 이에 대해서는 [[android: |
android/pdfdocument/sectioning.1734317161.txt.gz · 마지막으로 수정됨: 2024/12/16 11:46 저자 이거니맨