TextLayout 클래스

TextLayout 클래스

TextLayout은 스타일이 적용된 문자 데이터의 변경 불가능한(immutable) 그래픽 표현이에요. 다음과 같은 기능을 제공해요.

  • 암묵적 양방향 분석과 재정렬
  • 커서 위치 지정·이동(혼합 방향 텍스트의 분할 커서 포함)
  • 강조 표시(혼합 방향 텍스트의 논리·시각 강조)
  • 여러 기준선(로만, 매달림, 중앙)
  • 히트 테스트
  • 정렬(justification)
  • 기본 글꼴 대체
  • ascent, descent, advance 같은 메트릭 정보
  • 렌더링

출처: Java API Reference

본문

TextLayout 객체는 draw 메서드로 렌더링할 수 있어요. 직접 구성하거나 LineBreakMeasurer를 통해 구성할 수 있어요. 직접 구성할 때 원본 텍스트는 단락 하나를 나타내요. LineBreakMeasurer는 스타일 텍스트를 특정 폭 안에 들어맞는 줄로 나눌 수 있게 해요.

public final class TextLayout
extends Object
implements Cloneable

구성 과정

TextLayout 구성은 논리적으로 다음과 같이 진행돼요.

  1. 단락 속성을 추출·검사해요.
  2. 텍스트를 양방향 재정렬을 위해 분석하고 필요하면 재정렬 정보를 계산해요.
  3. 텍스트를 스타일 실행(run)으로 분할해요.
  4. 스타일 실행에 글꼴을 선택해요. TextAttribute.FONT 속성이 있으면 그 글꼴을, 아니면 정의된 속성으로 기본 글꼴을 계산해요.
  5. 텍스트가 여러 기준선에 있으면 실행·부분 실행을 공통 기준선을 공유하는 부분 실행으로 더 나눠요.
  6. 선택한 글꼴로 각 실행에 글리프벡터를 생성해요.
  7. 글리프벡터에 최종 양방향 재정렬을 수행해요.

좌표계

TextLayout 메서드가 반환하는 모든 그래픽 정보는 TextLayout의 원점(기준선과 왼쪽 가장자리의 교점)에 상대적이에요. 클라이언트는 보통 TextLayout 좌표계와 다른 객체(예: Graphics)의 좌표계 사이를 변환해야 해요.

TextLayout은 스타일 텍스트로 구성되지만 원본 텍스트에 대한 참조를 유지하지 않아요. 그래서 이전에 TextLayout을 만드는 데 사용한 텍스트가 바뀌어도 TextLayout에는 영향이 없어요.

getNextRightHit, getNextLeftHit, hitTestChar 세 메서드는 TextHitInfo 인스턴스를 반환하는데, 이 오프셋은 TextLayout의 시작에 상대적이에요.

사용 예제

Graphics2D g = ...;
Point2D loc = ...;
Font font = Font.getFont("Helvetica-bold-italic");
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout("This is a string", font, frc);
layout.draw(g, (float)loc.getX(), (float)loc.getY());

주요 메서드

  • draw(Graphics2D, float, float) — 레이아웃을 그려요.
  • getBounds() — 레이아웃의 경계 사각형을 반환해요.
  • hitTestChar(float, float) — 특정 그래픽 위치의 문자 히트를 반환해요.
  • getCaretShapes(int) — 삽입 위치의 커서 모양 Shape 배열을 반환해요.
  • getNextRightHit(int) / getNextLeftHit(int) — 다음 커서 위치의 히트를 반환해요.
  • getLogicalHighlightShape(int, int) / getVisualHighlightShape(TextHitInfo, TextHitInfo) — 선택 범위 모양을 반환해요.
  • getAscent() / getDescent() / getLeading() / getAdvance() — 메트릭을 반환해요.

좌표계 유의

글꼴 회전으로 텍스트 기준선이 회전하고, 서로 다른 회전을 가진 여러 실행이 기준선을 구부리거나 지그재그로 만들 수 있어요. 이런 드문 가능성을 다루기 위해 일부 API는 측정 값을 '기준선 상대 좌표'(예: ascent, advance)로, 다른 API는 '표준 좌표'(예: getBounds)로 반환해요. 일반적으로 측정 관련 API는 기준선 상대 좌표, 표시 관련 API는 표준 좌표예요.

더 알아보기