1. #include <gl/glut.h>
    2. #include <iostream>
    3. #include <ft2build.h>
    4. #include FT_FREETYPE_H
    5. using namespace std;
    6. #define PIXEL_SIZE 20 //字体的像素大小
    7. wchar_t ch = L'你';
    8. FT_Library ftLibrary;
    9. FT_Face ftFace;
    10. GLuint texture;
    11. void print(GLubyte *rgba);
    12. void ConvertMONOToRGBA(FT_Bitmap *source, GLubyte *rgba)
    13. {
    14. GLubyte *s = source->buffer;
    15. GLubyte *t = rgba;
    16. for(GLuint y = source->rows; y > 0; y--)
    17. {
    18. GLubyte *ss = s;
    19. GLubyte *tt = t;
    20. for(GLuint x = source->width >> 3; x > 0; x--)
    21. {
    22. GLuint val = *ss;
    23. for(GLuint i = 8; i > 0; i--)
    24. {
    25. tt[0] = tt[1] = tt[2] = tt[3] = (val & (1 << (i - 1))) ? 0xFF : 0x00;
    26. tt += 4;
    27. }
    28. ss += 1;
    29. }
    30. GLuint rem = source->width & 7;
    31. if(rem > 0)
    32. {
    33. GLuint val = *ss;
    34. for(GLuint x = rem; x > 0; x--)
    35. {
    36. tt[0] = tt[1] = tt[2] = tt[3] = (val & 0x80) ? 0xFF : 0x00;
    37. tt += 4;
    38. val <<= 1;
    39. }
    40. }
    41. s += source->pitch;
    42. t += source->width * 4; //pitch
    43. }
    44. }
    45. //FreeType的灰色模式:1个像素用1个字节保存。
    46. void ConvertGRAYToRGBA(FT_Bitmap *source, GLubyte *rgba) //灰度图转RGBA
    47. {
    48. for(GLuint y = 0; y < source->rows; y++)
    49. {
    50. for(GLuint x = 0; x < source->width; x++)
    51. {
    52. GLubyte *s = &source->buffer[(y * source->pitch) + x];
    53. GLubyte *t = &rgba[((y * source->pitch) + x) * 4];
    54. t[0] = t[1] = t[2] = 0xFF; //RGB为255
    55. t[3] = *s; //A通道存灰度图
    56. }
    57. }
    58. }
    59. GLubyte* get_rgba(FT_Bitmap& bitmap)
    60. {
    61. int rgbaSize = bitmap.rows * bitmap.rows * 4;
    62. GLubyte *rgba = new GLubyte[rgbaSize];
    63. switch(bitmap.pixel_mode) //像素模式
    64. {
    65. case FT_PIXEL_MODE_MONO: //黑白
    66. {
    67. // 将黑白转成RGBA
    68. ConvertMONOToRGBA(&bitmap, rgba);
    69. break;
    70. }
    71. case FT_PIXEL_MODE_GRAY: //灰度
    72. {
    73. ConvertGRAYToRGBA(&bitmap, rgba); //灰度转RGBA
    74. break;
    75. }
    76. default:
    77. {
    78. memset(rgba, 0xFF, rgbaSize);
    79. break;
    80. }
    81. }
    82. return rgba;
    83. }
    84. GLubyte* get_rgba_2(FT_Bitmap& bitmap) //自己写的,对位图的理解有不足
    85. {
    86. int rgbaSize = bitmap.rows * bitmap.rows * 4;
    87. GLubyte *rgba = new GLubyte[rgbaSize];
    88. for(GLuint y = 0; y < bitmap.rows; y++)
    89. {
    90. for(GLuint x = 0; x < bitmap.width; x++)
    91. {
    92. GLubyte *s = &bitmap.buffer[y * bitmap.pitch + x / 8];
    93. GLubyte *t = &rgba[((y * bitmap.width) + x) * 4];
    94. if((*s & (0xC0 >> (x % 8))) == 0) //非字符像素
    95. {
    96. t[0] = t[1] = t[2] = t[3] = 0x00;
    97. }
    98. else //字符像素
    99. {
    100. t[0] = t[1] = t[2] = t[3] = 0xff;
    101. }
    102. }
    103. }
    104. return rgba;
    105. }
    106. void init()
    107. {
    108. #pragma region FreeType的设置
    109. // - 初始化FreeType对象
    110. FT_Init_FreeType(&ftLibrary);
    111. FT_New_Face(ftLibrary,
    112. "C:\\WINDOWS\\Fonts\\simhei.ttf", //黑体中文字库
    113. 0,
    114. &ftFace);
    115. // - 设置
    116. FT_Set_Pixel_Sizes(ftFace, PIXEL_SIZE, 0); //像素大小
    117. // - 得到字符码的字形索引
    118. FT_UInt uiGlyphIndex = FT_Get_Char_Index(ftFace, ch);
    119. if(uiGlyphIndex <= 0)
    120. {
    121. printf("未找到该字符的索引");
    122. }
    123. FT_Load_Glyph(ftFace, uiGlyphIndex, FT_LOAD_DEFAULT);
    124. #pragma endregion
    125. #pragma region 生成位图
    126. // - 生成位图:FreeType所得是8位的灰度图
    127. if(ftFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
    128. {
    129. FT_Render_Glyph(ftFace->glyph, FT_RENDER_MODE_MONO);
    130. }
    131. // - 查看位图信息
    132. printf("行:%d;列:%d\n", ftFace->glyph->bitmap.rows, ftFace->glyph->bitmap.width);
    133. printf("\n------ 位图信息 ------\n");
    134. for(int iRow = 0; iRow < ftFace->glyph->bitmap.rows; iRow++)
    135. {
    136. for(int iCol = 0; iCol < ftFace->glyph->bitmap.width; iCol++)
    137. {
    138. printf("%d\t", ftFace->glyph->bitmap.buffer[iRow * ftFace->glyph->bitmap.pitch + iCol / 8]);
    139. }
    140. printf("\n");
    141. }
    142. #pragma endregion
    143. #pragma region 打印成字体
    144. printf("\n------ 查看字体信息 ------\n");
    145. for(int iRow = 0; iRow < ftFace->glyph->bitmap.rows; iRow++)
    146. {
    147. for(int iCol = 0; iCol < ftFace->glyph->bitmap.width; iCol++)
    148. {
    149. auto index = iRow * ftFace->glyph->bitmap.pitch + iCol / 8;
    150. auto tmp = 0xC0 >> (iCol % 8);
    151. auto value = index & tmp;
    152. if((ftFace->glyph->bitmap.buffer[iRow * ftFace->glyph->bitmap.pitch + iCol / 8] & (0xC0 >> (iCol % 8))) == 0)
    153. {
    154. printf(" ");
    155. }
    156. else
    157. {
    158. printf("1");
    159. }
    160. }
    161. printf("\n");
    162. }
    163. #pragma endregion
    164. #pragma region 生成纹理
    165. // 生成纹理
    166. glEnable(GL_TEXTURE_2D);
    167. glGenTextures(1, &texture);
    168. glBindTexture(GL_TEXTURE_2D, texture);
    169. GLubyte* rgba = get_rgba(ftFace->glyph->bitmap);
    170. //GLubyte* rgba = get_rgba_2(ftFace->glyph->bitmap);
    171. print(rgba);
    172. glTexImage2D(GL_TEXTURE_2D,
    173. 0,
    174. GL_RGBA,
    175. ftFace->glyph->bitmap.width, ftFace->glyph->bitmap.rows,
    176. 0,
    177. GL_RGBA,
    178. GL_UNSIGNED_BYTE,
    179. rgba);
    180. delete rgba;
    181. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    182. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    183. glBindTexture(GL_TEXTURE_2D, 0); //解绑
    184. #pragma endregion
    185. // 清空资源
    186. FT_Done_Face(ftFace);
    187. FT_Done_FreeType(ftLibrary);
    188. }
    189. void myDisplay(void)
    190. {
    191. glClear(GL_COLOR_BUFFER_BIT);
    192. glClearColor(0, 0, 0, 0);
    193. // 画纹理
    194. glBindTexture(GL_TEXTURE_2D, texture);
    195. glBegin(GL_QUADS);
    196. // 要注意字体纹理和OpenGL的绘制关系
    197. glTexCoord2d(0, 0); //纹理 左下角
    198. glVertex2f(-0.8f, 0.8f); //OpenGL 左上角
    199. glTexCoord2d(0, 1); //左上角
    200. glVertex2f(-0.8f, -0.8f); //左下角
    201. glTexCoord2f(1.0f, 1.0f); //右上角
    202. glVertex2f(0.8f, -0.8f); //右下角
    203. glTexCoord2d(1, 0); //右下角
    204. glVertex2f(0.8f, 0.8f); //右上角
    205. glEnd();
    206. glFlush();
    207. }
    208. int main(int argc, char *argv[])
    209. {
    210. glutInit(&argc, argv); //初始化GLUT
    211. glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //初始化显示模式
    212. glutInitWindowPosition(100, 100); //窗体位置
    213. glutInitWindowSize(500, 500); //窗体大小
    214. glutCreateWindow("OpenGL One Char"); //传入窗口名称,并开窗
    215. init();
    216. glutDisplayFunc(&myDisplay); //绘制的回调函数
    217. glutMainLoop(); //循环绘制
    218. return 0;
    219. }
    220. void print(GLubyte *rgba) //打印RGBA
    221. {
    222. printf("\n----- R -----\n");
    223. for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++)
    224. {
    225. for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++)
    226. {
    227. GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x];
    228. GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4];
    229. printf("%d\t", t[0]);
    230. }
    231. printf("\n");
    232. }
    233. printf("\n----- G -----\n");
    234. for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++)
    235. {
    236. for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++)
    237. {
    238. GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x];
    239. GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4];
    240. printf("%d\t", t[1]);
    241. }
    242. printf("\n");
    243. }
    244. printf("\n----- B -----\n");
    245. for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++)
    246. {
    247. for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++)
    248. {
    249. GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x];
    250. GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4];
    251. printf("%d\t", t[2]);
    252. }
    253. printf("\n");
    254. }
    255. printf("\n----- A -----\n");
    256. for(GLuint y = 0; y < ftFace->glyph->bitmap.rows; y++)
    257. {
    258. for(GLuint x = 0; x < ftFace->glyph->bitmap.width; x++)
    259. {
    260. GLubyte *s = &ftFace->glyph->bitmap.buffer[(y * ftFace->glyph->bitmap.pitch) + x];
    261. GLubyte *t = &rgba[((y * ftFace->glyph->bitmap.pitch) + x) * 4];
    262. printf("%d\t", t[3]);
    263. }
    264. printf("\n");
    265. }
    266. }