=================================
=================================
=================================
출처: http://soen.kr/lecture/library/freetype/ft2.htm
2.문자 출력
가.초기화
어떤 과목이든지 첫 예제가 어렵다. 과연 FreeType이 잘 동작하는지 첫번째 예제를 만들어 보되 첫 예제이니만큼 딱 한글자만 출력해 보자. 이 정도 예제에 특별한 기능이 필요치도 않고 UI도 단순하므로 간단하게 Win32 프로젝트로 작성하기로 한다. 이런 예제에 MFC나 닷넷을 동원할 필요가 없다.
C 드라이브의 루트에 FreeTypeExam이라는 예제 폴더를 만들고 이 안에 PrintOneChar라는 이름으로 Win32 프로젝트를 만들었다. 옵션에서 빈 프로젝트를 선택하고 마침 버튼을 누른다. 그리고 PrintOneChar.cpp 파일을 추가한 후 다음 소스를 작성한다.
예 제 : PrintOneChar |
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("PrintOneChar");
#include <ft2build.h>
#include FT_FREETYPE_H
FT_Library library;
#pragma comment(lib, "..\\..\\freetype237MT.lib")
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
, LPSTR lpszCmdParam, int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst = hInstance;
// 라이브러리 초기화
if (FT_Init_FreeType( & library)) {
MessageBox(NULL, TEXT("FreeType 라이브러리 초기화 실패"),
TEXT("에러"), MB_OK);
return -1;
}
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc;
WndClass.lpszClassName = lpszClass;
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass( & WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU) NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
while (GetMessage( & Message, NULL, 0, 0)) {
TranslateMessage( & Message);
DispatchMessage( & Message);
}
// 라이브러리 정리
FT_Done_FreeType(library);
return (int) Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int error;
FT_Face face;
unsigned index;
int x, y;
int Color;
int width, height;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, & ps);
// 폰트 읽음
error = FT_New_Face(library, "c:\\windows\\fonts\\batang.ttc", 2, & face);
if (error != 0) {
// 에러 처리
}
// 글리프 인덱스 구함
index = FT_Get_Char_Index(face, TEXT('형'));
if (index == 0) {
// 에러 처리
}
// 크기 설정
error = FT_Set_Char_Size(face, 256 * 64, 0,
GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
// 글리프 로드
error = FT_Load_Glyph(face, index, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
// 랜더링
error = FT_Render_Glyph(face - > glyph, FT_RENDER_MODE_NORMAL);
// 화면으로 출력
width = face - > glyph - > bitmap.width;
height = face - > glyph - > bitmap.rows;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
Color = 255 - face - > glyph - > bitmap.buffer[y * width + x];
if (Color != 255) {
SetPixelV(hdc, 0 + face - > glyph - > bitmap_left + x,
300 - face - > glyph - > bitmap_top + y, RGB(Color, Color, Color));
}
}
}
FT_Done_Face(face);
EndPaint(hWnd, & ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}
전체적인 구조나 사용 절차는 지극히 상식적이다. 먼저 라이브러리가 정의하는 타입 선언을 위해 필요한 헤더 파일을 인클루드한다. ft2build.h와 FT_FREETYPE_H를 인클루드하는데 이 두 줄은 거의 예외없이 포함해야 한다. FreeType은 헤더 파일명을 매크로로 정의하는데 ft2build.h는 실제 어떤 타입을 정의하는 것이 아니라 헤더 파일에 대한 매크로를 정의한다. FT_FREETYPE_H는 다음과 같이 정의되어 있다.
#define FT_FREETYPE_H <freetype/freetype.h>
헤더 파일명을 굳이 매크로로 정의한 이유는 이전 버전이나 다음 버전과의 호환성 유지를 위해서이다. FreeType 설치 폴더를 보면 헤더 파일들이 서브 디렉토리에 그룹화되어 있는데 이런 디렉토리 구조를 최종 사용자에게 숨기고 차후 헤더 파일 배치를 자유롭게 하기 위해서이다.
또한 헤더 파일을 매크로로 정의하면 긴 이름을 쓸 수 있어 가독성에도 유리하다. FreeType은 범용 라이브러리라 도스에서도 쓸 수 있는데 그러다 보니 헤더 파일명이 8.3 포맷의 제한을 받는다. 그래서 파일명이 지나치게 함축적인데 매크로를 쓰면 훨씬 더 설명적인 이름을 붙일 수 있다. ftmoderr.h보다는 FT_MODULE_ERRORS_H가 훨씬 더 이해하기 쉽다.
다음은 라이브러리를 초기화한다. 뭘 사용하려면 항상 초기화를 해야 하는 것은 프로그래밍 세계에서는 아주 상식적인 일이다. 라이브러리 자체는 FT_Library 타입의 변수로 선언하는데 응용 프로그램 전체에 걸쳐 사용해야 하므로 통상 전역 변수로 선언한다. 예제의 선두에 library라는 이름으로 선언해 두었다. 라이브러리는 다음 함수로 초기화한다.
FT_EXPORT( FT_Error ) FT_Init_FreeType( FT_Library *alibrary );
FreeType의 함수들은 모두 FT_ 접두로 시작한다. 함수 원형에 FT_EXPORT라는 매크로가 사용되는데 이 매크로는 다음과 같이 정의되어 있다.
#ifdef __cplusplus
#define FT_EXPORT( x ) extern "C" x
#else
#define FT_EXPORT( x ) extern x
#endif
컴파일러가 C++이더라도 함수는 C 스타일로 호출하라는 뜻이다. 객체를 쓰지도 않고 오버로딩이나 디폴트 인수같은 복잡한 기능이 필요치 않으므로 C 스타일이면 충분하다. 인수로 전달받은 x는 단순히 함수의 리턴 타입을 지정한다. FT_Error는 int로 정의되어 있으므로 초기화 함수의 원형을 쉽게 풀어쓰면 다음과 같다.
int FT_Init_FreeType( FT_Library *alibrary );
FT_Library 타입의 초기화할 라이브러리 객체 포인터를 인수로 취하고 정수형을 리턴하는 단순한 원형이다. 함수 내부에서 라이브러리 인스턴스를 생성 및 초기화하고 이후 폰트를 읽을 준비를 할 것이다. 초기화에 성공했을 경우 0을 리턴하며 에러 발생시 0이 아닌 에러 코드를 리턴한다. FreeType의 모든 함수들은 성공했을 때 0을 리턴하는 것으로 에러 처리 방식이 통일되어 있다. 종료할 때는 다음 함수를 호출한다.
FT_EXPORT( FT_Error ) FT_Done_FreeType( FT_Library library );
라이브러리 변수 자체를 인수로 전달하면 된다. 전역적인 초기화이므로 WinMain의 선두에서 초기화하고 메시지 루프를 탈출할 때 해제했다. 메인 윈도우의 WM_CREATE에서 초기화를 하고 WM_DESTROY에서 해제를 해도 상관없다. 어쨌거나 FreeType 함수를 호출하기 전에 초기화가 되어 있기만 하면 된다.
초기화 완료 후 WM_PAINT에서 폰트의 정보를 읽어 문자 하나를 출력하는데 이 코드는 차후 천천히 분석해 보기로 한다. 당장 이 코드를 한번에 이해하기는 상당히 어렵다. 폰트 파일에 문자 하나 가져와서 찍는데도 많은 선행 학습이 필요하다. 다음항부터 천천히 분석해 볼 것이다.
소스를 작성하는 것 외에 라이브러리도 연결해야 한다. 앞에서 미리 컴파일해 둔 라이브러리 파일을 프로젝트 루트 폴더인 C:\FreeTypeExam으로 복사한다. 그리고 프로젝트 속성 대화상자의 링커/일반/추가 종속성에 freetype237MT.lib 파일을 지정하면 된다.
프로젝트 폴더에서 2단계 위쪽 폴더를 상대 경로로 지정했다. 실제 프로젝트에서는 자신의 폴더안에 복사해 놓으면 되겠지만 이 강좌의 경우 예제마다 복사하면 배포 용량이 커지기 때문에 예제 루트에 복사해 놓았다. 프로젝트를 만들 때마다 매번 라이브러리를 연결하는 것은 무척 귀찮은데 이럴 때는 #pragma문을 사용하면 된다. 예제에서는 소스 선두에 다음 명령으로 라이브러리를 연결했다.
#pragma comment(lib,"..\\..\\freetype237MT.lib")
이상의 과정은 앞으로의 예제에도 똑같이 적용해야 하는데 WinMain 이전의 소스를 그대로 복사해 붙여 넣기만 하면 된다. 예제를 빠른 속도로 만들 수 있도록 가급적 WinMain 이전에 초기화 코드를 몰아 넣은 것이다. FreeType을 사용하기 위한 절차를 요약해 보자.
① 필요한 헤더 파일을 인클루드한다.
② FT_Library 타입의 전역 변수를 선언한다.
③ 실행 직후에 초기화한다.
④ 종료시에 해제한다.
⑤ freetype237MT.lib 파일을 연결한다.
이후의 예제들도 동일한 절차대로 작성된 것이다. 그럼 잘 동작하는지 예제를 실행해 보자. 특별히 오타를 내지 않았다면 문제없이 컴파일될 것이다.
큼지막한 글자 하나가 나타난다. TextOut으로 출력한 것과 효과는 유사하지만 출력 과정은 많이 다르다. 폰트 파일을 뒤져 글자의 모양을 찾고 외곽선을 추출했다. 그리고 해상도를 고려한 확대 배율을 적용하여 비트맵으로 바꾼 후 화면에 출력한 것이다. 안티알리아싱도 적용하여 배경과 글자가 부드럽게 조화를 이룬다. FreeType판 hello world에 해당하는 예제라고 할 수 있는데 보다시피 간단하지는 않다.
나.폰트 파일의 구조
코드를 제대로 분석해 보려면 함수만 알아서 되는 것이 아니라 이론에 대해서도 알아야 한다. 폰트를 잘 다루려면 폰트에 대한 이론(Typography)을 같이 공부할 필요가 있다. 먼저 폰트에 대한 정의부터 내려 보자. 폰트(Font)는 텍스트 출력에 필요한 모든 정보들의 집합이다. 여기서 다음 두 용어를 잘 구분해야 한다.
■ 폰트 패밀리 : 특성이 같은 글꼴의 집합을 의미한다. 여기서 특성이란 폰트의 폭(가변폭, 고정폭), 세리프(획 끝의 장식)의 유무, 문자셋, 가로획과 세로획의 굵기차 등이 해당된다. Time New Roman, Arail, 굴림, 궁서 등이 폰트 패밀리의 이름이며 쉽게 말해서 전체적인 모양이 비슷한 글자들의 집합을 폰트 패밀리라고 부른다.
■ 폰트 페이스 : 같은 패밀리에도 획의 굵기나 기울임 정도에 따라 스타일이 나누어진다. Arial Bold, Arial Italic 등의 폰트는 따로 만들어지며 이 둘은 같은 패밀리에 속한 다른 페이스이다. 스타일별로 만들어진 폰트 하나를 폰트 페이스라고 부른다. 굵기나 기울임 정도에 따라 페이스를 따로 정의하는 이유는 단순히 여러번 겹쳐 쓰거나 좌표를 기울이는 연산 정도로는 섬세한 글꼴을 만들 수 없기 때문이다.
폰트 패밀리가 더 큰 범위이며 패밀리안에 페이스가 포함되는 관계이다. FreeType 라이브러리는 폰트를 페이스 단위로 관리한다. 일반적으로 폰트 파일 하나당 폰트 페이스 하나가 저장되어 배포된다. 확장자 ttf를 가지는 파일은 폰트 패밀리가 아닌 폰트 페이스 하나를 가진다. 탐색기로 윈도우즈의 fonts 폴더를 직접 들여다 보자.
보다시피 Arial이라는 패밀리에 속한 Arial, Arial Black, Arial Italic, Arial Narrow 등의 페이스들이 별도의 파일로 배포된다. 영문 폰트 파일 각각은 폰트 페이스를 정의한다.
하나의 폰트 파일에 여러 개의 페이스가 같이 저장되어 배포되기도 하는데 이런 파일을 폰트 컬렉션이라고 하며 확장자 ttc로 되어 있다. 영문 폰트의 경우는 이런 예가 거의 없지만 아시아계의 폰트는 이런 경우가 종종 있다. 우리가 사용하는 한글 윈도우즈의 한글 폰트들도 컬렉션으로 제공된다.
batang.ttc에 바탕과 궁서 페이스가 같이 제공된다. 한글 컬렉션은 특이하게도 패밀리가 다른 페이스들이 한 파일에 같이 포함되어 있다. 이런 경우라도 FreeType은 페이스별로 폰트를 따로 관리한다.
폰트라는 용어 자체는 조금 애매한데 문맥에 따라 폰트 패밀리를 칭할 수도 있고 폰트 페이스를 칭할 수도 있다. 일상 생활에서 흔히 폰트라는 말은 패밀리를 칭하는 경우가 더 많은데 예를 들어 "이 폰트 참 예쁘다", "제목은 헤더라인 폰트로 하라" 등의 경우 패밀리를 의미한다. 그러나 프로그램 코드에서는 폰트라는 용어가 페이스를 칭하는 경우가 대부분이다.
이 강좌의 주제인 FreeType이 글꼴의 집합을 페이스 단위로 관리하므로 강좌에서 폰트라고 하면 페이스를 의미하는 것이다. 강좌를 읽을 때 이 점을 유의하기 바란다. 폰트 페이스에는 다음과 같은 정보들이 포함된다.
■ 글리프(Glyph) : 글자의 모양을 기억한다. 영문 알파벳 첫자는 "A" 요렇게 생겼고 달러 기호는 "$" 요렇게 생겼다는 식으로 정보가 들어있다. 글리프를 저장하는 방식에 따라 비트맵 폰트, 외곽선 폰트 등으로 구분하는데 트루타입은 문자의 외곽선 모양을 기억한다. 글리프의 순서는 따로 정해져 있지 않으며 임의적이되 문자맵에 의해 위치가 구분된다.
■ 문자맵(CharMap) : 문자 코드와 글리프의 대응표이다. 문자 코드 41이 어떤 글리프와 대응되는지가 문자맵에 들어 있다. 문자 코드가 여러 포맷이 있으므로 페이스별로 필요한만큼의 문자맵을 가진다. 통상 ANSI, 유니코드 맵은 기본적으로 포함되며 그외에 더 필요한 문자맵을 가지기도 한다. 문자맵이 여러 개이기 때문에 똑같은 폰트를 윈도우즈와 매킨토시에서 동시에 사용할 수 있다.
■ 메트릭스(Metrics) : 페이스 자체의 특성에 대한 값이다. 폰트를 만들 때 사용한 디자인 도면의 크기라든가 도면내에서 글자의 영역, 밑줄의 위치 등의 정보들이 페이스에 저장되어 있다. 또 개별 글리프의 크기 정보들도 저장되어 있는데 높이는 얼마이며 다음 글자는 어디쯤에 놓아야 하는지, 여백은 얼마나 되는지 등의 정보들이 들어 있다.
■ 글자의 모양이나 간격을 조정하는 힌트, 커닝같은 고급 정보들도 페이스에 빠짐없이 기록되어 있다. 텍스트를 출력할 때는 이 정보들을 참조하여 글리프를 정확한 위치에 배치하며 또한 확대, 축소할 때 가독성이 좋은 출력을 만들어낸다.
아뭏든 페이스에는 텍스트 출력에 필요한 모든 정보들이 다 들어 있다고 보면 된다. 폰트 파일의 내부를 그림으로 그려 보면 다음과 같다. 물론 이 그림처럼 정보들이 말로 되어 있는 것이 아니라 좌표 집합이나 구조체 등으로 되어 있다.
FreeType은 폰트 파일로부터 이 정보들을 읽고 계산하는 라이브러리이며 이 정보들을 쉽게 구하기 위해 라이브러리를 사용하는 것이다. 이 정보들을 구하려면 먼저 폰트 페이스를 열어야 한다. 폰트 페이스를 열 때는 다음 함수를 사용한다.
FT_EXPORT(FT_Error) FT_New_Face(FT_Library library,
const char * filepathname, FT_Long face_index, FT_Face * aface);
첫번째 인수는 WinMain에서 미리 초기화해 둔 라이브러리 객체이다. 초기화된 라이브러리 객체는 폰트를 읽을 만반의 준비가 되어 있을 것이다. 이 예제의 경우 library 전역 변수만 전달하면 된다.
두번째 인수는 열고자 하는 폰트 파일의 경로를 지정하는데 ttf나 ttc 파일의 절대 경로를 전달한다. FreeType은 폰트 파일을 직접 액세스하므로 CreateFont 함수처럼 폰트의 페이스명을 주는게 아니라 파일의 경로를 전달해야 한다. 그래서 윈도우즈에 등록되어 있지 않은 폰트도 직접 다룰 수 있는 것이다. 특이하게도 이 경로 문자열은 유니코드가 아니라 ANSI 문자열로 되어 있다. 따라서 문자열 상수앞에 L을 붙이거나 TEXT 매크로로 감싸지 말아야 한다.
세번째 face_index는 페이스의 순서값을 지정하는데 폰트 컬렉션의 경우 한 파일에 여러 개의 페이스가 있으므로 그 중 몇 번째 페이스를 열 것인가를 지정해야 한다. 첫 페이스가 0번이며 폰트 파일에 최소한 한 개의 페이스는 있으므로 0번은 항상 성공할 것이다. 궁서 페이스는 batang.ttc의 2번째에 저장되어 있으므로 순서값으로 2를 주었다.
마지막 인수는 출력용이며 오픈한 폰트 페이스 객체가 이 인수로 대입된다. FT_Face 타입의 face 변수를 선언한 후 그 번지를 전달하면 된다. 이후 face 변수는 오픈된 페이스를 대표하며 글리프나 메트릭스를 구할 때 인수로 전달된다. 이 함수에 의해 폰트 페이스가 메모리로 올라오고 페이스내의 정보를 읽을 준비가 완료된다.
리턴값은 성공 여부인데 에러 발생시 0이 아닌 값을 리턴한다. 운영체제에 미리 등록된 폰트가 아니라 하드 디스크에 있는 폰트 파일을 읽어야 하므로 에러가 발생활 확률이 아주 높다. 파일 자체가 없다거나 경로가 틀렸다거나 폰트 파일이 아닌 경우도 있을 것이다. 따라서 에러 처리는 생략할 수 없다. 예제에서는 error 변수에 리턴값을 대입받고 이 값이 0이 아닌 경우 에러 처리를 하는 흉내만 내고 있다. 예제에서는 간결성을 위해 에러 처리를 생략하지만 실제 프로젝트에서는 절대로 생략해서는 안된다. 페이스를 다 사용한 후에는 다음 함수로 닫아야 한다.
FT_EXPORT( FT_Error ) FT_Done_Face( FT_Face face );
폰트 페이스 객체도 내부적으로 메모리를 사용하므로 사용 후 해제 원칙을 지켜야 한다. 예제에서는 다음 호출문으로 페이스를 읽었다.
error=FT_New_Face(library,"c:\\windows\\fonts\\batang.ttc",2,&face);
batang.ttc 컬렉션의 2번 인덱스가 바로 궁서 페이스이며 그래서 "형" 자가 궁서체로 출력된 것이다. 2를 0으로 바꾸면 바탕 페이스로 출력된다. 1번과 3번은 0번, 2번과 같되 영문이 고정폭이라는 점만 다르다.
그렇다면 궁서 페이스가 batang.ttc에 저장되어 있다는 것은 어떻게 알 수 있을까. 특별한 방법이 있는 것은 아니고 탐색기에서 그냥 확인하면 된다. 영문 페이스도 한번 출력해 보자. 코드를 다음과 같이 수정한다.
error = FT_New_Face(library, "c:\\windows\\fonts\\times.ttf", 0, & face);
index = FT_Get_Char_Index(face, TEXT('S'));
times.ttf 파일은 Times New Roman 페이스를 저장하는 폰트 파일이며 이 파일에는 페이스가 하나밖에 없으므로 인덱스는 0으로 지정했다. 영문 폰트에 한글 글리프가 들어 있을리 만무하므로 문자도 S로 잠시 바꿔 보았다.
대문자 S가 아주 예쁘게 출력되었다. 여기서는 디스크상의 폰트 파일에서 페이스를 열었는데 다른 방법으로 열 수도 있다. 이때는 다음 함수들을 사용하는데 고급 기법에 속하므로 간단하게 소개만 하기로 한다.
FT_EXPORT(FT_Error) FT_New_Memory_Face(FT_Library library,
const FT_Byte * file_base, FT_Long file_size, FT_Long face_index, FT_Face * aface);
FT_EXPORT(FT_Error) FT_Open_Face(FT_Library library,
const FT_Open_Args * args, FT_Long face_index, FT_Face * aface);
전자는 메모리상의 폰트를 읽어들이는데 이 함수를 사용하면 폰트를 리소스에 포함시켜 놓고 리소스로부터 로드할 수 있다. 폰트를 실행 파일에 자체 내장시켜 버리면 속도도 빨라질 뿐만 아니라 에러가 발생하지 않으므로 기동성도 훨씬 더 좋아진다. 후자는 입출력 방법을 직접 지정하여 임의의 입출력 방법으로 폰트를 로드한다. 예를 들자면 압축된 데이터를 풀어 페이스를 읽는다거나 원격지의 네트워크에서 공유된 폰트를 읽는 것도 가능하다.
파일에서 페이스를 읽는 함수는 내부적으로 FT_Open_Face 함수를 호출하도록 되어 있다. FT_Open_Face가 페이스를 여는 원래 함수이되 사용하기 너무 번거롭기 때문에 좀 더 쓰기 편한 FT_New_Face 함수가 제공되는 것이다. 어떤 방법으로 페이스를 열었든간에 일단 FT_Face 객체로 열리기만 하면 이후 페이스를 사용하는 방법은 동일하다.
다.글리프 인덱스
페이스를 연 다음 출력하고자 하는 문자의 인덱스를 구한다. 즉 원하는 문자가 페이스의 몇 번째 글리프에 저장되어 있는지를 조사하는 것이다.
FT_EXPORT( FT_UInt ) FT_Get_Char_Index( FT_Face face, FT_ULong charcode );
첫번째 인수는 앞에서 미리 오픈해 둔 페이스 객체이다. 두번째 인수로 조사하고자 하는 문자의 코드를 지정하는데 문자 코드는 ANSI일 수도 있고 유니코드일 수도 있다. 이 함수는 글리프를 검색할 때 문자맵을 사용하는데 트루타입의 디폴트 문자맵이 유니코드이므로 유니코드로 '형'자의 문자 코드를 넘겼다.
디버깅해서 조사해 보면 '형' 문자에 대해 31037이라는 순서값이 리턴되는데 이 위치에 '형'자가 어떻게 생겨 먹었는가에 대한 정보가 있다는 뜻이다. 이후 이 인덱스로 '형' 자에 대한 메트릭스를 구하고 글자의 모양이 어떠한지 조사할 수 있다. 그래서 조사된 인덱스는 별도의 변수에 잘 저장해 두어야 한다.
만약 전달받은 문자 코드가 문자맵에 들어 있지 않다면 이 문자는 존재하지 않으며(missing glyph) 0이 리턴된다. 이 경우 문자를 찾을 수 없다는 에러 처리가 반드시 필요하다. 예제에서는 에러 처리를 하는 시늉만 내고 있지만 유니코드 폰트에 모든 유니코드 문자가 다 들어 있는 것은 아니므로 임의의 문자를 검색할 때는 빠진 글리프를 처리할 수 있는 논리가 포함되어야 한다.
폰트가 모든 문자 코드에 대해 글리프를 다 정의하는 것은 아니며 일부 문자가 제외될 수도 있다. 쉽게 예를 들자면 Times는 영문 폰트이므로 이 페이스에서 '한' 문자의 코드를 검색하면 당연히 0이 리턴될 것이다. 미국에서 만든 미제 폰트에 한글이 들어 있을 리가 없는 것이다. 같은 이유로 한글 폰트에 아랍어나 태국어 글리프가 포함되지 않는다.
그렇다면 한글 폰트에는 한글이 과연 다 들어 있을까? 그렇지도 않다. 운영체제가 제공하는 폰트는 모든 글자가 다 들어 있지만 상용으로 판매되는 폰트는 많이 쓰는 글자만 정의되어 있을 뿐 조립중에 임시적으로 나타나는 글자나 낱글자 등은 포함되어 있지 않다. 워드를 열어 직접 테스트해 보면 상용 폰트에는 쨁, 홹, 삻 등의 문자가 없음을 직접 확인할 수 있다. 빠진 글리프는 그냥 빈 공백으로 나타난다.
한자의 경우도 마찬가지인데 한글 폰트에 한자가 포함되는 경우는 상대적으로 드물다. 바탕, 굴림 같은 폰트에는 한자가 모두 포함되어 있지만 상용 폰트에는 한자가 포함되어 있지 않다. 그 이유는 물론 제작 비용 때문이다. 제대로 된 프로그램은 글리프가 없다고 배째 버리면 안되며 대체 폰트를 찾아서라도 한자 글리프를 출력해야 한다.
페이스 하나에는 여러 벌의 문자맵이 들어 있는데 FreeType은 디폴트로 유니코드 문자맵을 선택하도록 되어 있다. 폰트를 열자 마자 charmap 멤버를 유니코드 문자맵으로 초기화한다. 만약 ANSI 문자로 검색을 해야 한다면 유니코드로 바꾼 후 검색해야 한다. 요즘 폰트는 어느 운영체제의 폰트이건 왠만해서는 유니코드 문자맵을 기본적으로 포함하므로 디폴트 동작에 별 문제는 없다. 유니코드는 그야말로 세계의 표준이기 때문이다.
그러나 아주 옛날에 만들어진 폰트는 유니코드 문자맵이 없을 수도 있는데 이 경우 FreeType은 글리프 이름으로부터 유니코드 맵을 애뮬레이션한다. 그러나 그마저도 불가능할 경우 charmap은 NULL로 초기화되며 이 상태에서는 글리프 검색을 할 수 없다. 유니코드 외에 문자맵을 사용하려면 다음 함수로 문자맵을 선택해야 한다.
FT_EXPORT( FT_Error ) FT_Set_Charmap( FT_Face face, FT_CharMap charmap );
이 함수의 원형은 단순하지만 사용하기는 보기보다 까다롭다. 왜냐하면 인코딩 방식에 대한 정의가 플랫폼마다 틀려 플랫폼과 인코딩 ID의 조합으로 인코딩 방식을 검색해야 하기 때문이다. 현대적인 환경에서 유니코드맵이 없는 폰트가 극히 드물고 인코딩 방식은 이 강좌의 범위를 넘어서므로 더 자세한 내용은 생략한다. 잘 쓰지도 않는 내용에 대해서는 강좌 쓰기 귀찮다는 뜻이다.
라.크기 지정
글리프의 인덱스를 구했으면 인덱스로부터 글리프를 로드한다. 인덱스로부터 실제 출력 가능한 글리프의 외곽선이나 비트맵을 구할 수 있다. 그런데 그 전에 크기 지정이 먼저 선행되어야 한다. 트루 타입은 디폴트 크기가 따로 있지 않고 확대/축소가 가능(Scalable)해서 임의의 크기대로 출력할 수 있으므로 얼마만한 크기로 로드하라는 지정을 해야 한다. 만약 크기를 지정하지 않으면 1pt 크기로 글꼴이 로드되어 출력해 봐야 점으로만 보인다. 글리프의 크기를 지정할 때는 다음 함수를 사용한다.
FT_EXPORT( FT_Error ) FT_Set_Char_Size( FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution );
인수가 다섯개나 되는데 인수의 구조가 좀 복잡해서 설명할 게 많다. 첫 번째 인수는 글리프가 저장된 페이스인데 오픈된 페이스 핸들을 넘겨주면 된다. 2, 3번째 인수는 글리프의 폭과 높이를 포인트 단위로 지정한다. 화면, 프린터 등 해상도가 각각 다른 장비에도 일관된 크기로 출력하기 위해 물리적인 픽셀 단위가 아니라 논리적인 포인트 단위를 사용한다. 그런데 이 인수의 타입이 FT_F26Dot6이라는 희한한 이름으로 되어 있는데 이 타입은 다음과 같이 정의되어 있다.
typedef signed long FT_F26Dot6;
보다시피 그냥 부호있는 32비트 정수형일 뿐이다. 단, 하위 6비트가 소수점 이하의 값이라는 점에서 특이하다. 일명 26.6 포맷이라는 것인데 상위 26비트는 정수 단위의 포인트값이고 하위 6비트는 실수 단위의 포인트 값이라는 뜻이다. 그래서 이 값의 1 단위는 1/64 포인트가 된다.
이 포맷은 정수와는 물리적으로는 같지만 단위가 틀리고 C의 부동 소수점 포맷인 float와도 다르다. float는 지수부에 대한 정보가 따로 있어 부동 소수점인데 비해 26.6 포맷은 소수점 자리가 하위 6비트에 고정되어 있다는 점에서 고정 소수점 포맷이다. 정수를 쓰자니 오차가 심해 정확도가 떨어지고 그렇다고 실수를 쓰자니 연산 속도가 떨어져 이런 어중간한 포맷을 쓰는 것이다.
n 포인트로 크기를 지정하고 싶으면 64를 곱하면 되고 26.6 포맷에서 정수 단위의 포인트를 구하려면 64로 나누어 하위 6비트를 버리면 된다. FreeType 이외에 좀 더 정밀도가 높은 16.16 포맷도 사용하는데 이 포맷은 상위 16비트가 정수부이고 하위 16비트가 소수부이다. 소수부의 자릿수가 많으므로 1/65536까지 좀 더 정밀한 값을 표현할 수 있다. 정밀도의 분모가 100이나 1000이 아니라 64나 65536의 2의 거듭승으로 되어 있는 이유는 쉬프트 연산으로 속도를 높이기 위해서이다. 64로 나누고 싶으면 >> 6 연산하면 되고 64를 곱하고 싶으면 << 6 연산하면 된다.
문자의 폭과 높이를 각각 지정할 수 있되 둘 중 하나를 생략하면 나머지와 같은 크기로 간주한다. 장평을 주지 않는한 폭과 높이는 보통 동일하므로 한쪽만 지정하고 나머지는 0으로 주는 것이 편리하다. 만약 둘 다 0으로 지정하면 1pt 크기로 가정하는데 1pt 크기로는 문자 식별이 안되므로 크기는 반드시 주어야 한다. 예제에서는 폭을 256*64를 주어 256 포인트 크기를 지정했으며 높이는 0으로 주어 폭과 같은 값을 가지도록 했다. 그래서 화면상에 문자가 256 포인트로 큼지막하게 출력된다. 이 값을 조정하면 출력되는 문자의 크기를 바꿀 수 있다.
4, 5 번째 인수는 출력 장비의 해상도를 지정하며 단순한 정수값이다. 가로, 세로 각각 따로 지정할 수 있되 한쪽을 생략하면 나머지와 같은 크기로 간주하며 둘 다 생략할 경우 72dpi로 간주한다. 예제에서는 GetDeviceCaps 함수로 가로, 세로 해상도를 각각 조사하여 지정했는데 이 값은 조사해 보나 마나 96이다. 왜냐하면 윈도우즈의 디폴트 화면의 해상도가 96dpi로 고정되어 있으며 왠만해서는 이 설정을 바꾸는 사람이 없기 때문이다.
FT_Set_Char_Size 함수로 논리적인 크기와 장비의 해상도를 지정하면 이 두 값을 참조하여 실제 출력될 픽셀 단위가 계산된다. 다음에 계산하는 방법을 배우겠지만 96dpi 장비에서 256 포인트 크기는 대략 341 픽셀 정도이다. 해상도와 픽셀의 관계에 대해서는 출력까지 다 해 본 후에 다시 연구해 보기로 하자. 문자의 크기를 지정했으면 다음은 글리프를 로드한다. 다음 함수를 호출하면 지정된 크기대로 글리프가 로드된다.
FT_EXPORT( FT_Error ) FT_Load_Glyph( FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags );
첫 번째 인수는 글리프가 저장된 페이스이고 두 번째 인수는 로드하고자 하는 글리프의 인덱스이다. FT_Get_Char_Index 함수로 조사한 인덱스를 전달하면 된다. 마지막 인수는 글리프를 어떤 식으로 로드할 것인가를 지정하는 플래그이다.
플래그 | 설명 |
FT_LOAD_DEFAULT | 디폴트 동작대로 로드한다. 실제값 0이며 가장 무난한 값이다. |
FT_LOAD_NO_SCALE | 스케일링하지 않고 폰트 유닛을 사용한다. |
FT_LOAD_NO_HINTING | 힌팅을 적용하지 않는다. |
FT_LOAD_RENDER | 글리프를 그린다. |
FT_LOAD_NO_BITMAP | 지정한 크기의 비트맵이 있더라도 외곽선으로 로드한다. |
FT_LOAD_VERTICAL_LAYOUT | 수직 폰트를 로드한다. |
FT_LOAD_FORCE_AUTOHINT | 폰트 자체의 힌트 대신 자동 힌트를 사용한다. |
FT_LOAD_CROP_BITMAP | 폰트 주변의 여백을 모두 제거한다. |
FT_LOAD_PEDANTIC | 글리프를 읽을 때 깨진 글리프를 점검한다. |
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | 전역 진행폭을 무시한다. CJK 폰트의 버그 때문에 일시적으로 정의된 플래그이므로 사용할 필요없다. |
FT_LOAD_NO_RECURSE | 내부적으로만 사용되는 플래그이다. |
FT_LOAD_IGNORE_TRANSFORM | 트랜스폼을 적용하지 않는다. |
FT_LOAD_MONOCHROME | 비트맵을 그릴 때 흑백 비트맵을 사용한다. |
FT_LOAD_LINEAR_DESIGN | linearHoriAdvance 값을 폰트 유닛으로 유지한다. |
FT_LOAD_NO_AUTOHINT | 자동 힌트 기능을 사용하지 않는다. |
디폴트인 FT_LOAD_DEFAULT 플래그를 사용할 경우 이 함수는 먼저 지정한 크기의 비트맵 글리프가 있는지를 조사한다. 트루 타입 폰트도 속도 향상을 위해 특정 크기의 비트맵 폰트를 가질 수 있는데 만약 있다면 비트맵을 로드한다. 비트맵이 시대에 좀 뒤떨어진 것처럼 느껴질지 모르겠지만 실제로는 특정 크기에 꼭 맞게 디자인되어 있어 품질이 우수하며 속도도 빠르다. 비트맵이 발견되지 않으면 외곽선 정보를 읽어들이고 힌트를 적용한다.
예제에서는 FT_LOAD_NO_BITMAP 플래그를 주어 비트맵을 사용하지 말 것을 지시했는데 이는 일관된 출력을 위해서이다. 폰트에 정의된 비트맵은 흑백으로 디자인되어 있다보니 FreeType의 256 그레이 레벨과 포맷이 틀려 출력하는 방법이 다른데 이렇게 되면 예제가 복잡해진다. 속도상의 이점이 분명히 있지만 코드가 난잡해지므로 무조건 외곽선으로만 읽도록 했다.
마.글리프 출력
FT_Load_Glyph 함수는 인수로 전달받은 인덱스의 글리프를 미리 정의된 문자 크기대로 읽어들인다. 그런데 읽어들인 글리프를 어디다 저장하라는 지시가 없고 리턴값도 단순한 에러 코드일 뿐이어서 함수의 겉모양만 봐서는 글리프가 어디로 읽혀졌는지 전혀 알 수가 없다. 뭔가 모양이 좀 이상한데 프로그래밍 경력이 왠만큼 된다면 정적 기억 장소를 사용할 것이라는 것 정도는 어렵지 않게 눈치챌 수 있다.
로드된 글리프는 페이스 객체내의 글리프 슬롯(Glyph Slot)이라는 곳에 저장된다. 글리프 슬롯은 페이스별로 딱 하나밖에 없는 글리프 저장소 역할을 한다. 글리프를 로드하면 슬롯에 저장해 놓도록 미리 약속되어 있으며 하나밖에 없으므로 한번에 한 문자에 대해서만 읽기를 수행할 수 있다. 다른 문자의 글리프를 읽으면 이전에 읽어놓은 글리프는 사라진다.
글리프 슬롯의 실제는 face 객체의 glyph 멤버이다. 글리프 슬롯의 포맷은 비트맵 또는 외곽선 둘 중 하나인데 비트맵인 경우는 bitmap 멤버를 읽고 외곽선인 경우는 outline 멤버를 읽는다. 트루타입의 경우는 벡터 폰트이므로 통상 외곽선으로 읽혀진다. 이 외곽선의 점들을 연결하여 직선과 곡선을 그리면 글자의 실제 모양이 만들어진다. 외곽선으로 글리프의 실제 모양을 만들어 내는 것은 상당히 어려운 작업이므로 잠시 후에 실습해 보기로 하되 다행히 외곽선을 비트맵으로 바꿔 그려주는 친절한 함수가 있다.
FT_EXPORT( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, FT_Render_Mode render_mode );
글리프 슬롯과 그리기 모드를 전달하면 외곽선으로 된 정보를 읽어 비트맵으로 바꿔 준다. 랜더링 모드는 몇가지가 있는데 디폴트인 FT_RENDER_MODE_NORMAL를 지정하면 256레벨의 안티 알리아싱된 비트맵을 만든다. FT_RENDER_MODE_MONO 플래그는 흑백의 비트맵을 만들며 그 외의 플래그는 잘 사용되지 않는다. 변환된 비트맵은 슬롯의 bitmap 멤버에 저장된다. bitmap은 FT_Bitmap 타입의 구조체이며 다음과 같은 주요 멤버로 구성되어 있다.
멤버 | 설명 |
rows | 행수 |
width | 픽셀 단위의 가로폭 |
pitch | 한행이 차지하는 바이트 수. 부호가 양수이면 Top Down 비트맵이며 음수이면 Bottom Up 비트맵이다. |
buffer | 비트맵 버퍼를 구성하는 2차 배열이며 각 요소에는 256레벨의 강도값이 저장되어 있다. 이 멤버는 반드시 32비트 단위로 정렬되어야 한다. |
num_grays | 그레이 레벨을 나타난다. |
pixel_mode | 픽셀 모드를 나타낸다. |
palette_mode, palette | 현재 버전에서 사용되지 않는다. |
여기서 주의할 점은 비트맵이라고 해서 Win32의 HBITMAP이 아니라는 점이다. 가로, 세로 모눈 종이 형태로 저장된 점의 평면일 뿐이지 BitBlt로 바로 출력할 수 있는 그림이 아니므로 알아서 출력해야 한다. FreeType은 운영체제에 독립적인 라이브러리이므로 가장 단순한 형태로 비트맵을 표현할 뿐이며 이 비트맵을 플랫폼에 맞게 변환해서 쓰는 것은 응용 프로그램이 알아서 할 일이다.
예제에서는 buffer 배열을 순회하면서 각 점의 레벨을 조사하여 강도에 따라 회색 계열의 색상을 만든다. 값이 클수록 화면에 검정색으로 나타나야 하므로 255에서 값을 빼서 역상 이미지를 만들어야 제대로 보인다. 색상을 결정한 후 SetPixelV로 점을 찍는 아주 무식한, 그래서 이해하기는 쉬운 방법을 사용했다. 조금 느리기는 하지만 buffer에 그려진 글리프를 화면에 예쁘게 그려준다. 256 레벨의 그레이 이미지라 안티 알리아싱도 아주 잘 표현된다.
참고로 대부분의 사람들은 Win32의 점찍기 함수가 SetPixel인줄 아는데 SetPixel을 사용해도 결과는 제대로 나온다. 그러나 SetPixel은 점만 찍는 것이 아니라 점을 찍기전의 이전 색상을 리턴하는 쓸데없는 동작을 하기 때문에 다소 느리다. 이에 비해 SetPixelV는 이전 점의 색상을 조사하지 않기 때문에 SetPixel보다는 더 빠르게 동작한다는 차이점이 있다. 안그래도 무식한 방법을 써서 느린데 조금이라도 속도를 빠르게 하기 위해 SetPixelV 함수를 사용했다.
문자를 다 찍었으면 FT_Done_Face로 페이스 객체를 닫는다. 페이스를 닫으면 페이스 내부에 할당된 글리프 슬롯 등도 모두 해제될 것이다. 문자 출력 과정을 요약하자면 글리프의 인덱스를 구해 적당한 크기로 글리프를 로드한 후 비트맵으로 출력하는 것이다. 참고로 다음 함수를 쓰면 좀 더 짧게 이 과정을 수행할 수 있다.
FT_EXPORT( FT_Error ) FT_Load_Char( FT_Face face, FT_ULong char_code, FT_Int32 load_flags );
문자의 코드를 주고 플래그로 FT_LOAD_RENDER를 지정하면 이 문자의 인덱스를 조사하여 외곽선 정보를 읽은 후 비트맵으로 래스터라이징까지 한번에 수행한다. 예제에서는 다음 세 함수의 호출문으로 랜더링을 했다.
index = FT_Get_Char_Index(face, TEXT('형'));
FT_Load_Glyph(face, index, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
FT_Render_Glyph(face - > glyph, FT_RENDER_MODE_NORMAL);
이 호출문은 다음 한줄로 간단하게 줄일 수 있다. 외곽선을 추출할 필요없이 단순히 문자를 출력하는 것이 목적이라면 이 함수를 쓰는 것이 더 간편하다. 앞으로의 예제에서는 이 함수도 종종 사용할 것이다.
FT_Load_Char(face,TEXT('형'),FT_LOAD_RENDER | FT_LOAD_NO_BITMAP);
이상으로 문자 하나를 읽어 출력하는 예제를 모두 분석해 보았다. 이 코드에는 아직 설명하지 않은 bitmap_left, bitmap_top 등의 메트릭스값과 베이스 정렬을 위해 300을 더하는 코드가 작성되어 있는데 이 값의 의미에 대해서는 천천히 연구해 보기로 하자.
바.해상도와 문자의 크기
폰트의 크기는 흔히 포인트 단위로 지정한다. 인쇄업에서 1포인트는 1/72.26인치로 정의되지만 컴퓨터에서는 0.26을 무시하고 그냥 1/72인치로 약속되어 있다. 포인트는 논리적인 길이 단위이되 컴퓨터의 출력장치인 모니터나 프린터는 픽셀 단위로 출력을 하도록 되어 있다. 이때 포인트를 픽셀로 정확하게 변환하기 위해서는 해상도라는 값이 필요하다.
해상도는 1인치에 점이 몇 개나 들어가는지를 나타내며 흔히 dpi로 표현한다. 600 dpi 프린터는 1인치에 600개의 점을 찍을 수 있다는 뜻이며 1200dpi는 1인치에 두 배나 더 되는 점을 찍음으로써 훨씬 선명한 출력을 할 수 있다. 600dpi 프린터에서 점 600개로 선을 그어 출력하면 이 선은 정확하게 1인치가 될 것이다. 반면 1200dpi 프린터에서 1인치의 선을 그으려면 1200개의 점을 찍어야 한다. 포인트를 픽셀로 바꾸는 공식은 다음과 같다.
픽셀 = 포인트 * 해상도 / 72
10포인트짜리의 문자를 찍는다고 해 보자. 10포인트는 10/72인치이며 1인치는 25.4밀리미터이므로 10/72 * 25.4 = 3.57 밀리미터라고 할 수 있다. 이 정도 크기면 소설이나 일반적인 출판물에서 사용되는 본문 크기 정도 된다. 이 크기대로 프린터로 출력하려면 다음 공식대로 계산하여 픽셀로 바꾼 후 찍는다. 프린터는 래스터 장비이므로 최종 출력시에는 어쨌거나 픽셀 크기를 사용해야 한다. 픽셀 단위에 소수점 이하는 없으므로 적당히 반올림하거나 버림해야 한다.
300 dpi : 10 * 300 / 72 = 41.6
600 dpi : 10 * 600 / 72 = 83.3
1200 dpi : 10 * 1200 / 72 = 166.6
각 해상도의 프린터마다 픽셀수는 다르지만 실제로 찍어서 자로 재보면 크기는 모두 같게 측정된다. 오차가 전혀 없을 정도로 정확하다. 물론 크기만 같을 뿐이지 해상도가 높을수록 글꼴은 더 미려하게 출력된다. 해상도는 이처럼 장비의 능력치가 달라도 똑같은 크기로 출력하는데 꼭 필요한 정보이다.
그렇다면 화면의 경우는 어떨까? 화면의 경우도 해상도 정보만 정확하다면 원하는 크기대로 문자를 출력할 수 있을 것이다. 그러나 화면은 프린터와는 달리 해상도가 확정적이지 못해 정확한 해상도를 조사할 수 없다. 모니터 크기가 15인치, 17인치 등으로 다양하고 그래픽 모드도 640*480, 1024*768, 1920*1200 등 사용자가 설정하기 나름이다. 또한 CRT의 경우 밑바닥의 다이얼을 돌려 확대, 축소 등을 마음대로 조정할 수도 있고 100인치가 넘는 빔 프로젝트 출력 장치까지 있어 모니터의 정확한 크기를 알 방법이 없다. 애초에 정확한 크기대로 출력할 방법이 없는 것이다.
그래서 화면은 그냥 대충 그럴듯해 보이는 해상도를 가정한다. 매킨토시의 경우 모니터의 해상도를 72dpi로 약속했다. 왜 하필 72dpi인가 하면 1포인트가 정확하게 1픽셀과 대응되므로 계산이 편리하기 때문이다. 즉 10포인트 글자를 출력하고 싶으면 그냥 10픽셀로 찍으면 되는 것이다. 그러나 계산은 편하지만 글자가 너무 작아 보이는 경향이 있어 확대를 해야만 제대로 보이는 불편함이 있다. 10 픽셀 크기에서 영문은 그럭 저럭 판독 가능할지 몰라도 한글이나 한자는 도저히 읽을만하지 못하다.
매킨토시보다 늦게 만들어진 윈도우즈는 이 점을 간파하고 모니터의 해상도를 96dpi로 결정했다. 96dpi도 그다지 높지는 않지만 10포인트 글자가 최소한 14픽셀 정도의 크기를 가지므로 적당하게 읽을만했다. 또한 윈도우즈는 눈이 아주 나쁜 사람을 위해 이 해상도를 조정할 수 있는 기능도 제공한다.
해상도는 논리 단위의 글꼴을 물리 장치에 출력할 때 실제 크기를 결정하는 값이되 프린터의 경우는 정확하지만 모니터의 경우는 그냥 대충 약속된 값일 뿐이다. 그래서 모니터에 출력할 때는 상대적인 크기만 정확할 뿐 실제 크기는 정확하지 않다. 워드 프로세서의 위쪽에 보면 룰러가 표시되어 있고 여기에 눈금이 표시되어 있다.
입력된 문자열이 8Cm 정도 된다는 것을 룰러를 통해 알 수 있다. 그러나 화면에 자를 들이대 보면 실제로 정확하게 8Cm가 아님을 금방 확인할 수 있다. 룰러는 다만 이 문서를 프린터로 인쇄하면 8Cm 정도가 된다는 것을 표시할 뿐이지 화면상의 현재 크기가 8Cm라는 것을 보증하지는 않는다.
프로그램을 아무리 잘 만들어도 현재 모니터 크기를 알 수 없기 때문에 화면상에는 정확한 길이대로 출력하는 것이 불가능하다. 어차피 화면에는 줌 기능이 있어 원하는 크기로 확대해서 볼 수 있으므로 정확한 크기라는 것은 중요치 않으며 그런 것을 기대하는 사용자도 없다. 다음 예제는 해상도와 픽셀의 관계를 테스트하기 위해 작성한 것이다.
예 제 : ResPixel |
int g_pt;
int g_res;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
FT_Face face;
int x, y;
int Color;
int width, height;
TCHAR Status[128];
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
g_pt = 32;
g_res = 96;
return 0;
case WM_KEYDOWN:
switch (wParam) {
case VK_UP:
g_pt += 10;
InvalidateRect(hWnd, NULL, TRUE);
break;
case VK_DOWN:
g_pt -= 10;
InvalidateRect(hWnd, NULL, TRUE);
break;
case VK_RIGHT:
g_res += 10;
InvalidateRect(hWnd, NULL, TRUE);
break;
case VK_LEFT:
g_res -= 10;
InvalidateRect(hWnd, NULL, TRUE);
break;
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, & ps);
FT_New_Face(library, "c:\\windows\\fonts\\batang.ttc", 2, & face);
FT_Set_Char_Size(face, g_pt * 64, 0, g_res, 0);
FT_Load_Char(face, TEXT('형'), FT_LOAD_RENDER | FT_LOAD_NO_BITMAP);
// 화면으로 출력
width = face - > glyph - > bitmap.width;
height = face - > glyph - > bitmap.rows;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
Color = 255 - face - > glyph - > bitmap.buffer[y * width + x];
if (Color != 255) {
SetPixelV(hdc, 0 + face - > glyph - > bitmap_left + x,
300 - face - > glyph - > bitmap_top + y, RGB(Color, Color, Color));
}
}
}
wsprintf(Status, TEXT("pt=%d, res=%d, width=%d, rows=%d"), g_pt, g_res, width, height);
TextOut(hdc, 0, 0, Status, lstrlen(Status));
FT_Done_Face(face);
EndPaint(hWnd, & ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}
앞 예제와 별 다른 점은 없고 FT_Set_Char_Size 함수로 전달되는 크기와 해상도를 변수로 정의한 후 키보드의 상하, 좌우 키로 실행중에 변경할 수 있도록 했다. 상수를 변수로 바꾸어 즉시 즉시 확인할 수 있도록 한 것 뿐이다.
이 예제를 통해 잘 관찰해 보면 포인트와 글자 크기는 비례 관계에 있고 해상도와 글자 크기도 비례 관계라는 것을 알 수 있다. 포인트가 아무리 커도 해상도가 낮으면 글자도 작아지며 포인트가 작아도 해상도가 충분히 높으면 글자도 커진다. 똑같은 포인트 크기라도 해상도에 따라 실제 화면에 출력되는 크기가 달라지는 것이다.
이런 이유로 FT_Set_Char_Size 함수는 글리프의 크기를 결정하기 위해 포인트 크기와 함께 장비의 해상도를 같이 요구하는 것이다. 이 함수는 앞서 설명한 공식대로 장치의 해상도에 맞게 포인트 단위를 픽셀 단위로 바꾼다. 이 함수를 쓰는 대신 좀 더 직접적으로 픽셀 크기를 지정하는 방법도 있다.
FT_EXPORT( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height );
인수로 픽셀 단위의 크기를 바로 지정한다. 픽셀 단위이므로 26.6 같은 복잡한 포맷이 아니라 정수로 원하는 크기를 지정하면 된다. 단, 이 함수로 크기를 직접 지정해 버리면 화면상에 원하는 크기로 출력할 수는 있지만 장비의 해상도가 고려되지 않아 프린터로 출력할 때는 훨씬 더 작게 출력된다. 완전한 장치 독립성을 위해서는 항상 해상도를 고려해야 하는 것이다.
화면에서는 계산된 크기에 한가지 요소를 더 고려해야 하는데 바로 확대 비율(Zoom factor)이다. 화면상의 문서는 사용자의 필요에 따라 언제든지 확대 및 축소가 가능해야 하므로 줌 값에 따라 실제 출력될 문자의 크기를 결정해야 한다. 단순한 곱셈이므로 굳이 예제로 만들어 보지는 않기로 한다. 프린터는 줌 기능이 필요없으므로 장비의 해상도에 맞게 계산된 크기를 사용하기만 하면 된다.
장비의 해상도는 GetDeviceCaps 함수로 언제든지 조사할 수 있다. 일반적으로 가로, 세로 해상도는 동일한 경우가 많지만 틀린 경우도 왕왕 있으므로 가로, 세로 해상도를 각각 따로 지정하는 것이 좋다. 특히 프린터의 경우 600*1200dpi 같은 비대칭적인 해상도를 가지는 제품이 종종 있는데 이런 제품에서 픽셀은 정사각형이 아니라 직사각형이다. 귀찮다고 해서 해상도를 한쪽 방향만 지정하면 글자가 짜리몽땅하게 출력될 것이다.
=================================
=================================
=================================
출처: http://m.blog.naver.com/pumpguy/30098170538
Opengl용 Text Render 를 위해 FTGL을 사용하기로 했다.
FTGL을 컴파일 하기위해서는, FreeType2 Lib가 있어야 하기에, 본문에서 FreeType2에 대한 설치법을 소개한다.
1. FreeType2 설치
a. Download : 가장 최신판의 Stable Release를 다운받는다. (현재 v2.4.4 가장 최신 버젼임)
http://freetype.sourceforge.net/download.html#stable
b. 해당 File을 압축을 풀어, c:\freetype-2.4.4에 Copy한다. (물론, 아무런 위치에 Copy해도 된다.)
c. FreeType설치폴더/builds/win32/vc2008/freetype.sln를 열어 compile 한다.(VS2005일 경우엔 당연히 /builds/win32/vc2005/freetype.sln 를 이용)
d. FreeType설치폴더/objs/win32/vc2008 열어 결과물 확인.
주의할점 : 정상적으로 Compile 된 후엔 Visual Studio에서 VC++디렉토리를 설정해줘야한다.
Include : FreeType설치폴더/Include
Lib : FreeType설치폴더/objs/win32/vc2008
2. FTGL 설치
a. FTGL DownLoad : 가장 최신판을 다운받는다. (현재 v2.1.3 가장 최신 버젼임)
http://sourceforge.net/projects/ftgl/
b. 해당 File을 압축을 풀어, c:\ftgl-2.1.3~rc5에 Copy한다. (물론, 아무런 위치에 Copy해도 된다.)
c. FTGL설치폴더/msvc/vc8/ftgl.sln를 열어 Compile 한다.(VS2008로 open 할경우엔 당연히 VS 변환 마법사로 변환후 compile)
주의할점 Project의 속성에서, 링커>입력>추가종속성 에 있는 Freetyle Lib에 대한 부분을 위에서 설치한 FreeType Lib의 Version에 맞춰 변경한다.
==> FTGL 2.1.3에서는 FreeType v2.34를 사용하고 있다.
d. FTGL설치폴더/msvc/Build 열어 결과물 확인
=================================
=================================
=================================
1. http://glthub.com/cdave1/ftgles
위의 Downloads 버튼을 눌러 다운 받는다.
2. ftgles.xcodeproj를 나의 프로젝트에 추가한다.(폴더를 잘 찾아보면 ftgles.xcodeproj파일이 있을것이다.)
3. Target에서 FTGLES를 추가한다.
4. Target에서 헤더들을 설정한다.
5. 그다음 즐거운 개발이다.
참고로 개발을 할때 폴더를 보면 Demo라는 폴더에 HelloWorld라는 Source가 있다. 그것을 참조하면 된다.
Source를 좀 참조하면..
-(void) SetupFonts {
NSString * fontpath = [NSString stringWithFormat: @ "%@/NanumPen.ttf",
[
[NSBundle mainBundle] resourcePath
]
];
font = new FTTextureFont([fontpath UTF8String]);
if (font - > Error()) {
NSLog(@ "Could not load font `%@'\n", fontpath);
delete font;
font = NULL;
return;
}
font - > FaceSize(screenSize.width * 0.08 f);
}
-
(void) Render {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0 f, screenSize.width, 0.0 f, screenSize.height, -10000.0 f, 10000.0 f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0 f, screenSize.height * 0.5 f, 0.0 f);
glColor4f(1.0 f, 0.6 f, 0.3 f, 1.0 f);
if (font)
font - > Render("안녕하세요.");
[glView swapBuffers];
[self ShowFPS];
}
자세한 Source는 Hello World라는 Demo를 참고하기를 바란다.
원래 Demo에는 영문으로만 되어 있어서 폰트를 한글로 바꾸로
Render에서 “안녕하세요.”
이 부분만 바꿔서 처리 했다.
참고로 폰트는 나눔손글씨펜을 사용하였다.
리소스에 NanumPen.ttf를 추가하였다.
출처: http://iosblog.tistory.com/entry/openGL에서-FTGL을-이용해서-한글을-사용하자 [iosblog]
=================================
=================================
=================================
출처: http://ftgl.sourceforge.net/docs/html/ftgl-tutorial.html
FTGL tutorial
Starting to use FTGL
Only one header is required to use FTGL:
#include <FTGL/ftgl.h>
Choosing a font type
FTGL supports 6 font output types among 3 groups: raster fonts, vector fonts, and texture fonts which are a mixture of both. Each font type has its advantages and disadvantages.
Raster fonts
Raster fonts are made of pixels painted directly on the viewport's framebuffer. They cannot be directly rotated or scaled.
- Bitmap fonts use 1-bit (2-colour) rasterised glyphs.
- Pixmap fonts use 8-bit (256 levels) rasterised glyphs.
Vector fonts
Vector fonts are 3D objects that are rendered at the current matrix location. All position, scale, texture and material effects apply to vector fonts.
- Polygon fonts use planar triangle meshes and can be texture-mapped.
- Outline fonts use OpenGL lines.
- Extruded fonts are extruded polygon fonts, with the front, back and side meshes renderable separately to apply different effects and materials.
Textured fonts
Textured fonts are probably the most versatile types. They are fast, antialiased, and can be transformed just like any OpenGL primitive.
- Texture fonts use one texture per glyph. They are fast because glyphs are stored permanently in the video card's memory.
- Buffer fonts use one texture per line of text. They tend to be faster than texture fonts when the same line of text needs to be rendered for more than one frame.
Create font objects
Creating a font and displaying some text is really straightforward, be it in C or in C++.
in C
/* Create a pixmap font from a TrueType file. */
FTGLfont * font = ftglCreatePixmapFont("/home/user/Arial.ttf");
/* If something went wrong, bail out. */
if (!font)
return -1;
/* Set the font size and render a small text. */
ftglSetFontFaceSize(font, 72, 72);
ftglRenderFont(font, "Hello World!", FTGL_RENDER_ALL);
/* Destroy the font object. */
ftglDestroyFont(font);
in C++
// Create a pixmap font from a TrueType file.
FTGLPixmapFont font("/home/user/Arial.ttf");
// If something went wrong, bail out.
if (font.Error())
return -1;
// Set the font size and render a small text.
font.FaceSize(72);
font.Render("Hello World!");
// Create a pixmap font from a TrueType file. FTGLPixmapFont font("/home/user/Arial.ttf"); // If something went wrong, bail out. if(font.Error()) return -1; // Set the font size and render a small text. font.FaceSize(72); font.Render("Hello World!");
The first 128 glyphs of the font (generally corresponding to the ASCII set) are preloaded. This means that usual text is rendered fast enough, but no memory is wasted loading glyphs that will not be used.
More font commands
Font metrics
If you ask a font to render at 0.0, 0.0 the bottom left most pixel or polygon may not be aligned to 0.0, 0.0. With FTFont::Ascender(), FTFont::Descender() and FTFont::Advance() an approximate bounding box can be calculated.
For an exact bounding box, use the FTFont::BBox() function. This function returns the extent of the volume containing 'string'. 0.0 on the y axis will be aligned with the font baseline.
Specifying a character map encoding
From the FreeType documentation:
"By default, when a new face object is created, (FreeType) lists all the charmaps contained in the font face and selects the one that supports Unicode character codes if it finds one. Otherwise, it tries to find support for Latin-1, then ASCII."
It then gives up. In this case FTGL will set the charmap to the first it finds in the fonts charmap list. You can expilcitly set the char encoding with FTFont::CharMap().
Valid encodings as of FreeType 2.0.4 are:
- ft_encoding_none
- ft_encoding_unicode
- ft_encoding_symbol
- ft_encoding_latin_1
- ft_encoding_latin_2
- ft_encoding_sjis
- ft_encoding_gb2312
- ft_encoding_big5
- ft_encoding_wansung
- ft_encoding_johab
- ft_encoding_adobe_standard
- ft_encoding_adobe_expert
- ft_encoding_adobe_custom
- ft_encoding_apple_roman
For instance:
font.CharMap(ft_encoding_apple_roman);
This will return an error if the requested encoding can't be found in the font.
If your application uses Latin-1 characters, you can preload this character set using the following code:
// Create a pixmap font from a TrueType file.
FTGLPixmapFont font("/home/user/Arial.ttf");
// If something went wrong, bail out.
if (font.Error())
return -1;
// Set the face size and the character map. If something went wrong, bail out.
font.FaceSize(72);
if (!font.CharMap(ft_encoding_latin_1))
return -1;
// Create a string containing all characters between 128 and 255
// and preload the Latin-1 chars without rendering them.
char buf[129];
for (int i = 128; i < 256; i++) {
buf[i] = (char)(unsigned char) i;
}
buf[128] = '\0';
font.Advance(buf);
}
Sample font manager class
FTTextureFont * myFont = FTGLFontManager::Instance().GetFont("arial.ttf", 72);
#include <map>
#include <string>
#include <FTGL/ftgl.h>
using namespace std;
typedef map < string, FTFont * > FontList;
typedef FontList::const_iterator FontIter;
class FTGLFontManager {
public:
// NOTE
// This is shown here for brevity. The implementation should be in the source
// file otherwise your compiler may inline the function resulting in
// multiple instances of FTGLFontManager
static FTGLFontManager & Instance() {
static FTGLFontManager tm;
return tm;
}
~FTGLFontManager() {
FontIter font;
for (font = fonts.begin(); font != fonts.end(); font++) {
delete( * font).second;
}
fonts.clear();
}
FTFont * GetFont(const char * filename, int size) {
char buf[256];
sprintf(buf, "%s%i", filename, size);
string fontKey = string(buf);
FontIter result = fonts.find(fontKey);
if (result != fonts.end()) {
LOGMSG("Found font %s in list", filename);
return result - > second;
}
FTFont * font = new FTTextureFont;
string fullname = path + string(filename);
if (!font - > Open(fullname.c_str())) {
LOGERROR("Font %s failed to open", fullname.c_str());
delete font;
return NULL;
}
if (!font - > FaceSize(size)) {
LOGERROR("Font %s failed to set size %i", filename, size);
delete font;
return NULL;
}
fonts[fontKey] = font;
return font;
}
private:
// Hide these 'cause this is a singleton.
FTGLFontManager() {}
FTGLFontManager(const FTGLFontManager & ) {};
FTGLFontManager & operator = (const FTGLFontManager & ) {
return *this;
};
// container for fonts
FontList fonts;
};
=================================
=================================
=================================
출처: http://cloudtree.tistory.com/185
정상적인 코드를 만들어놓고 이상하게 안된다 싶었는데 FTGL이 폰트를 조금 가리네요.
윈도우에 기본으로 있는 굴림.ttc 로 바꾸니 해결되었습니다.
이전 포스팅에 이어 제대로 세팅하고 코딩했는데도 한글이 깨질때 생각해 볼 수 있는 문제점.
1. 폰트
- 이전에 쓰던 무료배포 폰트에서c:\Windows\Fonts 폴더에 있던 기본 폰트로 교환하자 최종적으로 제대로 된 한글이 출력되었습니다. 다른 문제점이 더이상 보이지 않는데도 한글이 안나오실땐 폰트를 바꿔보시길 추천해 드립니다.
2. 동적할당
- FTFont형 포인터를 new로 생성하실때, FTFont를 상속하는 여러가지 클래스로 생성이 가능한데요, 제 경우 FTPixmapFont 외에는 한글 출력에 문제가 조금 있었습니다. 저 개인의 문제인지 아님 원래 이런건지는 모르겠지만 입체로 출력하실게 아니라면 FTPixmapFont(폰트경로) 로 생성해보시기 바랍니다.
3. 출력 문자열
- 그냥 캐릭터배열로 쓰면 안되더라구요. 아마 FTGL 검색하셔서 레퍼런스를 많이 훑어보신 분들이면 다들 아시겠지만서도^^;;
저는 MultiByteToWideChar()를 이용해 멀티바이트를 와이드캐릭터로 변환하여 출력했습니다.
Application.h
...
#define FONT_FILE "C:\\Windows\\Fonts\\gulim.ttc"
...
public:
char m_strMsg[256];
FTFont* m_String;
wchar_t* m_wszString;
...
Application.cpp
...
// glInit() 함수 내부.. 사실 어디있든 별 상관은 없음;;
m_String = new FTPixmapFont(FONT_FILE);
m_wszString = new wchar_t[260];
...
// DrawGLScene() 함수 내부
strcpy(m_strMsg, "한글 나와라 뿅!!");
int nLen = MultiByteToWideChar(0, 0, m_strMsg, -1, NULL, NULL);
MultiByteToWideChar(0, 0, m_strMsg, -1, m_wszString, nLen)
m_String - > FaceSize(20);
glColor4f(1.0, 1.0, 1.0, 1);
glRasterPos3f(0.0, 0.0, 0.12 f);
m_String - > Render(m_wszString);
...
진작에 제대로 돌아가는 소스코드는 다 만들어놓고 폰트파일이 병맛일꺼라곤 생각도 못했습니다 =ㅂ= ;;
저처럼 바보같은 실수 안하시길 빕니다 여러분ㅎㅎ;;
출처: http://cloudtree.tistory.com/185 [cloudtree.tistory.com]
=================================
=================================
=================================
출처: http://smilemugi.net/wordpress/archives/74
기본적으로 비트맵을 읽어 오는 방식에 대해서는 GameDev.net 의 Article을 먼저 읽어 보기 바란다.
http://www.gamedev.net/page/resources/_/technical/game-programming/how-to-load-a-bitmap-r1966
OpenGL 에서 한글을 출력하는 방법을 찾기 위해서 구글링을 해 보면, 대부분의 글들이 FTGL Library 를 사용하는 방법에 대해서 알려 주고 있고, 많은 사람들이 이렇게 외부 라이브러리를 사용하는 방법을 선택하고 있는 것 같다.
하지만, 이 글에서는 dc(window device context) 를 사용하는 방법을 설명하고자 한다. 이 방법에 대해서도 몇몇 글들이 언급하고 있지만, 실제 앱에서 사용하기에는 적합하지 않다는 의견을 주고 있는 것 같다. 이유로는 속도문제가 제시되고 있다.
일단, 구현 방법에 대해서 설명하겠다.
전체 구현 방식은 Unicode String 을 임의의 Texture 에 기록하고 이 Texture를 화면에 Display 하는 것이다.
좀 더 구체적으로 설명하면, dc를 이용해서 비트맵 텍스쳐핸들을 하나 생성하고, 이 텍스쳐핸들에 출력할 텍스트를 지정된 속성(폰트, 글자색, 배경색)으로 출력한다.
그리고나서 그 텍스쳐핸들을 이용해서 실제 이미지 데이터를 얻는다. 이 이미지 데이터에는 출력할 텍스트가 이미지 형태로 존재하는 것이다.
OpenGL 에서는 이 이미지 데이터를 이용해 실제 출력할 텍스쳐를 생성한다. 그리고, 이 텍스쳐를 출력할 사각형 폴리곤 하나를 이용해서 화면에 출력하는 것이다.
소스에 추가 설명을 달았다.
// 먼저, DC(device context)를 이용해서 bitmap 을 생성한다.
HDC hdc = GetDC(NULL);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbm = CreateCompatibleBitmap(_hdc, TEXT_IMAGE_SIZE, TEXT_IMAGE_SIZE);
HGDIOBJ oldbm = SelectObject(memdc, hbm);
// 속성(폰트, 색상, 크기 등등)을 설정한다.
HFONT hfont = CreateFont(50, 50, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, L "맑은고딕");
SelectObject(memdc, hfont);
SetTextColor(memdc, RGB(255, 255, 0));
SetBkColor(memdc, RGB(0, 0, 0));
//지정된 속성으로 Unicode String 을 출력한다.
TextOut(memdc, 0, 0, L "test한글테스트ㅋ", 10);
//실제 이미지 데이터를 얻어 온다.
// Get the BITMAP from the HBITMAP
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = TEXT_IMAGE_SIZE;
bi.biHeight = TEXT_IMAGE_SIZE;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = (bi.biWidth * bi.biHeight * bi.biBitCount) / 8;
char * lpbitmap = new char[dwBmpSize];
GetDIBits(_hdc, hbm, 0, TEXT_IMAGE_SIZE, lpbitmap, (BITMAPINFO * ) & amp; bi, DIB_RGB_COLORS);
// 비트맵의 실제 이미지데이터의 RGB 데이터를 순서대로 변경 (이유는 위 링크 참조)
int byteWidth, padWidth;
byteWidth = padWidth = (bi.biWidth * bi.biBitCount) / 8;
//adjust the width for padding as necessary
while (padWidth % 4 != 0) {
padWidth++;
}
char tempvalue;
int offset = padWidth - byteWidth;
//count backwards so you start at the front of the image
for (int i = 0; i & lt; dwBmpSize; i += 3)
{
//jump over the padding at the start of a new line
if (((i + 1) % padWidth) == 0)
i += offset;
tempvalue = * (lpbitmap + i);
*(lpbitmap + i) = * (lpbitmap + i + 2);
*(lpbitmap + i + 2) = tempvalue;
}
SelectObject(memdc, oldbm);
DeleteDC(memdc);
DeleteObject(hbm);
// OpenGL 에서 위에서 생성한 이미지 데이터를 이용해서 텍스쳐를 생성한다.
glGenTextures(1, & amp; _textureid);
glBindTexture(GL_TEXTURE_2D, _textureid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TEXT_IMAGE_SIZE, TEXT_IMAGE_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, lpbitmap);
delete[] lpbitmap;
lpbitmap = NULL;
// 이 다음 단계에서는 폴리곤을 만들어서 화면에 display 하면 끝.
위와 같이 dc 를 이용해서 unicode string 을 출력하는 방법에 대해서 어려운 것은 없다.
다만 다음과 같은 문제들이 있다.
- 앱에서는 실시간으로 텍스트를 변경해 가면서 출력 요청을 한다.
- 텍스트의 길이가 매우 길어질 수도 있다.
위 문제들이 왜 문제인가하면,
첫번째 문제로 속도저하 문제 및 메모리 단편화 현상이 발생할 수 있다. 매번 텍스트 출력요청을 할 때마다, 해당 텍스쳐를 생성하려고 할 것이고, 이 과정에서 메모리를 생성/삭제를 반복적으로 하다보면, 당연히 발생할 가능성이 높다.
두번째 문제로 텍스트의 길이가 길면 텍스쳐 한장으로 해결이 안된다. 이유는 뻔하다.
위 두 문제의 해결방법에 대해서는 다음 글로 넘긴다.
=================================
=================================
=================================
출처: http://soen.kr/lecture/library/freetype/ft1.htm
1.FreeType이란
가.소개
FreeType은 폰트에 대한 정보를 추출하는 폰트 엔진이다. 폰트는 텍스트 출력에 사용되는 글꼴에 관련된 정보의 집합이다. 굉장히 많은 정보가 복잡한 구조로 직접되어 있어서 내부 구조가 굉장히 복잡하다. 포맷이 문서화되어 있기는 하지만 직접 분석해서 원하는 정보를 얻기는 상당히 어렵다. 이럴 때 폰트 엔진이 필요하다.
문자열을 출력하려면 원하는 글꼴을 만든 후 TextOut이나 DrawString으로 뿌리면 그만이다. 어차피 폰트는 문자열을 출력하기 위한 수단이며 이런 목적으로 쓸 수 있는 고수준의 함수들은 운영체제가 제공한다. 그러나 단순한 출력 이상의 뭔가를 하고 싶을 때는 폰트의 정보를 직접 읽어서 가공해야 한다. 예를 들자면 다음과 같은 경우가 해당된다.
■ 운영체제에 설치되지 않은 폰트를 사용하고 싶을 때는 폰트를 직접 읽어야 한다. 예를 들어 문서에 내장된 폰트라든가 네트워크를 통해 공유된 폰트를 사용해야 할 때 등의 경우가 이에 해당한다.
■ 워드 아트처럼 글자의 모양을 마음대로 변형하고 싶을 때. 운영체제는 글꼴을 아주 정상적인 모양으로 출력하는 기능만 제공하므로 변형하려면 외곽선을 직접 조작해야 한다.
■ 글자의 스타일을 다양하게 주고 싶을 때. 굵게, 이탤릭 정도는 되지만 이중 외곽선이나 글자 색상과 다른 특이한 밑줄 같은 것은 줄 수 없다. 직접 그려야 한다.
■ 플랫폼에 독립적인 응용 프로그램을 만들 때도 폰트 엔진을 사용해야 한다. 운영체제가 제공하는 고수준 함수는 쓰기는 편하지만 포맷에 종속적이다.
이 외에도 폰트 엔진이 필요한 경우는 많다. 하옇든 운영체제가 제공하는 문자열 출력 기능이 뭔가 부족할 때 직접 폰트를 다루어야 한다. 폰트 엔진은 폰트를 떡 주무르듯이 주무를 수 있게 해 주며 부족한 2%를 넉넉하게 채워줄 수 있다. 폰트 엔진은 여러 가지가 있지만 현재 가장 범용적이고 기능적으로 앞선 라이브러리가 바로 FreeType이다.
참 좋은 라이브러리인데 한글로 된 강좌가 없다. 국내에도 사용자가 꽤 많은데 다들 실무에 급급하다 보니 대충 익혀서 쓰기만 할 뿐 간단한 사용기조차도 올리는 사람도 보기 어렵다. 영문으로 된 강좌는 가끔 구할 수 있지만 이마저도 윈도우즈 환경이 아니라 주로 리눅스나 매킨토시 환경으로 되어 있어 국내 사정과는 잘 맞지 않다.
그래서 비록 사용 경험이 일천하지만 아는데까지 강좌를 써 보았다. 상업적으로 출판되는 출판물이 아니고 짧은 시간에 후다닥 쓰다 보니 디테일이 좀 떨어지지만 편하게 읽을 수 있도록 격식없이 썼으니 양해 바란다. 아무리 대충 썼다고는 하나 그래도 16년간 강좌만 써온 강좌의 달인... 퍽! 나가~
이 강좌의 예제들은 비스타 환경에서 한글 비주얼 스튜디오 2008로 작성했다. XP 환경의 VS 2005 컴파일러를 쓰더라도 이 강좌를 읽는데는 큰 문제가 없겠지만 사소하게 틀린 면들이 있을 수는 있으므로 환경이 다르다면 주의해서 읽기 바란다.
나.특징
FreeType의 웹 사이트는 FreeType 라이브러리를 다음과 같이 소개하고 있다.
small, efficient, highly customizable and portable, producing high-quality output font engine
작고 효율적이고 커스터마이징 가능하고 이식성있는 고품질 폰트 엔진이라고 되어 있다. 좋은말 다 붙여 놨는데 과연 어떤 특징이 있는지 정리해 보자. 장점도 있지만 단점도 있다.
■ 폰트 파일에 독립적이다. 특정 포맷만 읽는 것이 아니라 다양한 폰트를 일관된 인터페이스로 읽을 수 있다. TypeType, OpenType, Type1, CFF, PFR, BDF 등등 현재 널리 사용되는 거의 모든 폰트를 읽을 수 있다.
■ 확대 가능한(Scalable) 폰트를 지원한다. 외곽선 추출 기능이 있어서 품질 저하없이 미려한 모양으로 얼마든지 크게 출력할 수 있다. 비트맵 폰트도 물론 지원한다.
■ 힌트, 커닝 등의 고급 정보들도 섬세하게 조작할 수 있으며 트루타입 인터프리터까지 내장되어 있어 작은 크기로 출력해도 가독성이 높은 문자열을 출력할 수 있다.
■ 256 레벨의 안티 알리아싱 기능이 제공되어 고품질의 텍스트를 출력할 수 있다. 윈도우즈 2000 이하의 버전에서 고작 5레벨의 안티 알리아싱을 제공하는데 비해 훨씬 더 품질이 높다.
■ 응용 프로그램에 연결하는 형태가 자유롭다. 컴파일 타임에 정적으로 연결할 수도 있고 DLL로 만들어 실행중에 연결하여 사용할 수도 있다.
■ 라이브러리 내에 쓰기 가능한 전역 변수가 없으며 필요한 모든 메모리를 동적으로 할당한다. 그래서 ROM에서도 바로 실행할 수 있는데 이런 특성으로 인해 모바일 환경에도 충분히 활용할 수 있다. 즉, 영문폰에 한글 문자열을 출력할 수 있다는 뜻이다.
■ 라이브러리 자체는 표준 C언어로 작성되어 있어 함수만 호출하면 바로 사용할 수 있다. 물론 객체 지향적인 라이브러리보다 손이 많은 가기는 하지만 함수 레벨의 라이브러리가 처음 배우기 쉽고 효율도 좋다. C언어만 컴파일할 수 있으면 어떤 컴파일러에서나 사용할 수 있다. 물론 C++ 컴파일러에서도 당연히 사용 가능하다.
■ 특허가 걸린 기술은 일체 사용하지 않는다. 예를 들어 TrueType 관련 기술들은 애플사가 특허를 보유하고 있는데 이런 기술들은 대체 기술을 적용한다. 그래서 소송 걱정없이 사용할 수는 있지만 특정 기능에서는 품질이 조금 떨어질 수도 있다.
■ FreeType은 텍스트를 바로 출력하는 고수준의 함수가 아니라 저수준의 서비스이다. 그래서 텍스트 출력, 문자열 정렬, 캐싱 등의 작업은 직접 해야 한다. 또한 폰트를 읽기만 할 뿐 편집하는 기능도 제공되지 않는다. 즉, 아무나 쉽게 쓸 수 있는 먹기 좋은 떡은 아닌 셈이다.
FreeType은 다양한 포맷의 폰트를 지원하지만 이 강좌에서는 주로 트루 타입만을 다룬다. 왜냐하면 강좌 자체가 윈도우즈 환경에서 쓰여졌기 때문이다. FreeType은 유닉스나 매킨토시에서도 쓸 수 있지만 이 강좌에서는 다루지 않는다. 유닉스는 조금 알지만 설치할 남는 컴퓨터가 없고 집이 가난해서 매킨토시를 살 돈이 없기 때문이다.
다.설치
FreeType은 공개된 라이브러리이다. 떳떳하지 못하게 불법 복사하거나 P2P 사이트에서 남에게 아쉬운 소리해 가며 어렵게 구할 필요없이 다음 사이트에서 언제든지 다운로드받을 수 있다. 로그인이나 회원가입도 필요없다
최신 버전이 나왔는지도 항상 살펴 봐야 하고 자습서나 레퍼런스도 여기서 참조해야 하므로 즐겨찾기에 등록해 두기 바란다. 장사를 하는 사이트가 아니다 보니 디자인이 아주 검소하고 군더더기가 없다. 여러분이 이 강좌를 읽고 있는 WinApi와 거의 동급의 디자인 수준이다(솔직히 말해 WinApi가 조금 더 나아 보인다 ^_^).
여기서 라이브러리와 문서, 예제들을 다운받을 수 있다. FreeType도 나름대로 역사가 있는데 최초 1.0은 트루타입만 지원했으나 2.0부터 지원 포맷이 대폭 늘어 났으며 버전이 높아질수록 기능이 더 많이 추가되었다.
이 강좌를 쓰는 시점에서 최신 버전은 2.3.7이지만 여러분들이 이글을 읽을 때 쯤에는 아마도 더 최신 버전으로 업데이트되어 있을 것이다. 가급적이면 최신 버전을 받되 버전이 올라가면 기능의 첨삭이 당연히 있을 것이다. 최신 버전 사용자는 어! 강좌랑 다르네 하고 헷갈려하지 말고 눈치껏 강좌를 읽기 바란다.
일단 라이브러리를 받아야 실습을 해 볼 수 있으므로 다운로드부터 받아보자. Downloads의 Stable releases를 클릭하여 링크를 따라 들어가면 다음 페이지가 나타난다. 물론 지금 당장 그렇다는 것이지 장래에는 링크가 어떻게 바뀔지 알 수 없으므로 역시 눈치껏 다운로드받기 바란다.
여기서 라이브러리와 데모, 문서를 다운로드받는다. 문서는 웹 사이트에서도 읽을 수 있으므로 별도로 다운받지 않아도 상관없다. 다운로드받아봐야 어차피 html이라 웹에서 읽는것과 다르지 않다.
도표의 2번째에 있는 freetype2 링크를 클릭하여 ft237.zip을 다운로드 받는다. 압축을 풀면 freetype-2.3.7 폴더가 생기는데 이 폴더를 일단 루트에 복사해 놓자. 물론 원하는 곳에 풀어 놔도 상관없지만 이 강좌와 환경을 맞추려면 가급적 게기지 말고 시키는대로 따라하는 것이 좋다. 만약 최신 버전보다 이 강좌에서 사용하는 버전을 사용하려면 다음 사본을 받기 바란다.
압축 파일에는 바로 사용 가능한 바이너리가 포함되어 있지 않다. 다양한 운영체제에서 사용할 수 있으므로 사용 환경에 맞게 빌드해서 써야 한다. 일단 라이브러리부터 빌드하자. 다양한 운영체제별로 메이크 파일이 제공되는데 비주얼 스튜디오의 경우 builds/win32/visualc 폴더안에 솔루션 파일이 제공된다. freetype.sln 파일을 비주얼 스튜디오로 연다.
솔루션 파일은 VS 2005로 작성되어 있지만 VS 2008에서도 변환만 하면 문제없이 열 수 있다. 솔루션을 컴파일한다. 디버깅해 볼 게 아니므로 그냥 Release로 컴파일하면 된다. 경고가 엄청나게 발생하는데 확장자 C인 소스에 왜 //로 된 C++ 주석을 쓰느냐는 잔소리다. 그냥 무시해 버리면 된다. 컴파일이 완료되면 objs 폴더에 freetype237MT.lib라는 845K짜리 라이브러리 파일이 생성된다. 이 파일이 우리가 사용해야 할 라이브러리이며 배포 예제에도 포함되어 있으므로 이 강좌의 예제는 바로 컴파일해 볼 수 있다.
라이브러리의 크기가 부담스럽다면 꼭 필요한 모듈만 포함시켜 크기를 줄일 수도 있는데 커스텀 빌드 방법에 대해서는 배포 문서에 자세히 설명되어 있다. 그러나 굳이 그럴 필요는 없다. 비주얼 C++의 링커는 호출되는 함수만 쏙쏙 골라서 실행 파일에 링크할 정도로 충분히 똑똑하다. 845K가 통째로 실행 파일에 다 들어가는 것은 아니므로 부담없이 사용하면 된다.
다음은 비주얼 스튜디오에게 FreeType 라이브러리의 헤더 파일의 위치를 알려 주어야 한다. 도구/옵션 메뉴로 환경설정창을 열고 VC++ 디렉터리 노드에서 포함 파일 경로를 지정한다.
라이브러리는 프로젝트별로 직접 지정할 것이므로 포함 파일 경로만 가르쳐 주면 된다. 여기까지 작업하면 FreeType을 쓸 준비가 완료되었다. 운영체제나 링크 방식에 따라 조금씩 달라질 수도 있는데 상세한 빌드 방법은 압축 파일내의 문서에 설명되어 있다.
라.레퍼런스
어떤 과목을 공부하든지 레퍼런스는 꼭 필요하다. FreeType은 홈 페이지의 Documentation에 레퍼런스가 잘 구비되어 있으므로 도움말이 필요할 때 웹 사이트에서 원하는 정보를 바로 구할 수 있다. Index 링크로 들어가면 FreeType의 모든 함수, 구조체에 대한 정보를 볼 수 있다.
알파벳순으로 정렬되어 있으므로 별 어려움없이 함수나 구조체에 대한 도움말을 육안으로 검색할 수 있을 것이다. 도움말은 모두 링크로 연결되어 있으므로 마우스로 꾹꾹 누르기만 하면 된다. 초기화 함수에 대한 설명을 보자.
인수에 대한 설명, 리턴값에 대한 설명이 잘 기록되어 있으며 주의 사항도 친절하게 설명되어 있다. 구조체에 대한 정보도 아주 상세해서 모든 멤버의 의미를 바로 바로 조사할 수 있도록 되어 있다.
영문이지만 결코 어려운 영어가 아니므로 필요할 때마다 참조하면 된다. 만약 인터넷에 접속할 수 없는 환경이라면, 예를 들어 도서관에서 공부를 해야 한다면 이 도움말 전체를 다운로드받아 가지고 다니며 볼 수도 있다. 우리나라에서는 왠만해서는 인터넷 안되는 곳이 없으므로 그럴 필요가 없을 것이다.
도움말 외에 Typography에 대한 일반론과 Tutorial도 제공된다. 이 문서들은 분량이 얼마 안되지만 굉장히 쉽고 상세하게 쓰여져 있으므로 꼭 읽어 보기 바란다. 나는 이 문서를 인쇄하여 춘천 시립 도서관에 짱박혀서 아주 열심히 탐독했으며 그 결과 이런 강좌까지 쓰게 되었다. 처음부터 영문으로 공부하기 부담스럽다면 이 강좌를 통해 워밍업을 한 후 차근히 읽어 보기 바란다
=================================
=================================
=================================
출처: http://gpgstudy.phps.kr/forum/viewtopic.php?f=11&t=22057
Open GL 한글 출력 질문
전체글 글쓴이: crexy » 2009-01-15 09:55
오픈 GL에서 한글을 출력하려고 합니다.
그런데 싶게 찾을 것 같던 소스는 정말 없더군요..
여기 저기 둘러본 봐로는 window dc를 이용하는 방법이 있다고 하는데..
참고 코드 한줄 얻을 수 없었습니다.
알고 계신 분들 간단한 샘플코드라도 답변해 주시면 감사하겠습니다.
이것 때문에 꽤 시간을 많이 잡아 먹는군요 ㅡㅡ;
--------------------------------------------------------------------------------------------------------------------------------------------------
일단 소스인데..
http://www.codeguru.com/cpp/g-m/opengl/ ... .php/c5587
이걸로 찍으면 하드웨어 가속을 받을 수가 없습니다.
제가 이곳에서 쭉 공부하면서
윈도우 dc / wgl 비트맵 아웃라인 등등 다 써봤는데
결국은 걍 FTGL 라이브러리 써서 구현했습니다.
글씨 출력은 정말 일찌감치 라이브러리 알아보시는것을 추천합니다;
--------------------------------------------------------------------------------------------------------------------------------------------------
전체글 글쓴이: crexy » 2009-01-15 12:25
잘 활용하겠습니다.
=================================
=================================
=================================
출처: http://funnypr.tistory.com/entry/OpenGL-Tutorial-on-using-FreeType-Fonts-in-OpenGL
■ OpenGL: Tutorial on using FreeType Fonts in OpenGL[1]
네헤 라는 곳!!! 여기에 좋은 글들이 많네 .. 자 이 내용을 중심으로 이 사람은 어떻게 FreeType library를 활용했는지 보자.
1. MSVC(Microsoft Visual C++) 새 프로젝트 생성
- FreeType Library - Include folder 포함
- 라이브러리 설정(OpenGL.dlls, FreeType.dlls)
2. FreeType 설정 및 빌드를 위한 파일 복사
참고 사이트 하단에 가면 "DOWNLOAD visual C++ code for This Lesson"
- 클릭해서 다운로드
- 폴더 내에 "freetype.cpp" and "freetype.h" 파일을 생성한 프로젝트에 복사
- *.dll 파일도 생성한 프로젝트에 복사
3. FreeType 헤더파일 분석
-#include <xxxx.h> 파일들은 핸들링 및 보다 쉬운 디버깅을 위해 선언
#ifndef FREE_NEHE_H
#define FREE_NEHE_H
// FreeType Headers
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>
// OpenGL Headers
#include <windows.h> // (The GL Headers Need It)
#include <GL/gl.h>
#include <GL/glu.h>
// Some STL Headers
#include <vector>
#include <string>
// Using The STL Exception Library Increases The
// Chances That Someone Else Using Our Code Will Correctly
// Catch Any Exceptions That We Throw.
#include <stdexcept>
// MSVC Will Spit Out All Sorts Of Useless Warnings If
// You Create Vectors Of Strings, This Pragma Gets Rid Of Them.
#pragma warning(disable: 4786)
- WGL(Window OpenGL)
- 폰트 저장을 위해 구조체 선언 및 네임스페이스로 욘속이 freetype 이라고 이름 지어줌 낭낭
- 머 13장에서 배웠던 내용이라는데 난 그냥 이글만 봐서... 느낌상 위 구조체를 사용함으로써 하나의 명령 glCAllLists 를 사용하여 문자열을 출력할 수 있는 좋은 능력을 보여준다고 하넹 +_+ 흣(대단한 녀석이군)
- 128ASCII 코드를 사용하기 때문에 128개의 텍스쳐를 만들어야 함. 마지막 비트는 폰트의 픽셀 높이 정보라는군.
///Wrap everything in a namespace, that we can use common
///function names like "print" without worrying about
///overlapping with anyone else's code.
namespace freetype {
//Inside of this namespace, give ourselves the ability
//to write just "vector" instead of "std::vector"
using std::vector;
//Ditto for string.
using std::string;
//This holds all of the information related to any
//freetype font that we want to create.
struct font_data {
float h; ///< Holds the height of the font.
GLuint * textures; ///< Holds the texture id's
GLuint list_base; ///< Holds the first display list id
//The init function will create a font of
//of the height h from the file fname.
void init(const char * fname, unsigned int h);
//Free all the resources assosiated with the font.
void clean();
};
//The flagship function of the library - this thing will print
//out text at window coordinates x,y, using the font ft_font.
//The current modelview matrix will also be applied to the text.
void print(const font_data & ft_font, float x, float y,
const char * fmt, ...);
}
#endif
마지막으로 우리는 문자열을 출력할 수 있는 프로토타입(prototype)가 필요하다고 하는군. 위 코드 마지막 줄에 프린트 욘속을 말함.
4. FreeType.cpp 파일 분석
- 각 문자를 찍기 위해 텍스쳐를 사용함.
- OpenGL 텍스쳐들은 2의 제곱을 가지는 차원수를 가져야 한다고 함.
// This Function Gets The First Power Of 2 >= The
// Int That We Pass It.
inline int next_p2(int a)
{
int rval = 1;
// rval<<=1 Is A Prettier Way Of Writing rval*=2;
while (rval < a) rval <<= 1;
return rval;
}
해서 위와 같은 소스로 2제곱을 해서 리턴함
다음 함수가 제일 중요함 각 폰트의 Glyph 정보를 읽고 bitmap 저장
// Create A Display List Corresponding To The Given Character.
void make_dlist(FT_Face face, char ch, GLuint list_base, GLuint * tex_base) {
// The First Thing We Do Is Get FreeType To Render Our Character
// Into A Bitmap. This Actually Requires A Couple Of FreeType Commands:
// Load The Glyph For Our Character.
if (FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT))
throw std::runtime_error("FT_Load_Glyph failed");
// Move The Face's Glyph Into A Glyph Object.
FT_Glyph glyph;
if (FT_Get_Glyph(face - > glyph, & glyph))
throw std::runtime_error("FT_Get_Glyph failed");
// Convert The Glyph To A Bitmap.
FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal, 0, 1);
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph;
// This Reference Will Make Accessing The Bitmap Easier.
FT_Bitmap & bitmap = bitmap_glyph - > bitmap;
이제 OpenGL Texture를 위한 legal source를 만들기 위해 빈공간에 저장된 bitmap 정보를 저장함
- OpenGL에서 bitmap는 픽셀당 8bit 정보 저장
- grays를 저장할 수 있음(anti-aliased text를 만드는데 필요한 정보임)
// Use Our Helper Function To Get The Widths Of
// The Bitmap Data That We Will Need In Order To Create
// Our Texture.
int width = next_p2(bitmap.width);
int height = next_p2(bitmap.rows);
// Allocate Memory For The Texture Data.
GLubyte * expanded_data = new GLubyte[2 * width * height];
// Here We Fill In The Data For The Expanded Bitmap.
// Notice That We Are Using A Two Channel Bitmap (One For
// Channel Luminosity And One For Alpha), But We Assign
// Both Luminosity And Alpha To The Value That We
// Find In The FreeType Bitmap.
// We Use The ?: Operator To Say That Value Which We Use
// Will Be 0 If We Are In The Padding Zone, And Whatever
// Is The FreeType Bitmap Otherwise.
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
expanded_data[2 * (i + j * width)] = expanded_data[2 * (i + j * width) + 1] =
(i >= bitmap.width || j >= bitmap.rows) ?
0 : bitmap.buffer[i + bitmap.width * j];
}
}
위 작업 후 OpenGL Texture 를 만들어야 함.
- 알파 값을 통해 투명도 설정 가능하게 해놨음
// Now We Just Setup Some Texture Parameters.
glBindTexture(GL_TEXTURE_2D, tex_base[ch]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Here We Actually Create The Texture Itself, Notice
// That We Are Using GL_LUMINANCE_ALPHA To Indicate That
// We Are Using 2 Channel Data.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data);
// With The Texture Created, We Don't Need The Expanded Data Anymore.
delete[] expanded_data;
이제 우리는 텍스트를 그리기 위해 텍스쳐가 맵핑된 quads를 사용할 거얌!
- quads를 이용함으로써 장점: 회전, 크기 변경, 문자열 사용 가능, 색상 적용 가능
흣 +_+
// Now We Create The Display List
glNewList(list_base + ch, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, tex_base[ch]);
glPushMatrix();
// First We Need To Move Over A Little So That
// The Character Has The Right Amount Of Space
// Between It And The One Before It.
glTranslatef(bitmap_glyph - > left, 0, 0);
// Now We Move Down A Little In The Case That The
// Bitmap Extends Past The Bottom Of The Line
// This Is Only True For Characters Like 'g' Or 'y'.
glTranslatef(0, bitmap_glyph - > top - bitmap.rows, 0);
// Now We Need To Account For The Fact That Many Of
// Our Textures Are Filled With Empty Padding Space.
// We Figure What Portion Of The Texture Is Used By
// The Actual Character And Store That Information In
// The x And y Variables, Then When We Draw The
// Quad, We Will Only Reference The Parts Of The Texture
// That Contains The Character Itself.
float x = (float) bitmap.width / (float) width,
y = (float) bitmap.rows / (float) height;
// Here We Draw The Texturemapped Quads.
// The Bitmap That We Got From FreeType Was Not
// Oriented Quite Like We Would Like It To Be,
// But We Link The Texture To The Quad
// In Such A Way That The Result Will Be Properly Aligned.
glBegin(GL_QUADS);
glTexCoord2d(0, 0);
glVertex2f(0, bitmap.rows);
glTexCoord2d(0, y);
glVertex2f(0, 0);
glTexCoord2d(x, y);
glVertex2f(bitmap.width, 0);
glTexCoord2d(x, 0);
glVertex2f(bitmap.width, bitmap.rows);
glEnd();
glPopMatrix();
glTranslatef(face - > glyph - > advance.x >> 6, 0, 0);
// Increment The Raster Position As If We Were A Bitmap Font.
// (Only Needed If You Want To Calculate Text Length)
// glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL);
// Finish The Display List
glEndList();
}
다음 init함수는 FreeType Font 라이브러리를 초기화 하고 주어진 폰트 파일을 읽은 다음 폰트 사이즈를 설정한 후 해당 갯수의 텍스쳐를 생성하여 정보를 저장하는 작업
준비 작업임
void font_data::init(const char * fname, unsigned int h) {
// Allocate Some Memory To Store The Texture Ids.
textures = new GLuint[128];
this - > h = h;
// Create And Initilize A FreeType Font Library.
FT_Library library;
if (FT_Init_FreeType( & library))
throw std::runtime_error("FT_Init_FreeType failed");
// The Object In Which FreeType Holds Information On A Given
// Font Is Called A "face".
FT_Face face;
// This Is Where We Load In The Font Information From The File.
// Of All The Places Where The Code Might Die, This Is The Most Likely,
// As FT_New_Face Will Fail If The Font File Does Not Exist Or Is Somehow Broken.
if (FT_New_Face(library, fname, 0, & face))
throw std::runtime_error("FT_New_Face failed (there is probably a problem with your font file)");
// For Some Twisted Reason, FreeType Measures Font Size
// In Terms Of 1/64ths Of Pixels. Thus, To Make A Font
// h Pixels High, We Need To Request A Size Of h*64.
// (h << 6 Is Just A Prettier Way Of Writing h*64)
FT_Set_Char_Size(face, h << 6, h << 6, 96, 96);
// Here We Ask OpenGL To Allocate Resources For
// All The Textures And Display Lists Which We
// Are About To Create.
list_base = glGenLists(128);
glGenTextures(128, textures);
// This Is Where We Actually Create Each Of The Fonts Display Lists.
for (unsigned char i = 0; i < 128; i++)
make_dlist(face, i, list_base, textures);
// We Don't Need The Face Information Now That The Display
// Lists Have Been Created, So We Free The Assosiated Resources.
FT_Done_Face(face);
// Ditto For The Font Library.
FT_Done_FreeType(library);
}
폰트와 관련된 텍스쳐와 displaylist를 초기화 시키는 함수
void font_data::clean() {
glDeleteLists(list_base, 128);
glDeleteTextures(128, textures);
delete[] textures;
}
자원을 썼으니 반납하시오!!!!
윈도우 화면 투영 함수
// A Fairly Straightforward Function That Pushes
// A Projection Matrix That Will Make Object World
// Coordinates Identical To Window Coordinates.
inline void pushScreenCoordinateMatrix() {
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(viewport[0], viewport[2], viewport[1], viewport[3]);
glPopAttrib();
}
// Pops The Projection Matrix Without Changing The Current
// MatrixMode.
inline void pop_projection_matrix() {
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
폰트 출력함수
출력함수는 lesson13과 매우 흡사하나 두가지 중요한 점이 다르다.
- 비트멥들 대신 2채널의 텍스쳐를 사용하기 위해 OpenGL 활성화 flags 설정
- 새로운 라인을 다루기 위해 추가적인 기능을 넣었음.
///Much like Nehe's glPrint function, but modified to work
///with freetype fonts.
void print(const font_data & ft_font, float x, float y,
const char * fmt, ...) {
// We want a coordinate system where things coresponding to window pixels.
pushScreenCoordinateMatrix();
GLuint font = ft_font.list_base;
float h = ft_font.h / .63 f; //We make the height about 1.5* that of
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
*
text = 0; // Do Nothing
else {
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
}
//Here is some code to split the text that we have been
//given into a set of lines.
//This could be made much neater by using
//a regular expression library such as the one avliable from
//boost.org (I've only done it out by hand to avoid complicating
//this tutorial with unnecessary library dependencies).
const char * start_line = text;
vector < string > lines;
for (const char * c = text;* c; c++) {
if ( * c == '\n') {
string line;
for (const char * n = start_line; n < c; n++) line.append(1, * n);
lines.push_back(line);
start_line = c + 1;
}
}
/*
if(start_line) {
string line;
for(const char *n=start_line;n<c;n++) line.append(1,*n);
lines.push_back(line);
}
*/
glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glListBase(font);
float modelview_matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
//This is where the text display actually happens.
//For each line of text we reset the modelview matrix
//so that the line's text will start in the correct position.
//Notice that we need to reset the matrix, rather than just translating
//down by h. This is because when each character is
//draw it modifies the current matrix so that the next character
//will be drawn immediatly after it.
for (int i = 0; i < lines.size(); i++) {
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y - h * i, 0);
glMultMatrixf(modelview_matrix);
// The commented out raster position stuff can be useful if you need to
// know the length of the text that you are creating.
// If you decide to use it make sure to also uncomment the glBitmap command
// in make_dlist().
// glRasterPos2f(0,0);
glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str());
// float rpos[4];
// glGetFloatv(GL_CURRENT_RASTER_POSITION ,rpos);
// float len=x-rpos[0];
glPopMatrix();
}
glPopAttrib();
pop_projection_matrix();
}
5. 사용방법
step 1: 헤더파일 선언
#include "freetype.h" // Header for our little font library.
step 2: 전역 font_data object 생성
// This holds all the information for the font that we are going to create.
freetype::font_data our_font;
step 3: 폰트 자원의 메모리 할당 및 해제
생성자 또는 제일 먼저 호출되는 함수에 삽입(난 이 단어 쓸때 마다 야한거 같아)
our_font.init("test.TTF", 16); //Build the freetype font
종료 함수에 삽입
our_font.clean();
step 4: 폰트 드로웅~~~
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(0.0 f, 0.0 f, -1.0 f); // Move One Unit Into The Screen
// Blue text
glColor3ub(0, 0, 0xff);
// Position the WGL Text On The Screen
glRasterPos2f(-0.40 f, 0.35 f);
glPrint("Active WGL Bitmap Text With NeHe - %7.2f", cnt1); // Print GL Text To The Screen
// Here We Print Some Text Using Our Freetype Font
// The Only Really Important Command Is The Actual Print() Call,
// But For The Sake Of Making The Results A Bit More Interesting
// I Have Put In Some Code To Rotate And Scale The Text.
// Red Text
glColor3ub(0xff, 0, 0);
glPushMatrix();
glLoadIdentity();
glRotatef(cnt1, 0, 0, 1);
glScalef(1, .8 + .3 * cos(cnt1 / 5), 1);
glTranslatef(-180, 0, 0);
freetype::print(our_font, 320, 200, "Active FreeType Text - %7.2f", cnt1);
glPopMatrix();
// Uncomment This To Test Out Print's Ability To Handle Newlines.
// freetype::print(our_font, 320, 200, "Here\nthere\nbe\n\nnewlines\n.", cnt1);
cnt1 += 0.051 f; // Increase The First Counter
cnt2 += 0.005 f; // Increase The First Counter
return TRUE; // Everything Went OK
}
step 5: 예외처리 함수 삽입(+____+;;;)
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
try {
// Shutdown
KillGLWindow(); // Kill The Window
// Catch Any Exceptions That Were Thrown
}
catch (std::exception & e) {
MessageBox(NULL, e.what(), "CAUGHT AN EXCEPTION", MB_OK | MB_ICONINFORMATION);
}
return (msg.wParam); // Exit The Program
}
Now if we ever hit an exception, we will get a little message box telling us what happened. Note that exception handling can slow down your code, so when you are compiling a release version of your program, you may want to go to Project->Settings->C/C++, switch to the "C++ Language" category, and turn off exception handling.
So that's it! Compile the program and you should see some nice FreeType rendered text moving around underneath the original bitmapped text from lesson 13.
마지막 글
약간의 버그가 있다고 하넹
http://nehe.gamedev.net/data/lessons/http://www.cs.northwestern.edu/~sco590/fonts_tutorial.html
위 사이트 가서 버그를 샤샤삭~~~
뚜둥 실행화면
자 이렇게 나온단다.
나는 MFC 기반의 프로젝트를 만들고 있기 때문에 아마 좀 다르게 나오겠지 적용방법도 다르고 한번 해보자구웃!
역시나 제대로 출력이 안되넹
glPrint("FreeType using multi texture!!"); 요렇게 해서 찍어 봤지..
뒤에 g라는 욘속이 들어 가네 왜 그러징.. ㅋㅋ
흣... 이거 제대로 찍을라면 소스를 좀 수정해야 함.
아놔운서!!!(-_ㅡ;;)
수정해야 하는 소스는 다음과 같다.
위치: FreeType.cpp : void print(const font_data &ft_font, float x, float y, const char *fmt, ...)
const char * start_line = text;
vector < string > lines;
for (const char * c = text;* c; c++) {
if ( * c == '\n') {
string line;
for (const char * n = start_line; n < c; n++) line.append(1, * n);
lines.push_back(line);
start_line = c + 1;
}
}
if (start_line) {
string line;
for (const char * n = start_line; n < c; n++) line.append(1, * n);
lines.push_back(line);
}
위와 같이 되어 있는데.. 우선 데이터가 잘 넘어오는지 다 확인하고 나중에 lines 의 값을 찍어 보니 맹탕 알고 보니 위 소스를 보면 아하하고 아놔운서를 불렀더랬지
- 위 소스의 의도는 여러 줄을 찍는 것을 가능하게 해 주는 소스이다. 즉 넘거 받은 문자열 중에 개행문자를 만나면 줄을 바꾸고 저장.. 요런식으로 여러 줄을 찍을라고 한 작업이다.
const char * start_line = text;
vector < string > lines;
string line;
for (const char * c = text;* c; c++) {
if ( * c != '\n') line.append(1, * c);
}
lines.push_back(line);
수정된 소스라오. 난 한줄만 찍어도 충분하다.
본인은 폰트를 찍어서 회전시켜야 하는 일이 생겼다. 대부분의 그래픽 응용에서 폰트에 회전을 줄 필요는 없는 듯 보였다. 그래서 몇일 작업했더랬지.. 그래서 결국에는 회전 성공.. 하 지금은 텍스쳐를 여러개 만들어서 하는 방법이다. 이 방법보다 좋은것은 텍스쳐 아틀라스로 하나의 텍스쳐에서 좌표를 가져와 버텍스 매핑하는 방법이 되겠지 우선 여기까지만 해도 괜찮을듯 하다. 여러번해보고 버그 생기면 다시 고쳐야겠지 아뵤 힘내세요.
[1]http://nehe.gamedev.net/tutorial/freetype_fonts_in_opengl/24001/
출처: http://funnypr.tistory.com/entry/OpenGL-Tutorial-on-using-FreeType-Fonts-in-OpenGL [FunnyPR]
=================================
=================================
=================================
출처: http://blog.daum.net/knightofelf/18032
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=962700&ref=962700&page=1
-------------------------------------------------------------------
3D Font. 2D Font - Displaying text
http://www.gusongames.com/content/text_display.html
-------------------------------------------------------------------
error LNK2001: unresolved external symbol ___security_cookie
C:\DOCUME~1\shint\objs\release_mt\ftbase.obj) (.text[_FT_Raccess_Get_HeaderInfo]+0x1b1): undefined reference to `@__security_check_cookie@4'
/GS
http://smok95.tistory.com/110
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=829273&ref=829270
Unresolved external __security_cookie with Platform SDK compiler
http://blogs.msdn.com/b/nikolad/archive/2005/01/27/unresolved-external-security-cookie-with-platform-sdk-compiler.aspx
freetype237MT.lib
C:\WINDDK\3790.1830\lib\wxp\i386
bufferoverflowu.lib
C:\WINDDK\3790.1830\lib\wxp\i386
C:\Program Files\Microsoft Platform SDK\Lib
-------------------------------------------------------------------
WIN32API - SoEn 소프트웨어 공학 연구소 (라이브러리. OpenGL. FreeType. WTL. GDI+. JAVA. Delphi. ZIP)
http://soen.kr/
OpenGL 에서 한글 사용하는 방법
http://blog.naver.com/PostView.nhn?blogId=freewind_azu&logNo=140052998262&parentCategoryNo=&categoryNo=44&viewDate=&isShowPopularPosts=true&from=search
http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=104&docId=126949012&qb=d2dsVXNlRm9udEJpdG1hcHNX&enc=utf8§ion=kin&rank=1&search_sort=0&spq=0&pid=So95%2BdpySEhssvF5Rhssssssssw-097430&sid=/hANxaJlfzzoVQnGwFcSfg%3D%3D
http://blog.naver.com/nowcome/130035922465
http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=847726&ref=847726
日本語フォントサンプルプログラム - 일본어 잘 나온다.
http://www.asahi-net.or.jp/~yw3t-trns/opengl/samples/kanji1/
-std=c++11 -lglut32 -lopengl32
"../../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32/libopengl32.a"
"../../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32/libglaux.a"
"../../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32/libglu32.a"
"../../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32/libglut32.a"
"../../../Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib32/libglut.a"
C:\OGLSDK\lib
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\lib
C:\Program Files\Dev-Cpp\glut\lib
C:\Program Files\Dev-Cpp\opengl\lib
C:\Program Files\Dev-Cpp\opengl\extern\glfw-2.7.6\lib
C:\OGLSDK\include
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\include
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\include\freetype2
C:\Program Files\Dev-Cpp\glut\include
C:\Program Files\Dev-Cpp\opengl\include
C:\Program Files\Dev-Cpp\opengl\extern\glfw-2.7.6\include
C:\Program Files\Dev-Cpp\include
#include <gl\gl.h>
#include <gl\glu.h>
#define GLvoid void
wglUseFontBitmaps function
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx
https://www.winehq.org/pipermail/wine-patches/2004-January/009075.html
-------------------------------------------------------------------
[Error] '<anonymous>' has incomplete type
[Error] invalid use of 'GLvoid {aka void}'
5.GLUT
http://soen.kr/lecture/library/opengl/opengl-5.htm
성공한 영문 폰트 소스
Code samples for the OpenGL v1.1 Programming Guide (Redbook)
https://www.opengl.org/archives/resources/code/samples/redbook/
OpenGL Terrain Generation - An Introduction
http://www.codeproject.com/Articles/14154/OpenGL-Terrain-Generation-An-Introduction
[OpenGL Tutorial] Output String on the Screen(Bitmap) - 화면 중간에 출력
http://www.gisdeveloper.co.kr/429
OpenGL 한글 출력 라이브러리
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=1152&MAEULNO=138&no=4128&ref=173
http://byulbram.blog.me/100145268277
https://github.com/cdave1/ftgles
http://silpmomo.tistory.com/28
[OpenGL Tutorial] Using the Quadrics
http://www.gisdeveloper.co.kr/431
font 화면에 띄우기
http://blog.daum.net/leejuhee/4659063
opencv
glut
glew
glfw - 오픈지엘 슈퍼 바이블
http://www.hanbit.co.kr/exam/2204
glm
freeglut
FTGL
DevC++
.a
.lib
.dll
C:\Program Files\Dev-Cpp\glut\lib
C:\Program Files\Dev-Cpp\freeglut\lib
C:\Program Files\Dev-Cpp\glew-1.9.0\lib
C:\Program Files\Dev-Cpp\FTGL\lib
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\lib
C:\Program Files\Dev-Cpp\include
C:\Program Files\Dev-Cpp\glut\include
C:\Program Files\Dev-Cpp\freeglut\include
C:\Program Files\Dev-Cpp\glm
C:\Program Files\Dev-Cpp\freetype-2.6.2\include
C:\Program Files\Dev-Cpp\glew-1.9.0\include
C:\Program Files\Dev-Cpp\FTGL\include
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\include
[Error] '<anonymous>' has incomplete type
undefined reference to `gluOrtho2D@32'
libfreetype.lib opengl32.lib, glu32.lib glaux.lib
FREETYPE2
-lGLU
https://www.opengl.org/discussion_boards/showthread.php/170216-undefined-reference-to-gluOrtho2D
-std=c++11 -lglut32 -lopengl32 -lfreeglut -lglew -lglu32 -lcg -lcgGL
-static-libgcc
C:\Program Files\Dev-Cpp\FreeType-2.1.4-lib\include
Programming - Games - using OpenGL and C++
http://www.euclideanspace.com/software/games/setup/openglcpp/first/
Getting Started
https://www.opengl.org/wiki/Getting_Started
http://nehe.gamedev.net/
http://nehe.gamedev.net/tutorial/lessons_01__05/22004/
Opengl 문자열 일그러짐 현상
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=962700&ref=962700&page=1
freetype 이나 ftgl 에서 bold 구현하기(폰트문의)
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNo=20&no=945874&ref=945874
OpenGL 문자열 출력
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=960602&ref=960602
oF 에서 FTGL 을 통한 한글 출력
http://yamecoder.tistory.com/311
https://github.com/Flightphase/ofxFTGL
openGL에서 FTGL을 이용해서 한글을 사용하자.
http://iosblog.tistory.com/1
FTGL에 한글깨짐.. | OF 질문/답변
http://cafe.naver.com/openframeworks/648
OpenGL에서 텍스트 출력
http://blog.naver.com/delcube_acc/220448805895
opengl에서 한글, 한자, 특수문자 출력.. T_T;;
http://www.gpgstudy.com/forum/viewtopic.php?t=1413&sid=5060bfec24e392efa2e5f3fc01db4efb
Code Resources
https://www.opengl.org/wiki/Code_Resources
Code samples for the OpenGL v1.1 Programming Guide (Redbook)
https://www.opengl.org/archives/resources/code/samples/redbook/
Font 관련 OpenGL+VTK / 공부
http://blog.naver.com/pumpguy/30096978897
FTGL
https://www.opengl.org/archives/resources/features/fontsurvey/#ftgl
Max Script를 이용한 메쉬읽어 오기 소스/ OpenGL에서 GDI를 이
http://www.gpgstudy.com/forum/viewtopic.php?t=365&highlight=%C7%D1%B1%DB
FTGL is now hosted on SourceForge
http://homepages.paradise.net.nz/henryj/code/index.html#FTGL
ftgl-2.1.3-rc5.tar.gz (841.6 kB)
http://sourceforge.net/projects/ftgl/files/
FreeType is a freely available software library to render fonts.
http://www.freetype.org/
GLTT 2.5.2
http://gltt.sourceforge.net
OpenGL Headline News
https://www.opengl.org/
The FreeType Project
http://sourceforge.net/projects/freetype/?source=typ_redirect
Free Game Development Libraries 게임 개발
http://nicegary.egloos.com/4451035
Rendering/FreeType/CMakeLists.txt
https://github.com/Kitware/VTK/commit/41f5902e1be7a3e3d2e61cffd23da16d6a0a91f7
Rendering/FreeType/module.cmake
https://github.com/Kitware/VTK/commit/33b2338696de5f42d6fa179e911d8062c4cada8a
DevC++ 에서 GLUT 사용하는 방법
http://blog.daum.net/knightofelf/15182
GLUT program link error
http://stackoverflow.com/questions/12919277/glut-program-link-error
Freeglut 3.0.0 [Released: 7 March 2015]
http://freeglut.sourceforge.net/
http://www.transmissionzero.co.uk/software/freeglut-devel/
freeglut 3.0.0 MSVC Package
freeglut 3.0.0 MinGW Package
OpenGL Programming
https://en.wikibooks.org/wiki/OpenGL_Programming
OpenGL Programming/Modern OpenGL Tutorial Text Rendering 01
https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01
Wikibooks OpenGL / Modern Tutorials · Files
https://gitlab.com/wikibooks-opengl/modern-tutorials/tree/master
MinGW and GLUT undefined reference to '_imp____glutInitWithExit@12'
https://stackoverflow.com/questions/21210895/mingw-and-glut-undefined-reference-to-imp-glutinitwithexit12
The Mesa 3D Graphics Library
http://www.mesa3d.org/download.html
glewGenBuffers
https://www.opengl.org/sdk/docs/man/html/glGenBuffers.xhtml
http://docs.gl/gl3/glGenBuffers
http://gamedev.stackexchange.com/questions/68252/glgenbuffers-fails-with-0x0-win7-glew
glew devc++
Post Tutorial: set up glew and freeglut under dev-c++
https://www.opengl.org/discussion_boards/showthread.php/181902-Tutorial-set-up-glew-and-freeglut-under-dev-c
The OpenGL Extension Wrangler Library
http://sourceforge.net/projects/glew/files/glew/1.9.0/
glew-1.13.0-win32.zip (3.1 MB)
http://www.bloodshed.net/dev/devcpp.html
use glew with Dev-C++
http://www.gamedev.net/topic/325666-use-glew-with-dev-c/
(OpenGL/GLSL) Dev-C++ and GLEW?
https://www.3dbuzz.com/forum/threads/190504-%28OpenGL-GLSL%29-Dev-C-and-GLEW
Installation of freeglut, devc++, glew step-by-step for opengl programming in C++
http://setupguidelines.blogspot.kr/2015/01/installation-of-freeglut-devc-glew-step.html
The OpenGL Extension Wrangler Library
http://glew.sourceforge.net/
OpenGL extensions
WGL extensions
GLX extensions
glew-20150805.tgz
glew-20150124.tgz
C:\slapos\cygwin-cache\http%3a%2f%2fbox-soft.com%2f\x86\release\glew
C:\slapos\cygwin-cache\http%3a%2f%2fbox-soft.com%2f\x86\release\glew\libGLEW-devel
C:\Program Files\Dev-Cpp\QuadricMesh\ext\glew\lib\win32-vc
C:\Program Files\Dev-Cpp\glew-1.9.0\lib
C:\shint\test 폴더\DevC++ OpenGL glut 설치 문서
FTGLOutlineFont
http://oglft.sourceforge.net/
OGLFT: OpenGL-FreeType Library 0.8
GLE Tubing and Extrusion Fact Sheet
http://www.linas.org/gle/
OGLFT Namespace Reference
http://oglft.sourceforge.net/namespace__OGLFT.html
Flightphase/ofxFTGL
https://github.com/Flightphase/ofxFTGL
make pretty type in code with Rick Companje's ofx wrapper for Sam Hocevar FTGL library
openframeworks/openFrameworks
openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
https://github.com/openframeworks/openFrameworks
How to include Openframeworks header within opencv code?
http://stackoverflow.com/questions/12022735/how-to-include-openframeworks-header-within-opencv-code
"../../../Program Files/Dev-Cpp/lib/OPENGL32.LIB"
"../../../Program Files/Dev-Cpp/lib/GLAUX.LIB"
"../../../Program Files/Dev-Cpp/lib/GLU32.LIB"
"../../../Program Files/Dev-Cpp/lib/glut32.lib"
"../../../Program Files/Dev-Cpp/freeglut/lib/libfreeglut.a"
"../../../Program Files/Dev-Cpp/QuadricMesh/lib32/DevIL.lib"
"../../../Program Files/Dev-Cpp/QuadricMesh/lib32/glut32.lib"
"../../../Program Files/Dev-Cpp/QuadricMesh/lib32/ILU.lib"
"../../../Program Files/Dev-Cpp/QuadricMesh/lib32/ILUT.lib"
"../../../Program Files/Dev-Cpp/glew-1.9.0/lib/glew32.lib"
"../../../Program Files/Dev-Cpp/glew-1.9.0/lib/glew32mx.lib"
"../../../Program Files/Dev-Cpp/glew-1.9.0/lib/glew32mxs.lib"
"../../../Program Files/Dev-Cpp/glew-1.9.0/lib/glew32s.lib"
glGenBuffers
C Specification
http://docs.gl/gl3/glGenBuffers
https://www.opengl.org/sdk/docs/man/html/glGenBuffers.xhtml
GLM 설치
http://junsueg5737.blog.me/220511107783
http://glm.g-truc.net/0.9.7/index.html
http://blog.naver.com/junsueg5737/220511107783
http://minimonk.net/1667
libfreetype tutorial 따라하기
http://minimonk.net/1667
Download freeglut-3.0.0.tar.gz
http://sourceforge.net/projects/freeglut/?source=typ_redirect
Freeglut 3.0.0 [Released: 7 March 2015]
http://freeglut.sourceforge.net/index.php#download
http://freeglut.sourceforge.net/docs/api.php#FontRendering
http://freeglut.sourceforge.net/docs/api.php
http://freeglut.sourceforge.net/docs/install.php
http://www.transmissionzero.co.uk/computing/using-glut-with-mingw/
OpenGL Programming/Modern OpenGL Tutorial Text Rendering 01
https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01
modern-tutorials / common
https://gitlab.com/wikibooks-opengl/modern-tutorials/tree/master/common
modern-tutorials / text01_intro
https://gitlab.com/wikibooks-opengl/modern-tutorials/tree/master/text01_intro
=================================
=================================
=================================
출처: http://www.gpgstudy.com/forum/viewtopic.php?t=1413
opengl에서 한글, 한자, 특수문자 출력.. T_T;;
전체글 글쓴이: 한자출력급한이.. T_T » 2003-01-14 19:15
opengl로 게임을 만들고 있습니다.
한글, 한자, 특수문자(ⓑ 같은..)까지 다 찍어야 한다고 합니다. T_T;;
dc를 이용하는 방법 밖에는 없을 것 같다고 생각됩니다.
뮤 같은 거 보면 opengl로 만들었음에도 불구하고
한자와 특수 문자까지 출력이 잘되는 것으로 보아..
아마도 dc를 이용한것 같은데...
혹시 참고할만한 좋은 자료가 없을까요 ?
이곳에 질문 답변을 보니.. futurity님께서는
이미 gl에서 특수 문자까지 다 출력되게 만드셨던데..
혹시 소스 공개가 가능하신지 ? (아~ 염치없습니다. T_T)
한자 필요한이.. T_T
전체글 글쓴이: 한자 필요한이.. T_T » 2003-01-14 20:02
포럼을 검색해보니 감사하게도..
DC를 이용해서 gl에서 한글 찍으신 예제가 있는데....
http://www.gpgstudy.com/forum/viewtopic ... 7%D1%B1%DB
webyouco 라는 분께서 만드신것 같은데요..
링크가 깨졌네요... T_T
webyouco님께서 아직 이곳을 출입하신다면.. 좀 제공해 주시면 감사하겠습니다..
다른 분이라도 혹시 받아 놓은 신분 계시면 자료실에 올려주시면 정말 감사하겠습니다.
지나가다
전체글 글쓴이: 지나가다 » 2003-01-14 20:53
흠..답변은 아닌데....
뮤가 오픈지엘로 만들어졌나요????
DX 아니였나????????????
ㅡ_ㅡ?????
webyouco전체글: 94가입일: 2001-12-01 09:00
안녕하십니까 예전에 webyouco 입니다.
전체글 글쓴이: webyouco » 2003-01-14 21:13
제가 예전에 링크건 소스는 네츠고가 망하는 바람에
지워 졌습니다.
그 소스의 내용은 BITMAP을 만들어서 거기에 DC를 얻어 글씨를 찍고
그걸 다시 텍스쳐로 바꿔서 화면에 뿌려주는 방식입니다.
하지만 이렇게 할 경우 무지 느리더군요....
DC를 이용하는 방법 말고도 직접 TTF화일을 읽어와서 찍는 방법도 있습니다.
여기에 대한 내용은 FTGL이라는 소스에 잘 나와 있습니다.
저도 링크는 모르겠네요.. sourceforge같은 곳에서 찾아 보시길 바랍니다.
손님
뮤 오픈 지엘 맞는 거 같습니다.
전체글 글쓴이: 손님 » 2003-01-14 23:39
임포트된 dll 함수 테이블을 보면 opengl 함수 리스트들이 쫘악 나옵니다.
손님
ftgl에 대한이야기가
전체글 글쓴이: 손님 » 2003-01-15 00:31
ftgl에 대한 이야기가 여기도 나오는 군요..
예전에 저도 ftgl을 이용해서 한글을 출력하려고 시도를 했더랬습니다.
그런데, 한글 트루타입 폰트들의 용량이 커서 로딩이 좀 부담스럽고..
그것을 둘째쳐도....
ftgl의 폰트를 지원하기는 하지만 출력 부분이 제대로 한글을 출력하더록
되어있지 않은 것 같습니다.
혹시 ftgl을 이용해서 한글 출력에 성공하신 분이 계시다면
공유해주시면 감사하겠습니다.
webyouco전체글: 94가입일: 2001-12-01 09:00
webyouco
전체글 글쓴이: webyouco » 2003-01-15 09:48
이상하군요. FTGL정말 잘 되는데요...
FTGL에서 Render하는 부분에 유니코드로 써주시면 무리 없이 한글이 나올거라
고 생각되는데요... 전 잘 사용하고 있습니다. 지금 회사에서 만들고 있는 엔진도
FTGL을 사용해서 한글을 출력하고 있습니다. 속도도 잘나오고 좋습니다.
macwin전체글: 127가입일: 2001-08-04 09:00연락처:
한글..
전체글 글쓴이: macwin » 2003-01-15 09:53
DC로 사용해서 찍을때, 대량의 텍스트가 나오면 심각하게 느려지는
단점이 있지만, 이는 캐쉬를 사용해서 처리하면 해결을 하실수 있습니다.
그래서 어느정도 만족할만한 속도가 나오더군요.
열라 허덥하지만, 혹시나 제꺼라도 원하시면다면 그부분에 대한 소스를
공개 하도록 하지요.
그럼.
EMAIL : macwin at hitel.net
http://blog.naver.com/macwin
gmpguru전체글: 61가입일: 2002-12-13 23:21
전체글 글쓴이: gmpguru » 2003-01-15 10:36
소스까지 있는 좋은 싸이트가 있군요,..
http://www.superfrontier.com/pages/code ... index.html
webyouco전체글: 94가입일: 2001-12-01 09:00
webyouco
전체글 글쓴이: webyouco » 2003-01-15 10:45
TinmyFont.h
#ifdef WIN32
#define FONT_FILE "H2porl.ttf"
#endif
#ifndef FONT_H
#define FONT_H
#define FONT_SCREEN 5
#define FONT_VIEWPORT 6
#define FONT_OUTLINE 0
#define FONT_POLYGON 1
#define FONT_TEXTURE 2
#define FONT_PIXEL 3
#define FONT_BITMAP 4
#define FONT_EXTRD 5
#define DEFAULT_SIZE 20
#include <Tinymain.h>
#include <FTGLExtrdFont.h>
#include <FTGLOutlineFont.h>
#include <FTGLPolygonFont.h>
#include <FTGLTextureFont.h>
#include <FTGLPixmapFont.h>
#include <FTGLBitmapFont.h>
class TinyFont
{
public:
FTFont* m_font;
int m_Size;
int m_type;
~TinyFont();
TinyFont(int size = 20,int type = FONT_TEXTURE, const char * fontfile = FONT_FILE);
void Print(float x,float y,float z , float r,float g, float b,float a,int type ,WCHAR * _data,...);
};
#endif
코드: 모두 선택
TinyFont.cpp
#include <font.h>
TinyFont::TinyFont(int size, int type,
const char * fontfile) {
m_font = NULL;
switch (type) {
case FONT_OUTLINE:
m_font = new FTGLOutlineFont;
break;
case FONT_POLYGON:
m_font = new FTGLPolygonFont;
break;
case FONT_TEXTURE:
m_font = new FTGLTextureFont;
break;
case FONT_PIXEL:
m_font = new FTGLPixmapFont;
break;
case FONT_BITMAP:
m_font = new FTGLBitmapFont;
break;
case FONT_EXTRD:
m_font = new FTGLExtrdFont;
break;
}
m_type = type;
if (!m_font - > Open(fontfile, false)) {
// fprintf( stderr, "Failed to open font %s", fontfile);
// exit(1);
MessageBox(NULL, "지정된 폰트가 없습니다.", "ERROR", MB_OK);
}
if (!m_font - > FaceSize(size)) {
// fprintf( stderr, "Failed to set size");
// exit(1);
MessageBox(NULL, "폰트 사이즈를 변경할수 없습니다.", "ERROR", MB_OK);
}
m_font - > Depth(100);
m_font - > CharMap(ft_encoding_unicode);
m_Size = DEFAULT_SIZE;
}
TinyFont::~TinyFont() {
if (m_font != NULL) {
delete m_font;
m_font = NULL;
}
}
WCHAR lpszBuffer[1000];
void TinyFont::Print(float x, float y, float z, float r, float g, float b, float a, int type, WCHAR * __data, ...) {
if (m_font == NULL) return;
va_list marker;
va_start(marker, __data);
vswprintf(lpszBuffer, __data, marker);
va_end(marker);
EngineManager * Manager = Tiny_Engine_GetManager();
switch (type) {
case FONT_SCREEN:
if (m_type == FONT_POLYGON) {
glDisable(GL_TEXTURE_2D);
} else {
glEnable(GL_TEXTURE_2D);
}
glDisable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, Manager - > Width, 0, Manager - > Height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glNormal3f(0.0, 0.0, 1.0);
glTranslated(x, Manager - > Height - y - m_Size, 0);
glColor4f(r, g, b, a);
m_font - > render(lpszBuffer);
glColor4f(1, 1, 1, 1);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
break;
case FONT_VIEWPORT:
if (m_type == FONT_POLYGON) {
glDisable(GL_TEXTURE_2D);
} else {
glEnable(GL_TEXTURE_2D);
}
glDisable(GL_BLEND);
glPushMatrix();
glNormal3f(0.0, 0.0, 1.0);
glTranslated(x, y, z);
glColor4f(r, g, b, a);
m_font - > render(lpszBuffer);
glColor4f(1, 1, 1, 1);
glPopMatrix();
break;
}
}
코드: 모두 선택
위의 소스는 FTGL을 이용하여 OPENGL에 한글을 출력하는 Class입니다.
그냥 가져다가 사용하셔도 별무리 없을 것이라고 생각됩니다.
EngineManager * Manager = Tiny_Engine_GetManager();
부분은 무시하세요 Manager->Width,Manager->Height는
디스플레이의 가로세로 입니다.
도움받은이
아~ 여러 정보를 제공해주셔서 정말 감사합니다.
여러 정보를 공유해 주셔서 정말 감사합니다.
gpgstudy에서 항상 많은 도움을 받고 있습니다.
너무 고마워서 눈물이 날 지경이라는.. T_T;;
다시 한번 정말 감사드립니다.
여기서 ftgl이라는게?
freetype 폰트 라이브러리를 의미하시는 건가요?
sourceforge에서 ftgl이라고 치면 아무것도 검색이 안되네요
저도 한글출력에 문제를 겪고 있던 터에 아주 도움을 많이 받았습니
이왕이면 우리나라 수출의 주무대인 중국이나 일본쪽에 폰트 처리 방법도 논의 되었으면 좋겠네요.
전체글 글쓴이: soaringhs » 2003-01-15 12:26
http://www.opengl.org/developers/code/f ... index.html
unicode에는 확장완성형 한글코드에만 있는 특수문자는 빠져 있을테니 어느정도 수정이 필요하겠네요. unicode만
지원한다면 출력에 관한 부분은 어느 언어 윈도우를 사용하던지 고칠필요는 없겠죠.
TTF 파일 공개용 뭐가 있나요 ?
윈도우 기본 폰트은 NGULIM.TTF를 로딩했하면
너무 용량이 커서 로딩 시간이 너무 깁니다.
용량작고 무료인 공개 트루타입 폰트가 없을까요 ?
윗분 보니까 h2porl.ttf라는게 있는데 ? 그것은 무료 폰트인가요 ?
무료라면 어디서 구할 수 있을까요 ?
폰트가 안 찍혀여...
위에 webyouco님이 올려 놓은 소스로 테스트 프로그램을 만들어서 찍어봤는데
영문은 제대로 찍히는거 같은데 한글이 제대로 안 찍히네요 제가 잘못 사용한건
가요?
wchar_t myString[16];
strcpy ( (char*) myString , "A" ) ;
font->Print( 0 , 0 , 0 , 1.0 , 1.0 , 1.0 , 1.0 , FONT_SCREEN , myString ) ;
두바이트이상이 들어가면 이상해지는거 같습니다. 도와주세요...!!
폰트 뭘로 하셨어요 ?
폰트가 한글이 안들어가 있는 걸로 하면 안 찍히드라구요.
그리고 이상하게도 폰트 뷰어로 보면 한글이 있는대도
안 찍히는게 있습니다.
한글 폰트가 들어있는게 확실한 폰트로 한번해보세요.
webyouco
전체글 글쓴이: webyouco » 2003-01-15 16:06
"H2porl.ttf"는 윈도우에서 제공하는 기본 폰트 입니다.
폰트가 존재하지 않는다면 에러메세지가 나타 납니다.
H2porl.ttf 폰트는 2메가 정도 됩니다.속도도 로딩속도도 느리지 않네여^^
코드: 모두 선택
TinyFont Font = new TinyFont(27, FONT_TEXTURE);
wchar_t myString[16];
wcscpy(myString, L "한글");
font - > Print(0, 0, 0, 1.0, 1.0, 1.0, 1.0, FONT_SCREEN, myString);
delete Font;
으로 하시면 됩니다.
sourceforge 에서 FTGL을 찾아 보니 안나오네요..
저도 어디서 찾았는지 모르겠습니다.아나 FreeType 홈피안에 link된 곳중
어디가 아닌가 하는 생각이 드네요^^;; FTGL은 UniCode로 사용할수 있으니
폰트만 있다면 유니코드로 중국어나 일본어도 화면에 찍을수 있다고 생각됩니다.
webyouco님
감사 합니다 잘 되는군요.
L 이라는걸 몰라서 그냥 넣어서 안되는거였군요
유니코드로 변환시켜줘야한다는걸 몰랐네요
암튼 감사합니다.
유니코드면
전체글 글쓴이: ljh131 » 2003-01-15 17:30
유니코드면
윈9x에선 지원이 안된다는건가요?
상태정렬...
전체글 글쓴이: 손님 » 2003-01-15 17:55
상태정렬 어케 되나요 ?
지금 제작중엔 게임에 붙였더니
gl 상태를 다 망가트려 버리네요.
이거 ftgl 소스 보고 일일이 찾아서 맞춰야 하나요 ?
=================================
=================================
=================================
출처: http://cloudtree.tistory.com/171
이야...
내가 이런거 하는날도 있구나...
암튼 이틀간의 삽질의 결과가 너무 아까워서 이렇게 공개합니다
현재 이야기 하는건 윈도우 XP (32bit) + VS 2008 에서 입니다.
FTGL을 사용하게 위해서는 Freetype 라이브러리가 필요합니다. 각각의 링크를 따라 들어가서 라이브러리를 받습니다.
Freetype의 압축을 풀고 폴더를 확인 합니다. 본인의 감(?)에 따라 어디로 가야 우리가 원하는게 있을지 폴더를 찍어봅니다...
그렇지요... build 항목에 들어가면 OS 나 개발환경별 컴파일 플랫폼을 제공합니다. win32가 눈에 들어옵니다.
win32 아래에는 위와 같이 각 환경별로 제공하는 *.dsw 또는 *.sln이 있습니다.
많은 공개 코드를 써본건 아니자만 이것처럼 친절한 라이브러리는 처음이네요. 암튼 2008로 들어가서 생각없이 "빌드"질을 해 대시면 됩니다. 그러면 ft2312_D.lib (Debug) 와 ft2312.lib (Release)를 object/win32 아래에서 만나실 수 있습니다. 상당히 다양한 컴파일 옵션이 있습니다. 일반모드와 cpu에 따른 모드가 있는데 저는 그냥 기본적인 Debug와 Release 모드만을 사용하였습니다.
이제 재료가 다 준비 되었으니 라이브러리와 header들을 옮깁니다...
-hearder파일은 include 안에 있는 것을 모두 include폴더로 ...
-lib 들은 lib폴더로 ...
-2008의 경우는 program files/v_ s_ 9.0 폴더의 vc폴더 아래에도 넣어도 되지만 program files/windows SDKs/Windows/v6.0a 에도 가능... 특별이 gl 폴더는 v_ s_ 9.0 이 아닌 windows SDKs 아래에 있음...
이제 FTGL 컴파일을 합시다
FTGL 도 매우친철합니다. msvc 폴더를 유심히 봅니다. msvc ... microsoft visual studio... 그렇지요...
아래에 내려가면 vc 8.0 vc7.1 버젼의 환경이 있습니다. 8.0은 2005 이고 7.1은 2003 인가 그럴겁니다...
8.0을 선택하고 2008 에서 열면 무리없이 컨버젼 됩니다. 걍 컴파일 합니다. 그러면 현재위치에서 한번만 위로 올라가면 못보던 Build라는 폴더가 만들어져 있고 그곳에 다 모여 있습니다. (*.dll, *lib, 등등...)
이제 적당한 위치에 옮겨두면 OK... 사용준비 완료 입니다...
일거 같지요... ??
확실하지는 않으나 win64 bit에서는 문제가 없는데 32bit XP에서 사용하려면 문제가 발생합니다. 아마 환경에 따라서 전처리자가 결정이 안되는것 때문에 이 라이브러리로 visual studio 6.0 에서 개발하신다면 꽤나 애 먹으실 겁니다. dll에 구현되어 있는 함수가 제대로 export가 안되었을때 나오는 에러 메세지를 보게 되실겁니다. 즉,
error LNK2001: unresolved external symbol "public: virtual class FTBBox __thiscall FTFont::BBox(unsigned short const*,int,class FTPoint,class FTPoint)" (?BBox@FTFont@@UAE?AVFTBBox@@PBGHVFTPoint@@1@Z)
이와 비슷한것을 두개 더 보게 되실겁니다
(현재까지 제 경험상 winXP에서 OpenGL이 가장 원활하게 돌아갑니다. 그리고 저는 아직도 visual studio 6.0 을 못 버리고 있구요.)
다시 FTGL 컴파일 하는곳으로 돌아갑니다.
ftgl.dll 속성으로 들어가서 구성속성->c/c++->언어->wchar_t를 기본제공 형식으로 처리 를 예 에서 아니오로 바꾸고 다시 컴파일 하면 위의 문제는 사라집니다.
이건 제가 해결한건 아니고... 구글링 하다보니
http://objectmix.com/graphics/729918-ftgl-visual-studio.html
저와 동일한 문제를 안고 있던 분이 있더군요. 이자리를 질문하고 답변해준 분들께 감사의 말씀을...
FTGL을 사용하면 3D 화면상에다 글자를 2D 혹은 3D로 뿌릴 수 있고 각종폰트( 한글)도 자유자제로 쓸 수 있습니다. (OpenGL에서 글자쓰는게 만만한 일은 아닙니다. 특히 2D는... 그렇다고 DC 에다 때려 넣어서 쓰면... 3D perspective 상황에서는 글자도 안 보일겁니다.)
아뭏든 이렇게 하고 나면 깨끗한... 그리고 본인이 가장 좋아하는 영문폰트인 verdana를 써서
텍스트를 출력할 수 있습니다
이렇게 말이지요...
구글 검색을 통해서 FTGL에 관한 한글정보를 얻으신분들은 자료들이 상당히 오래 되었음을 발견하시게 될겁니다. 그래서 해보려면 상당히 많이 틀린것을 알 수있고 특히 FTGL은 함수들이 상당히 많이 바뀌어서 이 라이브러리 쓰는게 그리 녹녹하지 않았습니다.
그냥 instance하게 불러서 작업하신다면 위의같은 처리 안해도 작동합니다.
그런데 가령 위의 FTGL 객체를 class member variable로 동적할당을 하려면 위의 방법으로 하셔야 되지 않을까 합니다.
2차 출처 : http://blog.daum.net/piewani/16768994
출처: http://cloudtree.tistory.com/171 [cloudtree.tistory.com]
=================================
=================================
=================================
출처: http://www.gpgstudy.com/forum/viewtopic.php?t=13147
freetype에서 일정크기 이하에서의 처리 질문입니다..
운영자: 류광
11 개의 게시글 • 1개 중 1 페이지
jabi6전체글: 43가입일: 2004-12-16 11:43
freetype에서 일정크기 이하에서의 처리 질문입니다..
전체글 글쓴이: jabi6 » 2006-10-27 10:42
우선.. 아랫글들을 다 검색해보았습니다..
현재 폰트는 굴림입니다..
특정크기 이하라고 하셧는데.. 대부분 20크기라고 하더군요..
그런데 제가 확인한바로는 꼭 20이하가 아닌.. 특정 크기인게 맞는거 같습니다..
FT_Set_Pixel_Sizes(face, 20, 0); => 물론 그냥 비트맵을 가져다쓰면 이상하게 나옵니다..
FT_Set_Pixel_Sizes(face, 10, 0); => 20보다작은데도 글자가 이상없이 나옵니다..
그러하여 제가 얻어낸 결론은 특정크기에서만 이상하게 나온다입니다..
(제 주관적인 견해이니.. 잘못된 점은 지적바랍니다..)
위에서 이상하게 나온다는것은
pixel_mode가 평소 값이 아닌 ft_pixel_mode_mono가 와서 그렇다는건데요.
평소에는 8비트 grey값이 오는데 위의 모드값이 오면 1비트 값이 옵니다..
몇몇분들이 말하신거처럼.. 현재 저 grey값을 알파 텍스쳐의 알파값으로 넣어서
텍스쳐를 생성했습니다. 8비트값이면 0~255이니깐 깔끔한 텍스트가 나오는데요..
1비트면 난감해집니다.. 1비트일때 어케 계산하여서 글자를 출력하였습니다..
그런데.. 그 깔끔하게.. 안티먹은걸로 찍히던 글자들이.. ft_pixel_mode_mono가 와서..
그 해당픽셀을 0xff로 찍었더니.. 각진(??)글자가 나오더군요..
->각진이란.. 안티가 안먹은 글자를 제 생각대로 말한겁니다..
저 각진글자의 처리를 다들 어케 하시는지 해서 문의 올립니다.. 그냥 각진대로 놔두는지..
아니면 먼가 해결방안이 잇는지 해서요..
그럼 부탁드립니다..
추신.. 그런데.. 제 아이디가.. 블럭인걸까요.. 왜 제글은.. 답글이 안달릴까요.. 흠냐...
그래도!! 물어볼렵니다^^.. 물어보는게 죄는 아니잔아요~~
다들 즐거운 시간들되세요^^
언제나 초보인.. 프로그래머
전체글 글쓴이: 도지성 » 2006-10-27 13:24
굴림의 경우에는 ttf 중에서도 embedded bitmap을 가지고 있는 폰트입니다. 따라서 디자인 단계 때부터 특정 사이즈
이하에서는 미리 bitmap화된 monochrome data를 돌려 줍니다.
FreeType을 사용하실 때는 당연히 2가지 pixel mode에 대해서 모두 대응해 주셔야 하고, 님께서 하신 방법인 0x00과 0xFF
두가지로 분리하는 것이 맞습니다. 각져 보이는 것이 이상하고 생각될 수도 있겠지만 그것은 font 디자인 시 품질을 더 좋게 하기
위해서 그런 것입니다. 굳이 작은 사이즈에서도 anti-aliasing 되는 폰트를 원하시면 2M 정도의 한글 ttf 파일들을 적용하시면
될 겁니다. (한양쪽이나...)
제 생각으로는 작은 사이즈에서는 embedded bitmap이 적용된 쪽이 나아 보일 듯한데요... font 출력에 anti-alising이 적용되는
것이 더 좋은가에 대해서는 '조엘 온 소프트웨어'의 관련 내용을 보시고 판단하시는 것도 좋을 것 같습니다.
전체글 글쓴이: 곡마단주 » 2006-10-27 14:02
도지성 작성:굴림의 경우에는 ttf 중에서도 embedded bitmap을 가지고 있는 폰트입니다. 따라서 디자인 단계 때부터 특정 사이즈
이하에서는 미리 bitmap화된 monochrome data를 돌려 줍니다.
어떤 폰트 파일이 embedded bitmap을 가지고 있는지 여부는 어떻게 알 수 있나요?
전체글 글쓴이: jabi6 » 2006-10-27 15:31
그렇군요.. 흠.. 내심. 속으로 먼가 빼먹어서 그런게 아닐까 걱정하고있었습니다..
이제는.. 스트링열의 높이 맞추기에 대해서 연구해봐야겠네요.. 이게 매우 난감한데요..
비트맵이. 조금 난감하게 들어와서요.. 한글은 일정크기로 고정되는듯하구요.. 영어같은 경우는. 비트맵의 높이/넓이가
바뀌어서 오는데 아무생각없이 씩으면 뒤에 붙어서 찍히네요.. 왼쪽상단 모서리 0.0이라는거죠..
이것 맟출려구.. 노력하는데 안되네요.. glyph_mat 쪽을 보다보니 bearingY라는 있더군요.. 그림 보고나서 아자.. 이것만큼만
옴기면 되것구나!! 했지만!!.. 역시 저의 짧은 생각으로 인하여.. 아니더군요..
현재 개선책은 어짜피.. 폰트찍을 렉트가 올테니. 렉트의 bottom값을 기준으로해서 그 위로 찍자인데.. 흠냐.. 만들고서도 맘에
안드는중입니다.. 에구..
다시한번!!! 답글 감사합니다^^
언제나 초보인.. 프로그래머
전체글 글쓴이: 도지성 » 2006-10-27 20:55
어떤 폰트 파일이 embedded bitmap을 가지고 있는지 여부는 어떻게 알 수 있나요?
코딩으로 실시간에 확인하시려면 TTF를 직접 열어서 'EBDT' 태그가 존재하는지 보면 됩니다. 일반적인 RIFF
형식의 4bytes의 tag가 들어가기 때문에 필요한 태그가 아니면 length만큼 skip하면서 계속 찾아 가면 됩니다.
TrueType 또는 OpenType의 spec을 보시면 되는데 Apple이나 MS측에서 공개로 제공하는 것으로 알고 있습니다.
(EBDT: Embedded Bitmap Data Table)
-------------------------------------------------------------------
그리고 글자의 y 좌표 가 안맞는 것은 아래의 문제 때문인데요,
아마도 (0,0)을 좌상단으로 생각하고 코딩을 하신 것 같습니다. FreeType 뿐만 아니라 대부분의 상용 fone engine도
(0,0)의 기준은 항상 baseline입니다. 위의 그림에서 origin이라고 되어 있는 부분입니다.
전체글 글쓴이: jabi6 » 2006-10-30 10:43
흠 늦은 답변인데요... (0,0)기준으로 된다는것은 알고있는점이구요.. 프리타입에서만 그러는지 다 그러는지는 모르지만..
좌표 기준이 틀리더군요..
현재 도지성님이 보여주신건
Those used to layout the glyph in horizontal text layouts (Latin, Cyrillic, Arabic, Hebrew, etc.), and those used to
layout the glyph in vertical text layouts (Chinese, Japanese, Korean, etc.).
위의 전문에서 사용된 horizontal text layouts인거 같습니다.. 한글과 영어는 vertical text layouts를 사용하는거 같구요..
그러면 좌표 기준이 바뀝니다.. 자세한 자표기준은
http://freetype.sourceforge.net/freetyp ... tep2.html에 있습니다.. 제가 그림 붙이는법을 몰라서리.. 미안합니다..
그러하여서.. 저는 아무생각없이 bearingY만큼 아래로찍었지요.. 이게 답이야하면서.. 그러나.. 이게.. 아니었던게지요.. 하하..
지금도 고민중입니다..
머그냥.. 대충 해결햇지만 맘에는 안드네요... 흠냐루.. 답변 갑사합니다^^
언제나 초보인.. 프로그래머
전체글 글쓴이: jabi6 » 2006-10-30 10:48
전체 현재위치(0,0) + bearingY를 해서 했더니.. 안되었던거지요..
그래서 해결책으로한 방법은.. 어짜피.. 폰트를찍을대 렉트값을 인자로 넣을거니간.. 렉트의 bottom위에 찍는
방식으로 해결햇는데.. 그리 맘에 들지는 안네요^^.. 그럼 즐거운 시간되세요^^
언제나 초보인.. 프로그래머
전체글 글쓴이: 도지성 » 2006-10-30 13:33
한글은 구조상 horizontal text layouts과 vertical text layouts을 둘 다 지원합니다. '굴림'과 '@굴림'이 있는
이유가 그것 때문입니다. 그리고 이것은 font 디자인의 문제이기 때문에 어떤 font라도 vertical text layouts을
넣을 수 있습니다. 그리고 한글을 가로로 계속 찍으시겠다면 horizontal text layouts이고
그것에 맞도록 font metric을 적용하셔야 합니다.
또 다른 thread에서 말씀하신 outline 출력 문제는 FTGL만큼 좋은 예제는 없을 듯 한데요...
전체글 글쓴이: jabi6 » 2006-10-30 14:27
답변 감사합니다^^..
우선 제가 잘못알고 잇는게 많앗네요..
가로로 잘(??) 출력하기도 이만저만 힘든게 아니네요..(제 실력상..^^;;)
에거. 더 연구해봐야 될듯합니다..
외곽선은 도지성님이 말하신.. FTGL을 볼려구합니다..
그전에 우선. freetype에서 설명하는 외곽선에 대해서 해석점 하고 볼려구합니다..(제 해석실력이 미천하여.. 오래 걸리네요..하하...)
줄맟춤이라구 해야되나요.. 그건 다시 또 연구해봐야겠네요.. 아무래도 bottom에 맞게 출력하는건 먼가 아닌듯해서요..
아.. 전 비트맵에 넣을때부터 줄을 맟추어서 넣을려구 합니다.. 실시간으로 만들어서 찍어주는거죠..흠냐..
한장에 완성형 글자를 다 넣고서 빼서 쓰는방식도 생각해봣지만.. 이게 나름대로 메모리 잡아먹는게 조금 그래서요..
머.. 부하는 걸리겟지만.. 쓰고 지우고 해야죠...
흠 그럼 질문사항이 한개 있습니다..
horizontal text layouts이고 그것에 맞도록 font metric을 적용하셔야 합니다.
-> 이것에 대한 질문인데요 horizontal text layouts(가로 출력방식이라구 이해함)일때 그 해당 그것에 맞게 font metric를
적용하라구 하셧는데.. 이건 잘.. 계산해서 높이를 맟추라는 말씀이신지요.. 예로 제가 한것처럼 렉트이 bottom 위에
찍는식으로요.. 아니면 다른 방법이잇다는 것인지요??
에고.. 먼가.. 잡고 늘어지는거 같아서.. 보기는 매우 안좋습니다만.. 그래도 성실히 답변해주시니 다시 물어봅니다.. 죄송합니다^^...
언제나 초보인.. 프로그래머
전체글 글쓴이: 도지성 » 2006-10-30 18:34
저의 첫 답변에 말씀드린 'baseline 기준'이라는 말에 모든 것이 있습니다. top이나 bottom을 기준으로 하면 'f'와 'g'를 동시에
찍으면 높이가 안맞습니다. 그래서 top과 bottom 사이에 baseline이라는 것을 둡니다. 영어 공책에 보면 아래 2/3 지점에
빨간줄로 된 그 라인이 baseline입니다.
윗 글에 직접 링크하신 페이지에 보면 baseline 기준으로 출력하는 소스도 나와 있습니다. my_draw_bitmap()인가로 최종
출력할 때 y값 맞춰 주는 것입니다.
답글이 매우 많이 늦었습니다^^..
전체글 글쓴이: jabi6 » 2006-11-07 14:33
도지성님 의 말을 듣고서..
튜토리얼을 다시.. 열심히 보니깐.. 되더군요..
튜포리얼 2번이 센터의 센터??를 맟추는 그런거더군요..
이걸 잘 바꾸니 되네요^^
감사합니다!! 아주 많은 도움이되엇씁니다^^
=================================
=================================
=================================
출처: http://nehe.gamedev.net/tutorial/freetype_fonts_in_opengl/24001/
Tutorial on using FreeType Fonts in OpenGL
So here's a quick tutorial to show you how to use the FreeType version 2 font rendering library in OpenGL. By using the FreeType library we can create anti-aliased text that looks better than text made using bitmap fonts (as in Lesson 13). Our text will also have some other advantages over bitmap fonts - it will be easy to rotate and works well with OpenGL's picking functions.
Note: This tutorial has a small bug, see the fix here!
Motivation
Here I've printed out the same text using both WGL bitmap fonts and fonts rendered with FreeType as per this tutorial (both are Arial Black Italic).
The basic problem with using bitmaps fonts is that in OpenGL bitmaps are by definition binary images. This means that an OpenGL bitmap stores only one bit of information per-pixel. If you zoom in on the text created using WGL bitmaps, the result looks like this:
Because bitmaps are binary images, there are no gray pixels in the image above, and it means that the text looks blocky.
Luckily it is fairly easy to make better looking fonts using the GNU FreeType library. FreeType is the same library that Blizzard uses to render the fonts in their games, so you know it has to be good!
Here's a close up of the text that I've created with the help of the FreeType library:
You can see that there are a fair number of gray pixels around the edges of the text; this is typical of an anti-aliased font, the gray pixels make the font look smoother from a distance.
Creating the Program
The first step is to get yourself a copy of the GNU FreeType library. Go to /data/lessons/http://gnuwin32.sourceforge.net/packages/freetype.htm and download the binaries and developer files. When you install it make sure to notice the licensing terms, which basically say that if you are going to use FreeType in your own programs, you need to give them credit somewhere in your documentation.
Now we need to setup MSVC to use FreeType. So create new project as in Lesson 1, but when you go to Project->Settings->Link make sure you add libfreetype.lib to Object Modules / libraries along with opengl32.lib, glu32.lib and glaux.lib (if required).
Next we need to go to Tools->Options->Directories and add the FreeType library directories. Under "Show Directories For" select "Include Files", then double click on the empty line at the bottom of the directory list, after you double click a "..." button will appear that you can use to browse for a directory. In this way add
C:\PROGRAM FILES\GNUWIN32\INCLUDE\FREETYPE2
and
C:\PROGRAM FILES\GNUWIN32\INCLUDE
To you list of header directories.
Now under "Show Directories For" select "Library Files", and this time add
C:\PROGRAM FILES\GNUWIN32\LIB
At this point we should be able to compile programs using FreeType, but they won't run unless they can access the freetype-6.dll. Right now you have a copy of that DLL file in your GNUWIN32\BIN directory, and if you put it somewhere where all your programs can see it (Program Files\Microsoft Visual Studio\VC98\Bin is a good choice), you will be able to run programs using FreeType. But remember that if you distribute a program that you have made using FreeType, you will need to also distribute copies of the DLL along with it.
Ok, now we can finally start writing code. I've decided to work off the Lesson 13 source, so grab a copy of lesson 13 if you don't have one already. Copy lesson13.cpp to your project directory, and add the file to the project.
Now add and create two new files called "freetype.cpp" and "freetype.h". We will put all our FreeType specific code into these files, and then modify lesson13 a little to show off the functions that we've written. When we are done, we will have created a very simple OpenGL FreeType library that could theoretically be used in any OpenGL project.
We will start with freetype.h.
Naturally, we need include the FreeType and OpenGL headers. We will also include some handy parts of the Standard Template Library, including STL's exception classes, which will make it easier for us create nice debugging messages.
#ifndef FREE_NEHE_H
#define FREE_NEHE_H
// FreeType Headers
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>
// OpenGL Headers
#include <windows.h> // (The GL Headers Need It)
#include <GL/gl.h>
#include <GL/glu.h>
// Some STL Headers
#include <vector>
#include <string>
// Using The STL Exception Library Increases The
// Chances That Someone Else Using Our Code Will Correctly
// Catch Any Exceptions That We Throw.
#include <stdexcept>
// MSVC Will Spit Out All Sorts Of Useless Warnings If
// You Create Vectors Of Strings, This Pragma Gets Rid Of Them.
#pragma warning(disable: 4786)
We will put all the information that each font needs into one structure (this will make managing multiple fonts a little easier). As we learned in Lesson 13, when WGL creates a font, it generates a set of consecutive display lists. This is nifty, because it means that you can use glCallLists to print out a string of characters with just one command. When we create our font we will set things up the same way, which means that the list_base field will store the first of 128 consecutive display lists. Because we are going to use textures to draw our text, so we will also need storage for the 128 associated textures. The last bit of info that we will need is the height, in pixels, of the font that we have created (this will make it possible to handle newlines in our print function).
// Wrap Everything In A Namespace, That Way We Can Use A Common
// Function Name Like "print" Without Worrying About
// Overlapping With Anyone Else's Code.
namespace freetype {
// Inside Of This Namespace, Give Ourselves The Ability
// To Write Just "vector" Instead Of "std::vector"
using std::vector;
// Ditto For String.
using std::string;
// This Holds All Of The Information Related To Any
// FreeType Font That We Want To Create.
struct font_data {
float h; // Holds The Height Of The Font.
GLuint * textures; // Holds The Texture Id's
GLuint list_base; // Holds The First Display List Id
// The Init Function Will Create A Font With
// The Height h From The File fname.
void init(const char * fname, unsigned int h);
// Free All The Resources Associated With The Font.
void clean();
};
The last thing we need is a prototype for our print function:
// The Flagship Function Of The Library - This Thing Will Print
// Out Text At Window Coordinates X, Y, Using The Font ft_font.
// The Current Modelview Matrix Will Also Be Applied To The Text.
void print(const font_data & ft_font, float x, float y,
const char * fmt, ...);
} // Close The Namespace
#endif
And that's the end of the header file! Time to open up freetype.cpp.
// Include Our Header File.
#include "freetype.h"
namespace freetype {
We are using textures to display each character in our font. OpenGL textures need to have dimensions that are powers of two, so we need to pad the font bitmaps created by FreeType to make them a legal size. That's why we need this function:
// This Function Gets The First Power Of 2 >= The
// Int That We Pass It.
inline int next_p2(int a)
{
int rval = 1;
// rval<<=1 Is A Prettier Way Of Writing rval*=2;
while (rval < a) rval <<= 1;
return rval;
}
The next function that we need is make_dlist, it is really the heart of this code. It takes in an FT_Face, which is an object that FreeType uses to store information about a font, and creates a display list coresponding to the character which we pass in.
// Create A Display List Corresponding To The Given Character.
void make_dlist(FT_Face face, char ch, GLuint list_base, GLuint * tex_base) {
// The First Thing We Do Is Get FreeType To Render Our Character
// Into A Bitmap. This Actually Requires A Couple Of FreeType Commands:
// Load The Glyph For Our Character.
if (FT_Load_Glyph(face, FT_Get_Char_Index(face, ch), FT_LOAD_DEFAULT))
throw std::runtime_error("FT_Load_Glyph failed");
// Move The Face's Glyph Into A Glyph Object.
FT_Glyph glyph;
if (FT_Get_Glyph(face - > glyph, & glyph))
throw std::runtime_error("FT_Get_Glyph failed");
// Convert The Glyph To A Bitmap.
FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal, 0, 1);
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph) glyph;
// This Reference Will Make Accessing The Bitmap Easier.
FT_Bitmap & bitmap = bitmap_glyph - > bitmap;
Now that we have a bitmap created by FreeType, we need to pad it with empty pixels to make it a legal source for an OpenGL texture. It's important to remember that while OpenGL uses the term "bitmap" to mean binary images, in FreeType bitmaps store 8 bits of information per pixel, so FreeType's bitmaps can store the grays that we need to create anti-aliased text.
// Use Our Helper Function To Get The Widths Of
// The Bitmap Data That We Will Need In Order To Create
// Our Texture.
int width = next_p2(bitmap.width);
int height = next_p2(bitmap.rows);
// Allocate Memory For The Texture Data.
GLubyte * expanded_data = new GLubyte[2 * width * height];
// Here We Fill In The Data For The Expanded Bitmap.
// Notice That We Are Using A Two Channel Bitmap (One For
// Channel Luminosity And One For Alpha), But We Assign
// Both Luminosity And Alpha To The Value That We
// Find In The FreeType Bitmap.
// We Use The ?: Operator To Say That Value Which We Use
// Will Be 0 If We Are In The Padding Zone, And Whatever
// Is The FreeType Bitmap Otherwise.
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
expanded_data[2 * (i + j * width)] = expanded_data[2 * (i + j * width) + 1] =
(i >= bitmap.width || j >= bitmap.rows) ?
0 : bitmap.buffer[i + bitmap.width * j];
}
}
With the padding done, we can get onto creating the OpenGL texture. We are including an alpha channel so that the black parts of the bitmap will be transparent, and so that the edges of the text will be slightly translucent (which should make them look right against any background).
// Now We Just Setup Some Texture Parameters.
glBindTexture(GL_TEXTURE_2D, tex_base[ch]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Here We Actually Create The Texture Itself, Notice
// That We Are Using GL_LUMINANCE_ALPHA To Indicate That
// We Are Using 2 Channel Data.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data);
// With The Texture Created, We Don't Need The Expanded Data Anymore.
delete[] expanded_data;
We use texture mapped quads to draw our text. This means that it will be easy to rotate and scale text, and it will also make fonts inherit their color from the current OpenGL color (none of which would be true if we used pixmaps).
// Now We Create The Display List
glNewList(list_base + ch, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, tex_base[ch]);
glPushMatrix();
// First We Need To Move Over A Little So That
// The Character Has The Right Amount Of Space
// Between It And The One Before It.
glTranslatef(bitmap_glyph - > left, 0, 0);
// Now We Move Down A Little In The Case That The
// Bitmap Extends Past The Bottom Of The Line
// This Is Only True For Characters Like 'g' Or 'y'.
glTranslatef(0, bitmap_glyph - > top - bitmap.rows, 0);
// Now We Need To Account For The Fact That Many Of
// Our Textures Are Filled With Empty Padding Space.
// We Figure What Portion Of The Texture Is Used By
// The Actual Character And Store That Information In
// The x And y Variables, Then When We Draw The
// Quad, We Will Only Reference The Parts Of The Texture
// That Contains The Character Itself.
float x = (float) bitmap.width / (float) width,
y = (float) bitmap.rows / (float) height;
// Here We Draw The Texturemapped Quads.
// The Bitmap That We Got From FreeType Was Not
// Oriented Quite Like We Would Like It To Be,
// But We Link The Texture To The Quad
// In Such A Way That The Result Will Be Properly Aligned.
glBegin(GL_QUADS);
glTexCoord2d(0, 0);
glVertex2f(0, bitmap.rows);
glTexCoord2d(0, y);
glVertex2f(0, 0);
glTexCoord2d(x, y);
glVertex2f(bitmap.width, 0);
glTexCoord2d(x, 0);
glVertex2f(bitmap.width, bitmap.rows);
glEnd();
glPopMatrix();
glTranslatef(face - > glyph - > advance.x >> 6, 0, 0);
// Increment The Raster Position As If We Were A Bitmap Font.
// (Only Needed If You Want To Calculate Text Length)
// glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL);
// Finish The Display List
glEndList();
}
The next function that we are going to create will use make_dlist to create a set of display lists corresponding to a given font file and pixel height.
FreeType uses truetype fonts, so you will want to find yourself some truetype font files to feed into this function. Truetype font files are very common, and there are a bunch of sites out there where you can download lots of different truetype fonts for free. Windows 98 used truetype for nearly all of it's fonts, so if you can find an old computer running windows98, you can get all of the standard fonts in truetype format from its windows/fonts directory.
void font_data::init(const char * fname, unsigned int h) {
// Allocate Some Memory To Store The Texture Ids.
textures = new GLuint[128];
this - > h = h;
// Create And Initilize A FreeType Font Library.
FT_Library library;
if (FT_Init_FreeType( & library))
throw std::runtime_error("FT_Init_FreeType failed");
// The Object In Which FreeType Holds Information On A Given
// Font Is Called A "face".
FT_Face face;
// This Is Where We Load In The Font Information From The File.
// Of All The Places Where The Code Might Die, This Is The Most Likely,
// As FT_New_Face Will Fail If The Font File Does Not Exist Or Is Somehow Broken.
if (FT_New_Face(library, fname, 0, & face))
throw std::runtime_error("FT_New_Face failed (there is probably a problem with your font file)");
// For Some Twisted Reason, FreeType Measures Font Size
// In Terms Of 1/64ths Of Pixels. Thus, To Make A Font
// h Pixels High, We Need To Request A Size Of h*64.
// (h << 6 Is Just A Prettier Way Of Writing h*64)
FT_Set_Char_Size(face, h << 6, h << 6, 96, 96);
// Here We Ask OpenGL To Allocate Resources For
// All The Textures And Display Lists Which We
// Are About To Create.
list_base = glGenLists(128);
glGenTextures(128, textures);
// This Is Where We Actually Create Each Of The Fonts Display Lists.
for (unsigned char i = 0; i < 128; i++)
make_dlist(face, i, list_base, textures);
// We Don't Need The Face Information Now That The Display
// Lists Have Been Created, So We Free The Assosiated Resources.
FT_Done_Face(face);
// Ditto For The Font Library.
FT_Done_FreeType(library);
}
Now we need a function to cleanup all the displaylist and textures associated with a font.
void font_data::clean() {
glDeleteLists(list_base,128);
glDeleteTextures(128,textures);
delete [] textures;
}
Here are two little functions that we are going to define in anticipation of our print function. The print function is going to want to think in pixel coordinates (also called window coordinates), so we are going to need to switch to a projection matrix that makes everything measured in pixel coordinates.
We are using two very handy OpenGL functions here, glGet to get the window dimensions, and glPush / PopAttrib to make sure that leave the matrix mode in the same state as we found it. If you are not familiar with these functions, it's probably worth your time to look them up in your favorite OpenGL reference manual.
// A Fairly Straightforward Function That Pushes
// A Projection Matrix That Will Make Object World
// Coordinates Identical To Window Coordinates.
inline void pushScreenCoordinateMatrix() {
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]);
glPopAttrib();
}
// Pops The Projection Matrix Without Changing The Current
// MatrixMode.
inline void pop_projection_matrix() {
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
Our printing function looks very much like the one from lesson 13, but there are a couple of important differences. The OpenGL enable flags that we set are different, which reflects the fact that we are actually using 2 channel textures rather than bitmaps. We also do a little extra processing on the line of text that we get in order to properly handle newlines. Because we are such good samaritans, we take care to use OpenGL's matrix and attribute stacks to ensure that the function undoes any changes that it makes to OpenGL's internal state (this will prevent anyone using the function from suddenly finding that, say, the modelview matrix had mysteriously changed).
// Much Like NeHe's glPrint Function, But Modified To Work
// With FreeType Fonts.
void print(const font_data &ft_font, float x, float y, const char *fmt, ...) {
// We Want A Coordinate System Where Distance Is Measured In Window Pixels.
pushScreenCoordinateMatrix();
GLuint font=ft_font.list_base;
// We Make The Height A Little Bigger. There Will Be Some Space Between Lines.
float h=ft_font.h/.63f;
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
*text=0; // Do Nothing
else {
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
}
// Here Is Some Code To Split The Text That We Have Been
// Given Into A Set Of Lines.
// This Could Be Made Much Neater By Using
// A Regular Expression Library Such As The One Available From
// boost.org (I've Only Done It Out By Hand To Avoid Complicating
// This Tutorial With Unnecessary Library Dependencies).
const char *start_line=text;
vector<string> lines;
for(const char *c=text;*c;c++) {
if(*c=='\n') {
string line;
for(const char *n=start_line;n<c;n++) line.append(1,*n);
lines.push_back(line);
start_line=c+1;
}
}
if(start_line) {
string line;
for(const char *n=start_line;n<c;n++) line.append(1,*n);
lines.push_back(line);
}
glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glListBase(font);
Because we are using texture mapped quads, any transformations that we apply to the modelview matrix before making our glCallLists call will apply to the text itself. This means that there is the potential to rotate or scale the text (another advantage over using WGL bitmaps). The most natural way to take advantage of this fact would be to leave the current modelview matrix alone, thus letting any transformation made before the print function apply to the text. But because of the way that we are using the modelview matrix to set font position, this won't work. Our next best option is to save a copy of the modelview matrix that is passed in, and apply it between the glTranslate and the glCallLists. This is easy enough to do, but because we need to draw the text using a special projection matrix the effects of the modelview matrix will be a little different than one might expect- everything will be will be interpreted on scale of pixels. We could get around this issue entirely by not resetting the projection matrix inside of print. This is probably a good idea in some situations - but if you try it make sure to scale the fonts to an appropriate size (they tend to be something like 32x32, and you probably want something on the order of 0.01x0.01).
float modelview_matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix);
// This Is Where The Text Display Actually Happens.
// For Each Line Of Text We Reset The Modelview Matrix
// So That The Line's Text Will Start In The Correct Position.
// Notice That We Need To Reset The Matrix, Rather Than Just Translating
// Down By h. This Is Because When Each Character Is
// Drawn It Modifies The Current Matrix So That The Next Character
// Will Be Drawn Immediately After It.
for (int i = 0; i < lines.size(); i++) {
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y - h * i, 0);
glMultMatrixf(modelview_matrix);
// The Commented Out Raster Position Stuff Can Be Useful If You Need To
// Know The Length Of The Text That You Are Creating.
// If You Decide To Use It Make Sure To Also Uncomment The glBitmap Command
// In make_dlist().
// glRasterPos2f(0,0);
glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str());
// float rpos[4];
// glGetFloatv(GL_CURRENT_RASTER_POSITION ,rpos);
// float len=x-rpos[0]; (Assuming No Rotations Have Happend)
glPopMatrix();
}
glPopAttrib();
pop_projection_matrix();
}
} // Close The Namespace
The library is now finished. Open up lesson13.cpp and we will make some minor modifications to show off the functions we just wrote.
Underneth the other headers, add in the freetype.h header.
#include "freetype.h" // Header For Our Little Font Library.
And while we are here, let's create a global font_data object.
// This Holds All The Information For The Font That We Are Going To Create.
freetype::font_data our_font;
Now we need to see about creating and destroying the resources for our font. So add the following line to the end of InitGL
our_font.init("Test.ttf", 16); // Build The FreeType Font
And add this line to the start of KillGLWindow to destroy the font when we are finished.
our_font.clean();
Now we need to modify the function DrawGLScene function so that it uses our print function. This could have been as simple to adding a single line "hello world" command to the end of the function, but I got a little more creative because I wanted to show off rotations and scaling.
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(0.0 f, 0.0 f, -1.0 f); // Move One Unit Into The Screen
// Blue text
glColor3ub(0, 0, 0xff);
// Position the WGL Text On The Screen
glRasterPos2f(-0.40 f, 0.35 f);
glPrint("Active WGL Bitmap Text With NeHe - %7.2f", cnt1); // Print GL Text To The Screen
// Here We Print Some Text Using Our Freetype Font
// The Only Really Important Command Is The Actual Print() Call,
// But For The Sake Of Making The Results A Bit More Interesting
// I Have Put In Some Code To Rotate And Scale The Text.
// Red Text
glColor3ub(0xff, 0, 0);
glPushMatrix();
glLoadIdentity();
glRotatef(cnt1, 0, 0, 1);
glScalef(1, .8 + .3 * cos(cnt1 / 5), 1);
glTranslatef(-180, 0, 0);
freetype::print(our_font, 320, 200, "Active FreeType Text - %7.2f", cnt1);
glPopMatrix();
// Uncomment This To Test Out Print's Ability To Handle Newlines.
// freetype::print(our_font, 320, 200, "Here\nthere\nbe\n\nnewlines\n.", cnt1);
cnt1 += 0.051 f; // Increase The First Counter
cnt2 += 0.005 f; // Increase The First Counter
return TRUE; // Everything Went OK
}
The last thing to do is put in a little exception handling code. Go to WinMain and open up a try { .. } statement at the beginning of the function.
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
try { // Use Exception Handling
Then modify the end of the function to have a catch {} command.
// Shutdown
KillGLWindow(); // Kill The Window
// Catch Any Exceptions That Were Thrown
}
catch (std::exception & e) {
MessageBox(NULL, e.what(), "CAUGHT AN EXCEPTION", MB_OK | MB_ICONINFORMATION);
}
return (msg.wParam); // Exit The Program
}
Now if we ever hit an exception, we will get a little message box telling us what happened. Note that exception handling can slow down your code, so when you are compiling a release version of your program, you may want to go to Project->Settings->C/C++, switch to the "C++ Language" category, and turn off exception handling.
So that's it! Compile the program and you should see some nice FreeType rendered text moving around underneath the original bitmapped text from lesson 13.
General Notes
I have been keeping track of all known bugs in this tutorial, please take a look at the errata.
There are a number of improvements that you might want to make to this library. For one thing using the font data objects directly tends to be a little awkward, so you might want to create a standard cache of fonts to hide font resource management from users. You might also want to take a tip from the OpenGL library itself and create a font stack, which would let you avoid passing in references to font objects each time you called the print function. (These are all things that I currently do things in my own code, but decided to leave out of the tutorial for the sake of simplicity.) You might also want to make a version of print that centers the text- to do that you will probably need to use the techniques discussed below.
Right now I have the text spinning around it's center. However, to get an effect like this to work for arbitrary text, you would need to have some way of knowing exactly how long the line of text was - this can be a little tricky. One way to get the length of the text is to put glBitmap commands into the font's display lists in order modify the raster position as well as the modelview matrix (I've left the necessary line in the code, but it is commented out). Then you can set the raster position to x,y before using glCallLists, and use glGet to find the raster position after the text is drawn - the difference in raster positions will give you the length of the text in pixels.
You should be aware that FreeType fonts take up much more memory than WGL's bitmap fonts (that's one the advantages of binary images, they use very little space). If for some reason you really need to conserve your texture memory, you might want to stick with the code from lesson 13.
Another interesting advantage of using texture mapped quads to represent fonts is that quads, unlike bitmaps, work well with the OpenGL picking functions (see Lesson 32 ). This makes life much easier if you want to create text that responds when someone holds the mouse over it or clicks on it. (Making WGL fonts work well with picking functions is possible, again the key trick is to use raster coordinates to figure out the length of the text in pixels).
And finally, here are some links to OpenGL font libraries. Depending on your goals and compiler you may want to use one of them instead of this code (there are many more of them out there, I've generally only included things that I have some amount of experience with myself).
GLTT This library is an old library that doesn't seem to still be maintained, but it has gotten some very positive reviews. Based on FreeType1. I think you will need to find a copy of the old FreeType1 source distribution to compile it in MSVC6. Download available from /data/lessons/http://www.opengl.org/developers/faqs/technical/fonts.htm.
OGLFT A nice FreeType2 based font library, it takes a bit of work to compile under MSVC though (mostly just typical for-loop scope problems). Seems to be targeted at linux machines... /data/lessons/http://oglft.sourceforge.net.
FTGL Yet a third FreeType based font library, this one was clearly developed for OS X. /data/lessons/http://homepages.paradise.net.nz/henryj/code/#FTGL.
FNT A non-FreeType library that is part of PLIB. Seems to have a nice interface, uses its own font format, compiles under MSVC6 with a minimum amount of fuss... /data/lessons/http://plib.sourceforge.net/fnt.
* DOWNLOAD Visual C++ Code For This Lesson.
* DOWNLOAD Borland C++ Builder 6 Code For This Lesson. ( Conversion by Galileo Sjodin )
* DOWNLOAD Code Warrior 5.3 Code For This Lesson. ( Conversion by Scott Lupton )
* DOWNLOAD Dev C++ Code For This Lesson. ( Conversion by mt-Wudan )
* DOWNLOAD Linux/SDL Code For This Lesson. ( Conversion by Aaron Graves )
* DOWNLOAD Python Code For This Lesson. ( Conversion by Brian Leair )
* DOWNLOAD Visual Studio .NET Code For This Lesson. ( Conversion by Joachim Rohde )
=================================
=================================
=================================
출처: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/142576
From: "George Ogata" <g_ogata / optushome.com.au> > Ilmari Heikkinen <kig / misfiring.net> writes: > > > Is there some simple and nice Ruby lib for rendering text into an OpenGL > > texture? Something that takes a string and puts out a BGRA/ARGB pixels. > > > > Or if that's a bad idea, what's the usual way of rendering nice-looking > > text in GL? By nice-looking I mean variable width anti-aliased truetype > > fonts with different font sizes, hinting, line heights and all the usual > > font rendering lib niceties. Those niceties being the main reason I > > don't really want to cook up my own font renderer :) [...] > Otherwise, FTGL is nice, but I don't see any ruby bindings for it. It > has lazy-loaded, texture-based fonts for fast rendering, and extruded > geometry fonts for when you want render text as a solid object from > different angles. Hopefully it wouldn't be too hard to wrap some ruby > bindings around it. Nice !!! http://homepages.paradise.net.nz/henryj/code/index.html#FTGL I didn't know about FTGL... I'm currently using GLUT's simple built-in fonts. I see FTGL already builds on Windows/Mac/*nix, which is awesome. Ilmari, I don't know what your time frame for this is but I'll likely delve into creating some minimal ruby bindings for FTGL in the next month or two. Looking at FTGL's test cases, it seems nice and straightforward to call. From test/FTGLBitmapFont-Test.cpp: const char* const GOOD_ASCII_TEST_STRING = "test string"; void testDisplayList() { buildGLContext(); FTGLBitmapFont* bitmapFont = new FTGLBitmapFont(FONT_FILE); bitmapFont->FaceSize(18); int glList = glGenLists(1); glNewList( glList, GL_COMPILE); bitmapFont->Render(GOOD_ASCII_TEST_STRING); glEndList(); CPPUNIT_ASSERT( glGetError() == GL_NO_ERROR); } So far I've always written ruby <-> C++ binding code by hand, but I want to learn SWIG. Maybe this will be the time. Ilmari, if FTGL looks appropriate for your project, let's keep in touch so we don't end up duplicating effort in the ruby bindings? Maybe we could create a rubyforge project.... ? Or ? Regards, Bill
=================================
=================================
=================================
출처: https://stackoverflow.com/questions/22123725/properly-position-y-axis-of-font-in-ftgl
Yesterday, I struggled about how to render FTGL font in a window whose origin is at top-left.
Retaining this kind of orthographic settings makes it difficult for me to properly align FTGL font, esp. in y-axis
void enable2D(int w, int h) { winWidth = w; winHeight = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, w, h, 0, 0, 1); glMatrixMode(GL_MODELVIEW); }
Then rendered it like this:
glPushMatrix(); glTranslated(X, Y + font.LineHeight(), 0); glScalef(1, -1, 0); //reverse scaling of y font.Render(str); glPopMatrix();
I try to measure the bounding boxes of different fonts but it gives me inconsistent results.
Here they are:
Notice the inconsistency of y-position of boxes
And also the code:
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
///Draw the fonts
for (int i = 0;i < N; ++i)
{
auto &X = x[i];
auto &Y = y[i];
auto &font = fonts[i];
glColor3ub(0, 0, 0);
glPushMatrix();
glTranslated(X, Y + font.LineHeight(), 0);
glScalef(1, -1, 0);
font.Render(str);
glPopMatrix();
}
///Draw the boxes
for (int i = 0;i < N; ++i)
{
auto &X = x[i];
auto &Y = y[i];
auto &box = boxes[i];
glColor3ub(255, 0, 0);
glPushMatrix();
glTranslated(X, Y, 0);
glBegin(GL_LINE_LOOP);
glVertex2f(box.Lower().X(), -box.Lower().Y()); //top-left
glVertex2f(box.Upper().X() - box.Lower().X(), -box.Lower().Y()); //top-right
glVertex2f(box.Upper().X() - box.Lower().X(), +box.Upper().Y() - box.Lower().Y() * 2); //bottom-right
glVertex2f(box.Lower().X(), +box.Upper().Y() - box.Lower().Y() * 2); //bottom-left
glEnd();
glPopMatrix();
}
But I want to achieve a box that is totally fitted to the rendered font like this:
I just manually adjust some values to make it fit
Specific question is, how do I calculate y-position of the rendered font in this kind of settings?
I don't know what FTGL::Descender() does but I think it somewhat related to this?
I will accept as answer any links that discusses this kind of topic.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
However, after trial and error, I figured out the fault I am doing.
The box
First of all, I should have consider when doing this kind of coordinate system, that the left-most and upper-most part of the box should be set zero, i.e:
glVertex2f( 0, 0 ); glVertex2f( w, 0 ); glVertex2f( w, h ); glVertex2f( 0, h );
So I would not need to worry about the other things. And from that, I ensure that when translating the font to the specified coordinate, it must be relative to top-left-origin window (no padding, offsets, etc, etc...)
The Font
Now doing the translation in font section, I do this:
float x_offset = (font.BBox(str).Lower().X() * font_scale); float y_offset = (font.BBox(str).Upper().Y() * font_scale); glPushMatrix(); ///the coorinate should now be relative the box! glTranslatef( x - x_offset, y + y_offset, 0 ); glScalef( font_scale, -font_scale, 0); //notice the negative in y font.Render(str); glPopMatrix();
Now it should be look like this
The font that draws outside the box (#6), maybe is due to the style of the font.
Thanks! Hope someone could help by this :D
Update:
There was an error in my previous calculation, anyway, I updated my answer to be more accurate. You can see the changes in my edit history.
Update:
There was still an error here. The FTGL::BBox returns only the current bounding boxes of the current text, w/c the heights may vary when the largest glyph height is not present in the current string. I check the source code again but I cannot find the yMax w/c is the maximum height it could return. However, I can do iterate all over the available glpyhs and get the maximum heightthere, I think there's an existing functions in freetype that could already do this? Anyone know of it?
=================================
=================================
=================================
출처: http://www.gpgstudy.com/forum/viewtopic.php?p=68032&sid=74c098913746973e08c341647257b493
freetype에서 글자체에 따른 간격 질문입니다
전체글 글쓴이: jabi6 » 2006-11-14 16:10
흠 우선 제가 잘못된 지식으로 인하여 용어의 해석이 잘못될수도 잇으니 양해 바랍니다..
우선 문제는 이러합니다.
굴림을 쓰면 아래처럼 글자의 간격이 제대로 나옵니다
ex>Abgd 김
굴림체를 쓰면 아래의 현상이 발생합니다
ex>A b g d 김
굴림과 굴림체의 변경은
::GetWindowsDirectory(gStrFontName, 512);
_tcscat( gStrFontName, _T("\\fonts\\gulim.ttc") );
nError = FT_New_Face( m_library, gStrFontName, 0, &m_face);
-> nError = FT_New_Face( m_library, gStrFontName, 1, &m_face);
로해서 간다니 변경이 된다느것은 알고잇습니다..
글자의 간격은 이런식으로 처리하였습니다.
GlyphSlot를 가져와서 저 만큼 이동 시켜서 찍는거죠
pen.x += slot->advance.x >> 6;
굴림은 위의 slot->advance.x값이 각 글자에 맞게 변경되어서 나오지만
굴림체는 고정값으로 나오더군요..
그러하여.. 그럼 width값을 쓰면될까?? 하는생각에
slot->metrics.width
를 썻지만 이건 글자가 너무 붙고(당연한거지만..) 빈 공백에 대한 처리가 안되더군요
그러 하여서 질문 올립니다..
굴림만 쓰면 된다구 생각해보앗지만. 이건 아니다라는 생각이 들어서요..
어떤형식의 다른 처리가 필요한지 감도 안잡혀서 질문 올립니다^^..
그럼 즐거운 시간들 되세요^^
언제나 초보인.. 프로그래머
퍄갸야무전체글: 84가입일: 2006-08-29 13:40
전체글 글쓴이: 퍄갸야무 » 2006-11-28 18:35
질문을 잘못 이해한건지는 모르겠지만,
"굴림체"는 "굴림" 의 고정폭 버젼입니다.
각 글자간 간격이 모두 같다는 뜻입니다.
마찬가지로 "바탕" "바탕체" "돋움" "돋움체" 가 존재합니다.
당연히 굴림체라면 고정값이 나와야합니다.
윈도우즈에서의 처리라면 GetTextExtentPoint32 함수를 사용하면
전체글 글쓴이: 비회원 » 2006-11-29 15:40
주어진 문자열의 너비, 높이를 정확하게 반환해줍니다.
전체글 글쓴이: 비회원 » 2006-11-29 16:22
퍄갸야무 님 말씀처럼
'굴림체'는 고정폭이고 굴림은 가변폭입니다.. '~체' 는 모두 고정폭이라고 보시면 맞습니다.
포토샵이나 다른 워드 프로그램으로 확인해보시면 바로 아실듯 합니다.
Re: freetype에서 글자체에 따른 간격 질문입니다
전체글 글쓴이: bard » 2006-11-29 17:50
jabi6 작성:흠 우선 제가 잘못된 지식으로 인하여 용어의 해석이 잘못될수도 잇으니 양해 바랍니다..
우선 문제는 이러합니다.
굴림을 쓰면 아래처럼 글자의 간격이 제대로 나옵니다
ex>Abgd 김
굴림체를 쓰면 아래의 현상이 발생합니다
ex>A b g d 김
굴림과 굴림체의 변경은
::GetWindowsDirectory(gStrFontName, 512);
_tcscat( gStrFontName, _T("\\fonts\\gulim.ttc") );
nError = FT_New_Face( m_library, gStrFontName, 0, &m_face);
-> nError = FT_New_Face( m_library, gStrFontName, 1, &m_face);
로해서 간다니 변경이 된다느것은 알고잇습니다..
글자의 간격은 이런식으로 처리하였습니다.
GlyphSlot를 가져와서 저 만큼 이동 시켜서 찍는거죠
pen.x += slot->advance.x >> 6;
굴림은 위의 slot->advance.x값이 각 글자에 맞게 변경되어서 나오지만
굴림체는 고정값으로 나오더군요..
그러하여.. 그럼 width값을 쓰면될까?? 하는생각에
slot->metrics.width
를 썻지만 이건 글자가 너무 붙고(당연한거지만..) 빈 공백에 대한 처리가 안되더군요
그러 하여서 질문 올립니다..
굴림만 쓰면 된다구 생각해보앗지만. 이건 아니다라는 생각이 들어서요..
어떤형식의 다른 처리가 필요한지 감도 안잡혀서 질문 올립니다^^..
그럼 즐거운 시간들 되세요^^
뭐 굴림'체', 바탕'체', 궁서'체' 등은 윗 분들이 말씀해주신 그대로, '고정폭'입니다.
따라서 고정된 width 가 나오는게 정상이겠지요.
질문자님의 질문은 아마 영문의 폭이 한글의 폭과 같이 나오는것을 어떻게 처리하느냐 하는 점일거 같은데..
고정폭이기 때문에 오히려 간단할 수 있습니다. 한글 및 특수기호등의 2byte 캐릭터들의 width 절반 값이
영/숫자/1byte 특수기호의 width 입니다.
코드 비교를 하셔서 ASCII 범위 안이라면(32 ~ 127), pen.x += slot->advance.x >> 6 해주시던걸 >> 8을
하시거나, / 2 를 하셔서 사용하시면 될듯하네요. ^^;
전체글 글쓴이: jabi6 » 2006-11-30 13:34
흠냐.. 이번에도 답글이 늦었네요..한.. 몇일 보앗느데..질문을 잘못해서 그런지 답글이 없어서.. 포기하고잇었거든요..
흠 제가 질문을 조금.. 잘못햇네요..
답글 다신분들 말씀처럼... ??체는 고정폭이라는것을 알고는있었습니다..
문제는.. bard님의 말씀처럼 영문도 한글과 같은 고정폭이 나온다는것이엇습니다. 저의 짧은 생각으로는
영문은 영문데로 한글은 한글대로 나올줄 알았습니다만.. 그게 아니었다는것이죠..
예를들어 글자크기 10에서 영문은 10 한글은 20 이런식을줄 알앗던것이 한글에 맞게
영문도 20으로 나온다는것이엇습니다..
매번 현재 문자가 영문인지... 다른 한글인지를 비교하여서 해결하면 되지만.. 다른 방법이 잇을까해서
질문을 올렸습니다..
내심 제가 잘못써서.. 그런거 아닌가하는 의문과 프리타입은 원래 한글기준으로 나온다.. 그래서 이걸해결하는
프리타입만의 방법이잇다.. 이런걸 알고싶엇으나.. 답해주신 다른분들의 금과옥조같은 말을 종합해보니..
그런건 없는거 같다는 결론이 나오는군요.
결론적으로 bard님이 말씀하신것처럼.. 영문일때.. 폭의 1/2로 해주어야겟습니다^^
다시한번 답글 고맙습니다^^..~~ 그럼 다들 즐거운 12월이 되세요
언제나 초보인.. 프로그래머
=================================
=================================
=================================
관련링크:
http://www.gpgstudy.com/forum/viewtopic.php?t=1413&sid=8cfc0bea7810d736c135c6ffdaffc182
http://macnalra.blogspot.com/2011/03/opengl-ftgl.html
http://ftgl.sourceforge.net/docs/html/ftgl-tutorial.html
http://www.gamecode.org/tt/entry/1501
https://github.com/jlongster/ftgles/blob/master/test/FTTextureFont-Test.cpp
=================================
=================================
=================================
'프로그래밍 관련 > 3D,2D DRAW 관련' 카테고리의 다른 글
OpenGL 오픈지엘 설치 그리고 테스트 하기 관련 (0) | 2020.09.20 |
---|---|
OpenGL 오픈지엘3D 2D처럼 이용하기 관련, How do I position a 2D camera in OpenGL? (0) | 2020.09.15 |
OpenGL 오픈지엘 투영변환 해상도 크기에 그리기,2D, glOrtho, glViewport, gluLookAt 관련 (0) | 2020.09.15 |
FreeImage Library 를 이용하여 이미지 따로 저장 관련 (0) | 2020.09.15 |
OpenGL 텍스쳐 로드 그리기 관련 (0) | 2020.09.15 |
댓글 영역