2012-03-10 3 views
2

긴 문자열을 페이지에 배치하는 경우 CTFramesetterCreateFrame을 사용하여 CTFrameRef을 만들고 다음에 생성 할 문자열의 시작 색인을 앞으로 이동하십시오. CTFrameRef. 이것은 시작 인덱스가 앞으로 이동하기 때문에 쉽고 Core Text API는 이러한 종류의 레이아웃을 기본적으로 지원합니다.코어 텍스트를 사용하여 텍스트를 거꾸로 배치하는 방법은 무엇입니까?

이제는 내가 원하는 상황에 갇혀있다. 이전 페이지로 돌아 가기.

예를 들어 긴 문자열의 길이가 1000이고 현재 현재 페이지 (또는 CTFrameRef)의 시작 인덱스가 500이고 이전 페이지로 돌리고 싶습니다. 어떤 인덱스를 시작할 지 어떻게 알 수 있습니까? 각 페이지에 대한 모든 인덱스를 캐싱 할 수 없거나 문자열 시작 부분부터 계산할 수 없으므로 문자열이 메모리에 맞지 않는 매우 길어질 수 있습니다 (블록별로 파일 블록에서 문자열을 읽어야 함) . CT* API를 스캔했지만 텍스트를 거꾸로 배치 할 수있는 API는 없습니다.

이것에 대한 아이디어가 있습니까?

답변

1

API가없는 이유는 가장 좋은 시작 인덱스를 찾기 위해 시행 착오를 통해 전체 페이지를 조판하려고하는 것보다 효율적인 컨텍스트 독립적 인 방법이 없다는 것입니다. 집중적 인 작업. 텍스트의 각 페이지가 설정 폭을 가지고 있으며, 단지 직사각형 CTFrame 경우

, 이것은 당신이 할 수있는 방법 :

는 는
  1. "견적은"이전 페이지의 캐릭터 범위 (예를 들어, 그것이 가지고 가정 현재 페이지와 같은 길이
  2. 합리적인 큰 요인 (예 : 길이의 1.5/2x)으로 예상되는 오버 슛 오버 슛 범위를 선택하여 단락의 시작 부분에서 시작되도록
  3. 일반적으로 그 범위로 프레임을 만들지 만 프레임이 평소보다 훨씬 커야합니다.
  4. 프레임에서 선 정보를 가져오고 끝에서부터 한 줄씩 뒤로 이동하여 높이를 계산합니다.
  5. 실제 이전 페이지는 맞는 첫 번째 줄의 색인에서 시작하여 실제 CTFrame을 만드는 데 사용할 수 있습니다.

그래도 가능하지만 가능하면이 문제를 피하는 방법을 찾아 보시기 바랍니다. 더 복잡한 페이지 매김 알고리즘을 사용하자마자 분해되며,이 경우에도 1.5/2x 메모리가 사용됩니다. 여기에 당신이 할 수있는 방법에 대한 몇 가지 제안은 다음과 같습니다. (적어도 현재 위치까지) 인덱스

  1. 캐시는 각 페이지 아마 저장할 수 ~ 1000 자, 그래서 캐시 크기가 0.1 %가 될 것입니다 전체 텍스트의 크기이며 처음 텍스트를 표시 할 때 적어도 한 번은해야합니다. n 페이지마다 색인을 저장하여 캐시를 더 작게 만들 수 있습니다.

  2. 적용되는 경우 문자열을 논리적 부분 문자열로 나눕니다 (예 : 페이지 나누기 또는 섹션 나누기를 기반으로). 그런 다음 페이지 범위에 대해 각 부분 문자열을 전체적으로 조판합니다.

+0

감사합니다. @mohsenr, 제 질문은 마침내 대답을 얻었습니다. 나는 이미 첫 번째 제안과 99 % 동일한 방법을 시도하고 있었다. 이전 페이지의 문자열 범위를 1로 추정하는 것이 아닙니다.현재 페이지의 길이의 5 배/2 배로, 페이지에 1000 개의 'a'가 포함되어 있으면 페이지에 반복적으로 한 개의 문자 만 포함될 것이라고 가정했습니다. CTFrame을 만들고 4, 5 번에서 제안한 것을하십시오. – neevek

+0

두 번째 제안은 첫 번째 제안보다 좋지 않습니다. 텍스트 크기 나 글꼴이 변경되면 캐시가 깨지고 ** 인덱스를 다시 작성하는 데 비용이 많이 듭니다 **. * 다음 페이지를 돌릴 때 * n * 페이지에 대한 표시를 캐시 할 수 있지만 캐시에 항상 의존 할 수는 없습니다. 어쨌든, 당신은 안드로이드의'Paint.breakText()'의 아이폰 OS에 상응하는 것이 없다고 대답했다. – neevek

관련 문제