2011-04-08 9 views
7

내 목표 : IDWriteTextFormat 글꼴의 높이를 가져 와서 특정 높이의 IDWriteTextLayout에 맞는 텍스트 줄 수를 계산할 수 있습니다.직접 쓰기 : 글꼴 높이 가져 오기

내 문제 : 트루 타입의에 대한

inline int kmTextCtrl::GetVisLines() const 
{ 

    /* pTextFormat is an IDWriteTextFormat pointer, dpi_y is the desktop's vertical dpi, 
     and GetHeight() returns the height (in pixels) of the render target. */ 
    float size = (pTextFormat->GetFontSize()/72.0f)*dpi_y; 
    return (int)(GetHeight()/size); 
} 

계산이 일부 글꼴에 대한 정확한 것 같다,하지만 : 오른쪽 지금은 라인의 보이는 수를 계산하기 위해이 코드를 사용하고 있습니다 글꼴 (예 : Courier New, Arial, Times New Roman). 이 글꼴의 경우 표시된 텍스트는 렌더링 대상의 수직 경계 아래에 잘립니다.

일부 컨텍스트 : 나는 텍스트 컨트롤의 렌더 타겟에 텍스트를 넣어하는 IDWriteTextLayout을 사용하여 버퍼 제어를 다시 스크롤 만드는 중이라서 . GetVisLines()의 결과를 사용하여 원형 버퍼 (선에 의해 std :: strings에 텍스트를 저장함)에서 얼마나 많은 텍스트 행을 가져와 레이아웃 안으로 끌어오고 창을 스크롤하거나 크기를 조정할 때마다 다시 만들 것인지 결정합니다.

"기본"Win32 API C++를 사용하여 수행됩니다.

답변

6

나는 answer을 발견했습니다. 이의 DirectWrite에서 선 (글꼴 높이를 더한 격차)의 간격을 찾으려면 다음에 유사한 일을 수행해야합니다 물론

inline int kmTextCtrl::GetVisLines() const 
{ 

    IDWriteFontCollection* collection; 
    TCHAR name[64]; UINT32 findex; BOOL exists; 
    pTextFormat->GetFontFamilyName(name, 64); 
    pTextFormat->GetFontCollection(&collection); 
    collection->FindFamilyName(name, &findex, &exists); 
    IDWriteFontFamily *ffamily; 
    collection->GetFontFamily(findex, &ffamily); 
    IDWriteFont* font; 
    ffamily->GetFirstMatchingFont(pTextFormat->GetFontWeight(), pTextFormat->GetFontStretch(), pTextFormat->GetFontStyle(), &font); 
    DWRITE_FONT_METRICS metrics; 
    font->GetMetrics(&metrics); 
    float ratio = pTextFormat->GetFontSize()/(float)metrics.designUnitsPerEm; 
    float size = (metrics.ascent + metrics.descent + metrics.lineGap) * ratio; 
    float height = GetHeight(); 
    int retval = static_cast<int>(height/size); 
    ffamily->Release(); 
    collection->Release(); 
    font->Release(); 
    return retval; 
} 

, 당신은 아마 당신이 가진 모든 것을마다하고 싶지 않아 자주 사용되는 인라인 함수를 호출합니다.

+0

이것은 분명히 잘못된 접근입니다. 적절한 해결책에 대한 드웨인의 반응을보십시오. – bunglehead

+0

@bunglehead 왜 이것이 잘못된가요? 너무 많은 가정을하기 때문에 @DmitriNesteruk. –

+0

예를 들어 실제 텍스트 데이터에 따라 나중에 다른 글꼴을 사용할 수 있다는 것을 고려하지 않고도 선을 측정하기 시작합니다. 다음으로 라인 간격 모드를 무시하고 레이아웃이 (ascent + descent + lineGap)으로 공간을 계산하는 방식을 가정합니다. 위의 정격 응답을 참조하십시오. 왜 이것이 신뢰할 수없는 솔루션인지 더 잘 설명합니다. – bunglehead

8

가장 간단하고 강력한 방법은 텍스트 메트릭을 레이아웃 자체에 묻는 것입니다. 텍스트 메트릭스는 드로잉과 측정을 위해 설계된 두 가지 중 하나입니다. 텍스트 형식을 사용하여 IDWriteTextLayout을 만들고 GetMetrics으로 전화하여 DWRITE_TEXT_METRICS::height을 얻습니다. ID2D1RenderTarget::DrawText을 사용하고 텍스트 형식을 전달하는 것 같아서 직접 레이아웃을 만들지는 않았지만 DrawText을 호출하면 CreateTextLayout을 직접 호출하고 DrawTextLayout을 입력하는 것과 같습니다.

이 답변 (IDWriteFontFace 등)을 얻으려면 하위 레이어를 통과하는 것이 기본 세계 준비 텍스트 컨트롤이 가정해서는 안된다는 가정을해야합니다. 예를 들어 기본 글꼴이 사용되고 모든 라인이 같은 높이. 모든 문자가 주어진 기본 글꼴에 존재하는 한,이 방법이 효과가 있습니다 (대부분 영어가 표시되어 모든 것이 잘 나타나는 경우), 일부 CJK 또는 RTL 언어를 사용합니다 (Times New Roman은 확실히 지원하지 않습니다.), 대체 글꼴에 따라 줄 높이가 커지거나 작아집니다. GDI는 대체 글꼴을 기본 글꼴의 높이에 맞도록 재조정하지만, 오름차순 및 내림차순으로 더 많은 호흡 공간이 필요한 태국어 및 티벳어 같은 언어에서는 문자가 제대로 표시되지 않습니다. IDWriteTextLayout과 WPF/Word의 레이아웃과 같은 다른 레이아웃은 모든 글꼴 모양을 같은 크기로 유지합니다. 즉, 서로 인접 할 때 더 잘 정렬됩니다. 그러나 라인 높이가 가변적이라는 것을 의미합니다.

각 텍스트 줄이 모두 같은 높이 인 것처럼 그리면 선 사이의 글리프와 기준이 아닌 기준선 사이의 겹침 또는 컨트롤의 위쪽과 아래쪽에서의 자르기를 볼 수 있습니다.그래서 이상적인 일은 각 줄의 실제 높이를 사용하는 것입니다. 그러나 모두 같은 높이 (또는 컨트롤을 너무 복잡하게 만드는 경우)가 필요하면 SetLineSpacing을 사용하여 DWRITE_LINE_SPACING_UNIFORM을 사용하여 기본 글꼴의 줄 간격을 명시 적으로 설정하십시오. 이렇게하면 기준선이 균등하게 배치됩니다.

호기심에 따라, 라인 높이는 실제로 글꼴 디자인 메트릭 ascent + descent와 함께 존재하는 모든 lineGap을 사용하여 결정됩니다 (대부분의 글꼴은이 값을 0으로 설정하지만 Gabriola는 큰 줄 간격), em 크기에 곱한 값과 em 단위로 나눈 값. 모든 em 크기는 DIP (일반 96DPI는 1 : 1, DIP는 정확히 == 픽셀을 의미), 점 (1/72 인치)이 아닙니다.

관련 문제