android:pdfdocument:measuringparagraph
measuringparagraph
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 다음 판 | 이전 판 | ||
| android:pdfdocument:measuringparagraph [2024/12/07 09:13] – 만듦 이거니맨 | android:pdfdocument:measuringparagraph [2024/12/09 23:31] (현재) – 이거니맨 | ||
|---|---|---|---|
| 줄 51: | 줄 51: | ||
| totalPOS은 페이지 내의 상대위치가 아닌 절대 위치를 말한다. 그리고 currentPOS은 페이지 내에서의 상대위치를 가리키는 좌표이다. | totalPOS은 페이지 내의 상대위치가 아닌 절대 위치를 말한다. 그리고 currentPOS은 페이지 내에서의 상대위치를 가리키는 좌표이다. | ||
| + | ==== 3. 페이지 내 구역을 살펴보기 ==== | ||
| + | 위와 같이 4개의 꼭지점을 만들어주면 본문의 위치가 결정되고 아래와 같이 각 구역이 나뉘어진다. | ||
| + | {{: | ||
| + | |||
| + | |||
| + | ===== 위치 이동 함수 만들기 ===== | ||
| + | |||
| + | 아래의 두개의 함수로 글자의 위치를 조정할 것이다. | ||
| + | |||
| + | ==== 1. 줄 바뀜 함수 만들기 ==== | ||
| + | |||
| + | 워드프로세서에서 엔터를 치면 줄을 한칸 아래로 내리는 함수를 대충 만들어 보았다. | ||
| + | |||
| + | <code kotlin> | ||
| + | // Line Break : Veritcal Movement | ||
| + | fun linefeed() { | ||
| + | totalPOS += POS(0, 50) | ||
| + | currentPOS += POS(0, 50) | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 2. 스페이스 함수 만들기 ==== | ||
| + | |||
| + | 한칸 오른쪽으로 옮기는 함수를 만들었다. | ||
| + | |||
| + | <code kotlin> | ||
| + | // Space : Horizontal Movement | ||
| + | fun space() { | ||
| + | totalPOS += POS(20, 0) | ||
| + | currentPOS += POS(20, 0) | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== 글자의 경계선 확인하기 ===== | ||
| + | |||
| + | ==== 1. Font metrics 이해 ==== | ||
| + | |||
| + | Android graphics API에서 서체의 픽셀을 다루는 기준선은 아래와 같다(([[https:// | ||
| + | |||
| + | {{: | ||
| + | |||
| + | baseline을 기준(0)으로 위로 갈수록 음수, 아래로 갈 수록 양수라고 한다. | ||
| + | |||
| + | 글자가 baseline보다 아래로 갈 수도 있음을 알 수 있다. | ||
| + | |||
| + | 이에 따라서 글자나 문장의 경계선을 구할 때에도 baseline보다 아래의 위치도 고려해야 한다. | ||
| + | |||
| + | 참고로, leading은 두 줄 이상일 떄 줄간격을 의미한다. | ||
| + | |||
| + | |||
| + | ==== 2. 글자의 높이와 폭을 확인하는 함수 ==== | ||
| + | |||
| + | |||
| + | === 가. getTextWidths === | ||
| + | |||
| + | 각각의 글자의 폭을 개별로 계산해 주는 함수이다. | ||
| + | |||
| + | paint.getTextWidths( String text, float[] widths )(([[https:// | ||
| + | |||
| + | === 나. mesasureText === | ||
| + | |||
| + | float paint.measureText(String text)(([[https:// | ||
| + | |||
| + | 출력하고자 하는 글자들의 전체 폭을 구하는 함수이다. 자간이 존재하므로 measureText는 getTextWidths의 전체 합보다 크다. | ||
| + | |||
| + | |||
| + | 다음 그림은 설명의 편의를 위해 위에서 인용한 블로그에서 가져온 것이다. | ||
| + | |||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | === 다. getTextBounds === | ||
| + | |||
| + | public void getTextBounds (String text, int start, int end, Rect bounds) | ||
| + | |||
| + | |||
| + | 글자들의 전체 경계썬을 구해주는 함수이다. 폭의 경우 measureText와 비슷하지만 문장의 좌우양끝의 자간은 삭제하기 떄문에 measureText보다 결과값이 작다((https:// | ||
| + | |||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | 그런데 경계선을 구해주는 이 함수는 정확히 끝과 끝을 나타내주는 것은 아니다. 아마도 fontmetrics에서 baseline이라는 개념떄문에 그런것 아닌가 싶다. | ||
| + | |||
| + | 그렇기 떄문에 아래에서는 정확히 어떤 부분을 나타내는 지를 확인해보고자 한다. | ||
| + | |||
| + | |||
| + | ==== 3. 글자의 경계확인하는 함수 ===== | ||
| + | |||
| + | 위의 getTextBounds를 통해 다음과 같이 상자와 선을 그려 보았다. | ||
| + | |||
| + | === 가. 상자와 선을 그리는 함수 === | ||
| + | |||
| + | 다음과 같이 상자와 선을 그리는 함수를 만들었다. | ||
| + | |||
| + | <code kotlin> | ||
| + | // Text with underline, rectangle, outline | ||
| + | fun richText(text : String, canvas: Canvas, switch : String) { | ||
| + | title.setTypeface(fontStrawberry) | ||
| + | title.color = ContextCompat.getColor(context, | ||
| + | title.textSize = 16f | ||
| + | title.textAlign = Paint.Align.LEFT | ||
| + | |||
| + | // Draw Text | ||
| + | canvas.drawText(text, | ||
| + | |||
| + | // Font Effect | ||
| + | when (switch) { | ||
| + | " | ||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | val rc = Rect(currentPOS.X, | ||
| + | |||
| + | canvas.drawRect(rc, | ||
| + | } | ||
| + | " | ||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | canvas.drawLine(currentPOS.X.toFloat(), | ||
| + | |||
| + | canvas.drawText(" | ||
| + | } | ||
| + | " | ||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | canvas.drawLine(currentPOS.X.toFloat(), | ||
| + | |||
| + | canvas.drawText(" | ||
| + | } | ||
| + | " | ||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | canvas.drawLine(currentPOS.X.toFloat(), | ||
| + | |||
| + | canvas.drawText(" | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | } | ||
| + | </ | ||
| + | |||
| + | getTextBounds에서 top과 bottom, 그리고 줄의 높이인 height()가 어떻 결과값을 나타내는지 확인하게 만들었다. | ||
| + | |||
| + | |||
| + | === 나. 호출하기 === | ||
| + | |||
| + | |||
| + | 다음과 같이 호출하였다. | ||
| + | |||
| + | <code kotlin> | ||
| + | // 상자만들기 | ||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.titleText(" | ||
| + | |||
| + | pdfUtil.space() | ||
| + | // 선을 그리기 | ||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | 아래 그림은 각각 [[http:// | ||
| + | |||
| + | |||
| + | ^ 고령딸기체 | ||
| + | | {{: | ||
| + | |||
| + | |||
| + | LineHeight()로 줄의 높이를 정하는게 가장 시인성 있는 것을 알 수 있다. 따라서 앞으로는 이를 기준으로 글자의 높이를 정하겠다. | ||
| + | |||
| + | |||
| + | ===== 결론 ===== | ||
| + | |||
| + | ==== 1. Rich Text ==== | ||
| + | |||
| + | 다음과 같이 Rich Text를 구현할 수 있다. | ||
| + | |||
| + | <code kotlin> | ||
| + | // Text with underline, rectangle, outline, shadow | ||
| + | fun richText(text : String, canvas: Canvas, switch : String) { | ||
| + | title.setTypeface(fontKJCMyungjo) | ||
| + | title.color = ContextCompat.getColor(context, | ||
| + | title.textSize = 16f | ||
| + | title.textAlign = Paint.Align.LEFT | ||
| + | |||
| + | // Font Effect | ||
| + | when (switch) { | ||
| + | " | ||
| + | // Draw Text | ||
| + | canvas.drawText(text, | ||
| + | |||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | val offset = 2 | ||
| + | val rc = Rect(currentPOS.X - offset, currentPOS.Y - bounds.height() + offset, currentPOS.X + bounds.right + offset, currentPOS.Y + bounds.bottom + offset) | ||
| + | |||
| + | canvas.drawRect(rc, | ||
| + | } | ||
| + | " | ||
| + | // Draw Text | ||
| + | canvas.drawText(text, | ||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | val offset = 2f | ||
| + | canvas.drawLine(currentPOS.X.toFloat() - offset, currentPOS.Y.toFloat() + bounds.bottom + offset, currentPOS.X + bounds.right.toFloat() + offset, currentPOS.Y + bounds.bottom + offset, linePaint) | ||
| + | |||
| + | canvas.drawText(" | ||
| + | } | ||
| + | " | ||
| + | // Draw Text | ||
| + | canvas.drawText(text, | ||
| + | |||
| + | val bounds = Rect() | ||
| + | title.getTextBounds(text, | ||
| + | val offset = 2f | ||
| + | canvas.drawLine(currentPOS.X.toFloat() - offset, currentPOS.Y.toFloat() - (bounds.height() / 2).toFloat() + bounds.bottom, | ||
| + | |||
| + | canvas.drawText(" | ||
| + | } | ||
| + | " | ||
| + | // draw outline of text | ||
| + | title.style = Paint.Style.FILL_AND_STROKE | ||
| + | title.strokeWidth = 1f | ||
| + | title.color = ContextCompat.getColor(context, | ||
| + | |||
| + | canvas.drawText( text, currentPOS.X.toFloat(), | ||
| + | } | ||
| + | " | ||
| + | // draw outline of text | ||
| + | title.style = Paint.Style.STROKE | ||
| + | title.strokeWidth = 0.5f | ||
| + | title.color = ContextCompat.getColor(context, | ||
| + | |||
| + | canvas.drawText( text, currentPOS.X.toFloat(), | ||
| + | } | ||
| + | " | ||
| + | title.style = Paint.Style.FILL | ||
| + | title.strokeWidth = 1f | ||
| + | title.setShadowLayer(1f, | ||
| + | canvas.drawText( text, currentPOS.X.toFloat(), | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 2. 예시 ==== | ||
| + | |||
| + | 위의 글자꾸미기는 다음과 같이 PDF로 인쇄된다. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | |||
| + | <code kotlin> | ||
| + | pdfUtil.space() | ||
| + | // 선을 그리기 | ||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | pdfUtil.linefeed() | ||
| + | pdfUtil.richText(" | ||
| + | |||
| + | </ | ||
android/pdfdocument/measuringparagraph.1733530432.txt.gz · 마지막으로 수정됨: 저자 이거니맨
