_imagingft.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545
  1. /*
  2. * PIL FreeType Driver
  3. *
  4. * a FreeType 2.X driver for PIL
  5. *
  6. * history:
  7. * 2001-02-17 fl Created (based on old experimental freetype 1.0 code)
  8. * 2001-04-18 fl Fixed some egcs compiler nits
  9. * 2002-11-08 fl Added unicode support; more font metrics, etc
  10. * 2003-05-20 fl Fixed compilation under 1.5.2 and newer non-unicode builds
  11. * 2003-09-27 fl Added charmap encoding support
  12. * 2004-05-15 fl Fixed compilation for FreeType 2.1.8
  13. * 2004-09-10 fl Added support for monochrome bitmaps
  14. * 2006-06-18 fl Fixed glyph bearing calculation
  15. * 2007-12-23 fl Fixed crash in family/style attribute fetch
  16. * 2008-01-02 fl Handle Unicode filenames properly
  17. *
  18. * Copyright (c) 1998-2007 by Secret Labs AB
  19. */
  20. #define PY_SSIZE_T_CLEAN
  21. #include "Python.h"
  22. #include "libImaging/Imaging.h"
  23. #include <ft2build.h>
  24. #include FT_FREETYPE_H
  25. #include FT_GLYPH_H
  26. #include FT_BITMAP_H
  27. #include FT_STROKER_H
  28. #include FT_MULTIPLE_MASTERS_H
  29. #include FT_SFNT_NAMES_H
  30. #ifdef FT_COLOR_H
  31. #include FT_COLOR_H
  32. #endif
  33. /* -------------------------------------------------------------------- */
  34. /* error table */
  35. #undef FTERRORS_H
  36. #undef __FTERRORS_H__
  37. #define FT_ERRORDEF(e, v, s) {e, s},
  38. #define FT_ERROR_START_LIST {
  39. #define FT_ERROR_END_LIST \
  40. { 0, 0 } \
  41. } \
  42. ;
  43. #ifdef HAVE_RAQM
  44. # ifdef HAVE_RAQM_SYSTEM
  45. # error #include <raqm.h>
  46. # else
  47. # error #include "thirdparty/raqm/raqm.h"
  48. # ifdef HAVE_FRIBIDI_SYSTEM
  49. # error #include <fribidi.h>
  50. # else
  51. # error #include "thirdparty/fribidi-shim/fribidi.h"
  52. # error #include <hb.h>
  53. # endif
  54. # endif
  55. #endif
  56. static int have_raqm = 0;
  57. #define LAYOUT_FALLBACK 0
  58. #define LAYOUT_RAQM 1
  59. typedef struct {
  60. int index, x_offset, x_advance, y_offset, y_advance;
  61. unsigned int cluster;
  62. } GlyphInfo;
  63. struct {
  64. int code;
  65. const char *message;
  66. } ft_errors[] =
  67. #include FT_ERRORS_H
  68. /* -------------------------------------------------------------------- */
  69. /* font objects */
  70. static FT_Library library;
  71. typedef struct {
  72. PyObject_HEAD FT_Face face;
  73. unsigned char *font_bytes;
  74. int layout_engine;
  75. } FontObject;
  76. static PyTypeObject Font_Type;
  77. /* round a 26.6 pixel coordinate to the nearest integer */
  78. #define PIXEL(x) ((((x) + 32) & -64) >> 6)
  79. static PyObject *
  80. geterror(int code) {
  81. int i;
  82. for (i = 0; ft_errors[i].message; i++) {
  83. if (ft_errors[i].code == code) {
  84. PyErr_SetString(PyExc_OSError, ft_errors[i].message);
  85. return NULL;
  86. }
  87. }
  88. PyErr_SetString(PyExc_OSError, "unknown freetype error");
  89. return NULL;
  90. }
  91. static PyObject *
  92. getfont(PyObject *self_, PyObject *args, PyObject *kw) {
  93. /* create a font object from a file name and a size (in pixels) */
  94. FontObject *self;
  95. int error = 0;
  96. char *filename = NULL;
  97. float size;
  98. FT_Size_RequestRec req;
  99. FT_Long width;
  100. Py_ssize_t index = 0;
  101. Py_ssize_t layout_engine = 0;
  102. unsigned char *encoding;
  103. unsigned char *font_bytes;
  104. Py_ssize_t font_bytes_size = 0;
  105. static char *kwlist[] = {
  106. "filename", "size", "index", "encoding", "font_bytes", "layout_engine", NULL};
  107. if (!library) {
  108. PyErr_SetString(PyExc_OSError, "failed to initialize FreeType library");
  109. return NULL;
  110. }
  111. #if PY_MAJOR_VERSION > 3 || PY_MINOR_VERSION > 11
  112. PyConfig config;
  113. PyConfig_InitPythonConfig(&config);
  114. if (!PyArg_ParseTupleAndKeywords(
  115. args,
  116. kw,
  117. "etf|nsy#n",
  118. kwlist,
  119. config.filesystem_encoding,
  120. &filename,
  121. &size,
  122. &index,
  123. &encoding,
  124. &font_bytes,
  125. &font_bytes_size,
  126. &layout_engine)) {
  127. PyConfig_Clear(&config);
  128. return NULL;
  129. }
  130. PyConfig_Clear(&config);
  131. #else
  132. if (!PyArg_ParseTupleAndKeywords(
  133. args,
  134. kw,
  135. "etf|nsy#n",
  136. kwlist,
  137. Py_FileSystemDefaultEncoding,
  138. &filename,
  139. &size,
  140. &index,
  141. &encoding,
  142. &font_bytes,
  143. &font_bytes_size,
  144. &layout_engine)) {
  145. return NULL;
  146. }
  147. #endif
  148. self = PyObject_New(FontObject, &Font_Type);
  149. if (!self) {
  150. if (filename) {
  151. PyMem_Free(filename);
  152. }
  153. return NULL;
  154. }
  155. self->face = NULL;
  156. self->layout_engine = layout_engine;
  157. if (filename && font_bytes_size <= 0) {
  158. self->font_bytes = NULL;
  159. error = FT_New_Face(library, filename, index, &self->face);
  160. } else {
  161. /* need to have allocated storage for font_bytes for the life of the object.*/
  162. /* Don't free this before FT_Done_Face */
  163. self->font_bytes = PyMem_Malloc(font_bytes_size);
  164. if (!self->font_bytes) {
  165. error = FT_Err_Out_Of_Memory;
  166. }
  167. if (!error) {
  168. memcpy(self->font_bytes, font_bytes, (size_t)font_bytes_size);
  169. error = FT_New_Memory_Face(
  170. library,
  171. (FT_Byte *)self->font_bytes,
  172. font_bytes_size,
  173. index,
  174. &self->face);
  175. }
  176. }
  177. if (!error) {
  178. width = size * 64;
  179. req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
  180. req.width = width;
  181. req.height = width;
  182. req.horiResolution = 0;
  183. req.vertResolution = 0;
  184. error = FT_Request_Size(self->face, &req);
  185. }
  186. if (!error && encoding && strlen((char *)encoding) == 4) {
  187. FT_Encoding encoding_tag =
  188. FT_MAKE_TAG(encoding[0], encoding[1], encoding[2], encoding[3]);
  189. error = FT_Select_Charmap(self->face, encoding_tag);
  190. }
  191. if (filename) {
  192. PyMem_Free(filename);
  193. }
  194. if (error) {
  195. if (self->font_bytes) {
  196. PyMem_Free(self->font_bytes);
  197. self->font_bytes = NULL;
  198. }
  199. Py_DECREF(self);
  200. return geterror(error);
  201. }
  202. return (PyObject *)self;
  203. }
  204. static int
  205. font_getchar(PyObject *string, int index, FT_ULong *char_out) {
  206. if (PyUnicode_Check(string)) {
  207. if (index >= PyUnicode_GET_LENGTH(string)) {
  208. return 0;
  209. }
  210. *char_out = PyUnicode_READ_CHAR(string, index);
  211. return 1;
  212. }
  213. return 0;
  214. }
  215. #ifdef HAVE_RAQM
  216. static size_t
  217. text_layout_raqm(
  218. PyObject *string,
  219. FontObject *self,
  220. const char *dir,
  221. PyObject *features,
  222. const char *lang,
  223. GlyphInfo **glyph_info) {
  224. size_t i = 0, count = 0, start = 0;
  225. raqm_t *rq;
  226. raqm_glyph_t *glyphs = NULL;
  227. raqm_direction_t direction;
  228. rq = raqm_create();
  229. if (rq == NULL) {
  230. PyErr_SetString(PyExc_ValueError, "raqm_create() failed.");
  231. goto failed;
  232. }
  233. if (PyUnicode_Check(string)) {
  234. Py_UCS4 *text = PyUnicode_AsUCS4Copy(string);
  235. Py_ssize_t size = PyUnicode_GET_LENGTH(string);
  236. if (!text || !size) {
  237. /* return 0 and clean up, no glyphs==no size,
  238. and raqm fails with empty strings */
  239. goto failed;
  240. }
  241. int set_text = raqm_set_text(rq, text, size);
  242. PyMem_Free(text);
  243. if (!set_text) {
  244. PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed");
  245. goto failed;
  246. }
  247. if (lang) {
  248. if (!raqm_set_language(rq, lang, start, size)) {
  249. PyErr_SetString(PyExc_ValueError, "raqm_set_language() failed");
  250. goto failed;
  251. }
  252. }
  253. } else {
  254. PyErr_SetString(PyExc_TypeError, "expected string");
  255. goto failed;
  256. }
  257. direction = RAQM_DIRECTION_DEFAULT;
  258. if (dir) {
  259. if (strcmp(dir, "rtl") == 0) {
  260. direction = RAQM_DIRECTION_RTL;
  261. } else if (strcmp(dir, "ltr") == 0) {
  262. direction = RAQM_DIRECTION_LTR;
  263. } else if (strcmp(dir, "ttb") == 0) {
  264. direction = RAQM_DIRECTION_TTB;
  265. #if !defined(RAQM_VERSION_ATLEAST)
  266. /* RAQM_VERSION_ATLEAST was added in Raqm 0.7.0 */
  267. PyErr_SetString(
  268. PyExc_ValueError,
  269. "libraqm 0.7 or greater required for 'ttb' direction");
  270. goto failed;
  271. #endif
  272. } else {
  273. PyErr_SetString(
  274. PyExc_ValueError, "direction must be either 'rtl', 'ltr' or 'ttb'");
  275. goto failed;
  276. }
  277. }
  278. if (!raqm_set_par_direction(rq, direction)) {
  279. PyErr_SetString(PyExc_ValueError, "raqm_set_par_direction() failed");
  280. goto failed;
  281. }
  282. if (features != Py_None) {
  283. int j, len;
  284. PyObject *seq = PySequence_Fast(features, "expected a sequence");
  285. if (!seq) {
  286. goto failed;
  287. }
  288. len = PySequence_Fast_GET_SIZE(seq);
  289. for (j = 0; j < len; j++) {
  290. PyObject *item = PySequence_Fast_GET_ITEM(seq, j);
  291. char *feature = NULL;
  292. Py_ssize_t size = 0;
  293. PyObject *bytes;
  294. if (!PyUnicode_Check(item)) {
  295. Py_DECREF(seq);
  296. PyErr_SetString(PyExc_TypeError, "expected a string");
  297. goto failed;
  298. }
  299. bytes = PyUnicode_AsUTF8String(item);
  300. if (bytes == NULL) {
  301. Py_DECREF(seq);
  302. goto failed;
  303. }
  304. feature = PyBytes_AS_STRING(bytes);
  305. size = PyBytes_GET_SIZE(bytes);
  306. if (!raqm_add_font_feature(rq, feature, size)) {
  307. Py_DECREF(seq);
  308. Py_DECREF(bytes);
  309. PyErr_SetString(PyExc_ValueError, "raqm_add_font_feature() failed");
  310. goto failed;
  311. }
  312. Py_DECREF(bytes);
  313. }
  314. Py_DECREF(seq);
  315. }
  316. if (!raqm_set_freetype_face(rq, self->face)) {
  317. PyErr_SetString(PyExc_RuntimeError, "raqm_set_freetype_face() failed.");
  318. goto failed;
  319. }
  320. if (!raqm_layout(rq)) {
  321. PyErr_SetString(PyExc_RuntimeError, "raqm_layout() failed.");
  322. goto failed;
  323. }
  324. glyphs = raqm_get_glyphs(rq, &count);
  325. if (glyphs == NULL) {
  326. PyErr_SetString(PyExc_ValueError, "raqm_get_glyphs() failed.");
  327. count = 0;
  328. goto failed;
  329. }
  330. (*glyph_info) = PyMem_New(GlyphInfo, count);
  331. if ((*glyph_info) == NULL) {
  332. PyErr_SetString(PyExc_MemoryError, "PyMem_New() failed");
  333. count = 0;
  334. goto failed;
  335. }
  336. for (i = 0; i < count; i++) {
  337. (*glyph_info)[i].index = glyphs[i].index;
  338. (*glyph_info)[i].x_offset = glyphs[i].x_offset;
  339. (*glyph_info)[i].x_advance = glyphs[i].x_advance;
  340. (*glyph_info)[i].y_offset = glyphs[i].y_offset;
  341. (*glyph_info)[i].y_advance = glyphs[i].y_advance;
  342. (*glyph_info)[i].cluster = glyphs[i].cluster;
  343. }
  344. failed:
  345. raqm_destroy(rq);
  346. return count;
  347. }
  348. #endif
  349. static size_t
  350. text_layout_fallback(
  351. PyObject *string,
  352. FontObject *self,
  353. const char *dir,
  354. PyObject *features,
  355. const char *lang,
  356. GlyphInfo **glyph_info,
  357. int mask,
  358. int color) {
  359. int error, load_flags;
  360. FT_ULong ch;
  361. Py_ssize_t count;
  362. FT_GlyphSlot glyph;
  363. FT_Bool kerning = FT_HAS_KERNING(self->face);
  364. FT_UInt last_index = 0;
  365. int i;
  366. if (features != Py_None || dir != NULL || lang != NULL) {
  367. PyErr_SetString(
  368. PyExc_KeyError,
  369. "setting text direction, language or font features is not supported "
  370. "without libraqm");
  371. }
  372. if (!PyUnicode_Check(string)) {
  373. PyErr_SetString(PyExc_TypeError, "expected string");
  374. return 0;
  375. }
  376. count = 0;
  377. while (font_getchar(string, count, &ch)) {
  378. count++;
  379. }
  380. if (count == 0) {
  381. return 0;
  382. }
  383. (*glyph_info) = PyMem_New(GlyphInfo, count);
  384. if ((*glyph_info) == NULL) {
  385. PyErr_SetString(PyExc_MemoryError, "PyMem_New() failed");
  386. return 0;
  387. }
  388. load_flags = FT_LOAD_DEFAULT;
  389. if (mask) {
  390. load_flags |= FT_LOAD_TARGET_MONO;
  391. }
  392. if (color) {
  393. load_flags |= FT_LOAD_COLOR;
  394. }
  395. for (i = 0; font_getchar(string, i, &ch); i++) {
  396. (*glyph_info)[i].index = FT_Get_Char_Index(self->face, ch);
  397. error = FT_Load_Glyph(self->face, (*glyph_info)[i].index, load_flags);
  398. if (error) {
  399. geterror(error);
  400. return 0;
  401. }
  402. glyph = self->face->glyph;
  403. (*glyph_info)[i].x_offset = 0;
  404. (*glyph_info)[i].y_offset = 0;
  405. if (kerning && last_index && (*glyph_info)[i].index) {
  406. FT_Vector delta;
  407. if (FT_Get_Kerning(
  408. self->face,
  409. last_index,
  410. (*glyph_info)[i].index,
  411. ft_kerning_default,
  412. &delta) == 0) {
  413. (*glyph_info)[i - 1].x_advance += PIXEL(delta.x);
  414. (*glyph_info)[i - 1].y_advance += PIXEL(delta.y);
  415. }
  416. }
  417. (*glyph_info)[i].x_advance = glyph->metrics.horiAdvance;
  418. // y_advance is only used in ttb, which is not supported by basic layout
  419. (*glyph_info)[i].y_advance = 0;
  420. last_index = (*glyph_info)[i].index;
  421. (*glyph_info)[i].cluster = ch;
  422. }
  423. return count;
  424. }
  425. static size_t
  426. text_layout(
  427. PyObject *string,
  428. FontObject *self,
  429. const char *dir,
  430. PyObject *features,
  431. const char *lang,
  432. GlyphInfo **glyph_info,
  433. int mask,
  434. int color) {
  435. size_t count;
  436. #ifdef HAVE_RAQM
  437. if (have_raqm && self->layout_engine == LAYOUT_RAQM) {
  438. count = text_layout_raqm(
  439. string, self, dir, features, lang, glyph_info);
  440. } else
  441. #endif
  442. {
  443. count = text_layout_fallback(
  444. string, self, dir, features, lang, glyph_info, mask, color);
  445. }
  446. return count;
  447. }
  448. static PyObject *
  449. font_getlength(FontObject *self, PyObject *args) {
  450. int length; /* length along primary axis, in 26.6 precision */
  451. GlyphInfo *glyph_info = NULL; /* computed text layout */
  452. size_t i, count; /* glyph_info index and length */
  453. int horizontal_dir; /* is primary axis horizontal? */
  454. int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
  455. int color = 0; /* is FT_LOAD_COLOR enabled? */
  456. const char *mode = NULL;
  457. const char *dir = NULL;
  458. const char *lang = NULL;
  459. PyObject *features = Py_None;
  460. PyObject *string;
  461. /* calculate size and bearing for a given string */
  462. if (!PyArg_ParseTuple(
  463. args, "O|zzOz:getlength", &string, &mode, &dir, &features, &lang)) {
  464. return NULL;
  465. }
  466. horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
  467. mask = mode && strcmp(mode, "1") == 0;
  468. color = mode && strcmp(mode, "RGBA") == 0;
  469. count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
  470. if (PyErr_Occurred()) {
  471. return NULL;
  472. }
  473. length = 0;
  474. for (i = 0; i < count; i++) {
  475. if (horizontal_dir) {
  476. length += glyph_info[i].x_advance;
  477. } else {
  478. length -= glyph_info[i].y_advance;
  479. }
  480. }
  481. if (glyph_info) {
  482. PyMem_Free(glyph_info);
  483. glyph_info = NULL;
  484. }
  485. return PyLong_FromLong(length);
  486. }
  487. static int
  488. bounding_box_and_anchors(FT_Face face, const char *anchor, int horizontal_dir, GlyphInfo *glyph_info, size_t count, int load_flags, int *width, int *height, int *x_offset, int *y_offset) {
  489. int position; /* pen position along primary axis, in 26.6 precision */
  490. int advanced; /* pen position along primary axis, in pixels */
  491. int px, py; /* position of current glyph, in pixels */
  492. int x_min, x_max, y_min, y_max; /* text bounding box, in pixels */
  493. int x_anchor, y_anchor; /* offset of point drawn at (0, 0), in pixels */
  494. int error;
  495. FT_Glyph glyph;
  496. FT_BBox bbox; /* glyph bounding box */
  497. size_t i; /* glyph_info index */
  498. /*
  499. * text bounds are given by:
  500. * - bounding boxes of individual glyphs
  501. * - pen line, i.e. 0 to `advanced` along primary axis
  502. * this means point (0, 0) is part of the text bounding box
  503. */
  504. position = x_min = x_max = y_min = y_max = 0;
  505. for (i = 0; i < count; i++) {
  506. if (horizontal_dir) {
  507. px = PIXEL(position + glyph_info[i].x_offset);
  508. py = PIXEL(glyph_info[i].y_offset);
  509. position += glyph_info[i].x_advance;
  510. advanced = PIXEL(position);
  511. if (advanced > x_max) {
  512. x_max = advanced;
  513. }
  514. } else {
  515. px = PIXEL(glyph_info[i].x_offset);
  516. py = PIXEL(position + glyph_info[i].y_offset);
  517. position += glyph_info[i].y_advance;
  518. advanced = PIXEL(position);
  519. if (advanced < y_min) {
  520. y_min = advanced;
  521. }
  522. }
  523. error = FT_Load_Glyph(face, glyph_info[i].index, load_flags);
  524. if (error) {
  525. geterror(error);
  526. return 1;
  527. }
  528. error = FT_Get_Glyph(face->glyph, &glyph);
  529. if (error) {
  530. geterror(error);
  531. return 1;
  532. }
  533. FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &bbox);
  534. bbox.xMax += px;
  535. if (bbox.xMax > x_max) {
  536. x_max = bbox.xMax;
  537. }
  538. bbox.xMin += px;
  539. if (bbox.xMin < x_min) {
  540. x_min = bbox.xMin;
  541. }
  542. bbox.yMax += py;
  543. if (bbox.yMax > y_max) {
  544. y_max = bbox.yMax;
  545. }
  546. bbox.yMin += py;
  547. if (bbox.yMin < y_min) {
  548. y_min = bbox.yMin;
  549. }
  550. FT_Done_Glyph(glyph);
  551. }
  552. if (anchor == NULL) {
  553. anchor = horizontal_dir ? "la" : "lt";
  554. }
  555. if (strlen(anchor) != 2) {
  556. goto bad_anchor;
  557. }
  558. x_anchor = y_anchor = 0;
  559. if (count) {
  560. if (horizontal_dir) {
  561. switch (anchor[0]) {
  562. case 'l': // left
  563. x_anchor = 0;
  564. break;
  565. case 'm': // middle (left + right) / 2
  566. x_anchor = PIXEL(position / 2);
  567. break;
  568. case 'r': // right
  569. x_anchor = PIXEL(position);
  570. break;
  571. case 's': // vertical baseline
  572. default:
  573. goto bad_anchor;
  574. }
  575. switch (anchor[1]) {
  576. case 'a': // ascender
  577. y_anchor = PIXEL(face->size->metrics.ascender);
  578. break;
  579. case 't': // top
  580. y_anchor = y_max;
  581. break;
  582. case 'm': // middle (ascender + descender) / 2
  583. y_anchor = PIXEL(
  584. (face->size->metrics.ascender +
  585. face->size->metrics.descender) /
  586. 2);
  587. break;
  588. case 's': // horizontal baseline
  589. y_anchor = 0;
  590. break;
  591. case 'b': // bottom
  592. y_anchor = y_min;
  593. break;
  594. case 'd': // descender
  595. y_anchor = PIXEL(face->size->metrics.descender);
  596. break;
  597. default:
  598. goto bad_anchor;
  599. }
  600. } else {
  601. switch (anchor[0]) {
  602. case 'l': // left
  603. x_anchor = x_min;
  604. break;
  605. case 'm': // middle (left + right) / 2
  606. x_anchor = (x_min + x_max) / 2;
  607. break;
  608. case 'r': // right
  609. x_anchor = x_max;
  610. break;
  611. case 's': // vertical baseline
  612. x_anchor = 0;
  613. break;
  614. default:
  615. goto bad_anchor;
  616. }
  617. switch (anchor[1]) {
  618. case 't': // top
  619. y_anchor = 0;
  620. break;
  621. case 'm': // middle (top + bottom) / 2
  622. y_anchor = PIXEL(position / 2);
  623. break;
  624. case 'b': // bottom
  625. y_anchor = PIXEL(position);
  626. break;
  627. case 'a': // ascender
  628. case 's': // horizontal baseline
  629. case 'd': // descender
  630. default:
  631. goto bad_anchor;
  632. }
  633. }
  634. }
  635. *width = x_max - x_min;
  636. *height = y_max - y_min;
  637. *x_offset = -x_anchor + x_min;
  638. *y_offset = -(-y_anchor + y_max);
  639. return 0;
  640. bad_anchor:
  641. PyErr_Format(PyExc_ValueError, "bad anchor specified: %s", anchor);
  642. return 1;
  643. }
  644. static PyObject *
  645. font_getsize(FontObject *self, PyObject *args) {
  646. int width, height, x_offset, y_offset;
  647. int load_flags; /* FreeType load_flags parameter */
  648. int error;
  649. GlyphInfo *glyph_info = NULL; /* computed text layout */
  650. size_t count; /* glyph_info length */
  651. int horizontal_dir; /* is primary axis horizontal? */
  652. int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
  653. int color = 0; /* is FT_LOAD_COLOR enabled? */
  654. const char *mode = NULL;
  655. const char *dir = NULL;
  656. const char *lang = NULL;
  657. const char *anchor = NULL;
  658. PyObject *features = Py_None;
  659. PyObject *string;
  660. /* calculate size and bearing for a given string */
  661. if (!PyArg_ParseTuple(
  662. args, "O|zzOzz:getsize", &string, &mode, &dir, &features, &lang, &anchor)) {
  663. return NULL;
  664. }
  665. horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
  666. mask = mode && strcmp(mode, "1") == 0;
  667. color = mode && strcmp(mode, "RGBA") == 0;
  668. count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
  669. if (PyErr_Occurred()) {
  670. return NULL;
  671. }
  672. load_flags = FT_LOAD_DEFAULT;
  673. if (mask) {
  674. load_flags |= FT_LOAD_TARGET_MONO;
  675. }
  676. if (color) {
  677. load_flags |= FT_LOAD_COLOR;
  678. }
  679. error = bounding_box_and_anchors(self->face, anchor, horizontal_dir, glyph_info, count, load_flags, &width, &height, &x_offset, &y_offset);
  680. if (glyph_info) {
  681. PyMem_Free(glyph_info);
  682. glyph_info = NULL;
  683. }
  684. if (error) {
  685. return NULL;
  686. }
  687. return Py_BuildValue(
  688. "(ii)(ii)",
  689. width,
  690. height,
  691. x_offset,
  692. y_offset);
  693. }
  694. static PyObject *
  695. font_render(FontObject *self, PyObject *args) {
  696. int x, y; /* pen position, in 26.6 precision */
  697. int px, py; /* position of current glyph, in pixels */
  698. int x_min, y_max; /* text offset in 26.6 precision */
  699. int load_flags; /* FreeType load_flags parameter */
  700. int error;
  701. FT_Glyph glyph;
  702. FT_GlyphSlot glyph_slot;
  703. FT_Bitmap bitmap;
  704. FT_Bitmap bitmap_converted; /* initialized lazily, for non-8bpp fonts */
  705. FT_BitmapGlyph bitmap_glyph;
  706. FT_Stroker stroker = NULL;
  707. int bitmap_converted_ready = 0; /* has bitmap_converted been initialized */
  708. GlyphInfo *glyph_info = NULL; /* computed text layout */
  709. size_t i, count; /* glyph_info index and length */
  710. int xx, yy; /* pixel offset of current glyph bitmap */
  711. int x0, x1; /* horizontal bounds of glyph bitmap to copy */
  712. unsigned int bitmap_y; /* glyph bitmap y index */
  713. unsigned char *source; /* glyph bitmap source buffer */
  714. unsigned char convert_scale; /* scale factor for non-8bpp bitmaps */
  715. PyObject *image;
  716. Imaging im;
  717. Py_ssize_t id;
  718. int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
  719. int color = 0; /* is FT_LOAD_COLOR enabled? */
  720. int stroke_width = 0;
  721. PY_LONG_LONG foreground_ink_long = 0;
  722. unsigned int foreground_ink;
  723. const char *mode = NULL;
  724. const char *dir = NULL;
  725. const char *lang = NULL;
  726. const char *anchor = NULL;
  727. PyObject *features = Py_None;
  728. PyObject *string;
  729. PyObject *fill;
  730. float x_start = 0;
  731. float y_start = 0;
  732. int width, height, x_offset, y_offset;
  733. int horizontal_dir; /* is primary axis horizontal? */
  734. /* render string into given buffer (the buffer *must* have
  735. the right size, or this will crash) */
  736. if (!PyArg_ParseTuple(
  737. args,
  738. "OO|zzOzizLffO:render",
  739. &string,
  740. &fill,
  741. &mode,
  742. &dir,
  743. &features,
  744. &lang,
  745. &stroke_width,
  746. &anchor,
  747. &foreground_ink_long,
  748. &x_start,
  749. &y_start)) {
  750. return NULL;
  751. }
  752. mask = mode && strcmp(mode, "1") == 0;
  753. color = mode && strcmp(mode, "RGBA") == 0;
  754. foreground_ink = foreground_ink_long;
  755. #ifdef FT_COLOR_H
  756. if (color) {
  757. FT_Color foreground_color;
  758. FT_Byte *ink = (FT_Byte *)&foreground_ink;
  759. foreground_color.red = ink[0];
  760. foreground_color.green = ink[1];
  761. foreground_color.blue = ink[2];
  762. foreground_color.alpha =
  763. (FT_Byte)255; /* ink alpha is handled in ImageDraw.text */
  764. FT_Palette_Set_Foreground_Color(self->face, foreground_color);
  765. }
  766. #endif
  767. count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
  768. if (PyErr_Occurred()) {
  769. return NULL;
  770. }
  771. load_flags = stroke_width ? FT_LOAD_NO_BITMAP : FT_LOAD_DEFAULT;
  772. if (mask) {
  773. load_flags |= FT_LOAD_TARGET_MONO;
  774. }
  775. if (color) {
  776. load_flags |= FT_LOAD_COLOR;
  777. }
  778. horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
  779. error = bounding_box_and_anchors(self->face, anchor, horizontal_dir, glyph_info, count, load_flags, &width, &height, &x_offset, &y_offset);
  780. if (error) {
  781. PyMem_Del(glyph_info);
  782. return NULL;
  783. }
  784. width += stroke_width * 2 + ceil(x_start);
  785. height += stroke_width * 2 + ceil(y_start);
  786. image = PyObject_CallFunction(fill, "ii", width, height);
  787. if (image == Py_None) {
  788. PyMem_Del(glyph_info);
  789. return Py_BuildValue("ii", 0, 0);
  790. } else if (image == NULL) {
  791. PyMem_Del(glyph_info);
  792. return NULL;
  793. }
  794. PyObject *imageId = PyObject_GetAttrString(image, "id");
  795. id = PyLong_AsSsize_t(imageId);
  796. Py_XDECREF(imageId);
  797. im = (Imaging)id;
  798. x_offset -= stroke_width;
  799. y_offset -= stroke_width;
  800. if (count == 0 || width == 0 || height == 0) {
  801. PyMem_Del(glyph_info);
  802. return Py_BuildValue("ii", x_offset, y_offset);
  803. }
  804. if (stroke_width) {
  805. error = FT_Stroker_New(library, &stroker);
  806. if (error) {
  807. geterror(error);
  808. goto glyph_error;
  809. }
  810. FT_Stroker_Set(
  811. stroker,
  812. (FT_Fixed)stroke_width * 64,
  813. FT_STROKER_LINECAP_ROUND,
  814. FT_STROKER_LINEJOIN_ROUND,
  815. 0);
  816. }
  817. /*
  818. * calculate x_min and y_max
  819. * must match font_getsize or there may be clipping!
  820. */
  821. x = y = x_min = y_max = 0;
  822. for (i = 0; i < count; i++) {
  823. px = PIXEL(x + glyph_info[i].x_offset);
  824. py = PIXEL(y + glyph_info[i].y_offset);
  825. error =
  826. FT_Load_Glyph(self->face, glyph_info[i].index, load_flags | FT_LOAD_RENDER);
  827. if (error) {
  828. geterror(error);
  829. goto glyph_error;
  830. }
  831. glyph_slot = self->face->glyph;
  832. bitmap = glyph_slot->bitmap;
  833. if (glyph_slot->bitmap_top + py > y_max) {
  834. y_max = glyph_slot->bitmap_top + py;
  835. }
  836. if (glyph_slot->bitmap_left + px < x_min) {
  837. x_min = glyph_slot->bitmap_left + px;
  838. }
  839. x += glyph_info[i].x_advance;
  840. y += glyph_info[i].y_advance;
  841. }
  842. /* set pen position to text origin */
  843. x = (-x_min + stroke_width + x_start) * 64;
  844. y = (-y_max + (-stroke_width) - y_start) * 64;
  845. if (stroker == NULL) {
  846. load_flags |= FT_LOAD_RENDER;
  847. }
  848. for (i = 0; i < count; i++) {
  849. px = PIXEL(x + glyph_info[i].x_offset);
  850. py = PIXEL(y + glyph_info[i].y_offset);
  851. error = FT_Load_Glyph(self->face, glyph_info[i].index, load_flags);
  852. if (error) {
  853. geterror(error);
  854. goto glyph_error;
  855. }
  856. glyph_slot = self->face->glyph;
  857. if (stroker != NULL) {
  858. error = FT_Get_Glyph(glyph_slot, &glyph);
  859. if (!error) {
  860. error = FT_Glyph_Stroke(&glyph, stroker, 1);
  861. }
  862. if (!error) {
  863. FT_Vector origin = {0, 0};
  864. error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, &origin, 1);
  865. }
  866. if (error) {
  867. geterror(error);
  868. goto glyph_error;
  869. }
  870. bitmap_glyph = (FT_BitmapGlyph)glyph;
  871. bitmap = bitmap_glyph->bitmap;
  872. xx = px + bitmap_glyph->left;
  873. yy = -(py + bitmap_glyph->top);
  874. } else {
  875. bitmap = glyph_slot->bitmap;
  876. xx = px + glyph_slot->bitmap_left;
  877. yy = -(py + glyph_slot->bitmap_top);
  878. }
  879. // Null buffer, is dereferenced in FT_Bitmap_Convert
  880. if (!bitmap.buffer && bitmap.rows) {
  881. PyErr_SetString(PyExc_OSError, "Bitmap missing for glyph");
  882. goto glyph_error;
  883. }
  884. /* convert non-8bpp bitmaps */
  885. switch (bitmap.pixel_mode) {
  886. case FT_PIXEL_MODE_MONO:
  887. convert_scale = 255;
  888. break;
  889. case FT_PIXEL_MODE_GRAY2:
  890. convert_scale = 255 / 3;
  891. break;
  892. case FT_PIXEL_MODE_GRAY4:
  893. convert_scale = 255 / 15;
  894. break;
  895. default:
  896. convert_scale = 1;
  897. }
  898. switch (bitmap.pixel_mode) {
  899. case FT_PIXEL_MODE_MONO:
  900. case FT_PIXEL_MODE_GRAY2:
  901. case FT_PIXEL_MODE_GRAY4:
  902. if (!bitmap_converted_ready) {
  903. FT_Bitmap_Init(&bitmap_converted);
  904. bitmap_converted_ready = 1;
  905. }
  906. error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);
  907. if (error) {
  908. geterror(error);
  909. goto glyph_error;
  910. }
  911. bitmap = bitmap_converted;
  912. /* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
  913. case FT_PIXEL_MODE_GRAY:
  914. break;
  915. case FT_PIXEL_MODE_BGRA:
  916. if (color) {
  917. break;
  918. }
  919. /* we didn't ask for color, fall through to default */
  920. default:
  921. PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
  922. goto glyph_error;
  923. }
  924. /* clip glyph bitmap width to target image bounds */
  925. x0 = 0;
  926. x1 = bitmap.width;
  927. if (xx < 0) {
  928. x0 = -xx;
  929. }
  930. if (xx + x1 > im->xsize) {
  931. x1 = im->xsize - xx;
  932. }
  933. source = (unsigned char *)bitmap.buffer;
  934. for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++, yy++) {
  935. /* clip glyph bitmap height to target image bounds */
  936. if (yy >= 0 && yy < im->ysize) {
  937. /* blend this glyph into the buffer */
  938. int k;
  939. unsigned char *target;
  940. unsigned int tmp;
  941. if (color) {
  942. /* target[RGB] returns the color, target[A] returns the mask */
  943. /* target bands get split again in ImageDraw.text */
  944. target = (unsigned char *)im->image[yy] + xx * 4;
  945. } else {
  946. target = im->image8[yy] + xx;
  947. }
  948. if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
  949. /* paste color glyph */
  950. for (k = x0; k < x1; k++) {
  951. unsigned int src_alpha = source[k * 4 + 3];
  952. /* paste only if source has data */
  953. if (src_alpha > 0) {
  954. /* unpremultiply BGRa */
  955. int src_red = CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha);
  956. int src_green = CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha);
  957. int src_blue = CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha);
  958. /* blend required if target has data */
  959. if (target[k * 4 + 3] > 0) {
  960. /* blend RGBA colors */
  961. target[k * 4 + 0] = BLEND(src_alpha, target[k * 4 + 0], src_red, tmp);
  962. target[k * 4 + 1] = BLEND(src_alpha, target[k * 4 + 1], src_green, tmp);
  963. target[k * 4 + 2] = BLEND(src_alpha, target[k * 4 + 2], src_blue, tmp);
  964. target[k * 4 + 3] = CLIP8(src_alpha + MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp));
  965. } else {
  966. /* paste unpremultiplied RGBA values */
  967. target[k * 4 + 0] = src_red;
  968. target[k * 4 + 1] = src_green;
  969. target[k * 4 + 2] = src_blue;
  970. target[k * 4 + 3] = src_alpha;
  971. }
  972. }
  973. }
  974. } else if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
  975. if (color) {
  976. unsigned char *ink = (unsigned char *)&foreground_ink;
  977. for (k = x0; k < x1; k++) {
  978. unsigned int src_alpha = source[k] * convert_scale;
  979. if (src_alpha > 0) {
  980. if (target[k * 4 + 3] > 0) {
  981. target[k * 4 + 0] = BLEND(src_alpha, target[k * 4 + 0], ink[0], tmp);
  982. target[k * 4 + 1] = BLEND(src_alpha, target[k * 4 + 1], ink[1], tmp);
  983. target[k * 4 + 2] = BLEND(src_alpha, target[k * 4 + 2], ink[2], tmp);
  984. target[k * 4 + 3] = CLIP8(src_alpha + MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp));
  985. } else {
  986. target[k * 4 + 0] = ink[0];
  987. target[k * 4 + 1] = ink[1];
  988. target[k * 4 + 2] = ink[2];
  989. target[k * 4 + 3] = src_alpha;
  990. }
  991. }
  992. }
  993. } else {
  994. for (k = x0; k < x1; k++) {
  995. unsigned int src_alpha = source[k] * convert_scale;
  996. if (src_alpha > 0) {
  997. target[k] = target[k] > 0 ? CLIP8(src_alpha + MULDIV255(target[k], (255 - src_alpha), tmp)) : src_alpha;
  998. }
  999. }
  1000. }
  1001. } else {
  1002. PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
  1003. goto glyph_error;
  1004. }
  1005. }
  1006. source += bitmap.pitch;
  1007. }
  1008. x += glyph_info[i].x_advance;
  1009. y += glyph_info[i].y_advance;
  1010. if (stroker != NULL) {
  1011. FT_Done_Glyph(glyph);
  1012. }
  1013. }
  1014. if (bitmap_converted_ready) {
  1015. FT_Bitmap_Done(library, &bitmap_converted);
  1016. }
  1017. Py_DECREF(image);
  1018. FT_Stroker_Done(stroker);
  1019. PyMem_Del(glyph_info);
  1020. return Py_BuildValue("ii", x_offset, y_offset);
  1021. glyph_error:
  1022. if (im->destroy) {
  1023. im->destroy(im);
  1024. }
  1025. if (im->image) {
  1026. free(im->image);
  1027. }
  1028. if (stroker != NULL) {
  1029. FT_Done_Glyph(glyph);
  1030. }
  1031. if (bitmap_converted_ready) {
  1032. FT_Bitmap_Done(library, &bitmap_converted);
  1033. }
  1034. FT_Stroker_Done(stroker);
  1035. PyMem_Del(glyph_info);
  1036. return NULL;
  1037. }
  1038. #if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 9) || \
  1039. (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 9 && FREETYPE_PATCH == 1)
  1040. static PyObject *
  1041. font_getvarnames(FontObject *self) {
  1042. int error;
  1043. FT_UInt i, j, num_namedstyles, name_count;
  1044. FT_MM_Var *master;
  1045. FT_SfntName name;
  1046. PyObject *list_names, *list_name;
  1047. error = FT_Get_MM_Var(self->face, &master);
  1048. if (error) {
  1049. return geterror(error);
  1050. }
  1051. num_namedstyles = master->num_namedstyles;
  1052. list_names = PyList_New(num_namedstyles);
  1053. if (list_names == NULL) {
  1054. FT_Done_MM_Var(library, master);
  1055. return NULL;
  1056. }
  1057. name_count = FT_Get_Sfnt_Name_Count(self->face);
  1058. for (i = 0; i < name_count; i++) {
  1059. error = FT_Get_Sfnt_Name(self->face, i, &name);
  1060. if (error) {
  1061. Py_DECREF(list_names);
  1062. FT_Done_MM_Var(library, master);
  1063. return geterror(error);
  1064. }
  1065. for (j = 0; j < num_namedstyles; j++) {
  1066. if (PyList_GetItem(list_names, j) != NULL) {
  1067. continue;
  1068. }
  1069. if (master->namedstyle[j].strid == name.name_id) {
  1070. list_name = Py_BuildValue("y#", name.string, name.string_len);
  1071. PyList_SetItem(list_names, j, list_name);
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. FT_Done_MM_Var(library, master);
  1077. return list_names;
  1078. }
  1079. static PyObject *
  1080. font_getvaraxes(FontObject *self) {
  1081. int error;
  1082. FT_UInt i, j, num_axis, name_count;
  1083. FT_MM_Var *master;
  1084. FT_Var_Axis axis;
  1085. FT_SfntName name;
  1086. PyObject *list_axes, *list_axis, *axis_name;
  1087. error = FT_Get_MM_Var(self->face, &master);
  1088. if (error) {
  1089. return geterror(error);
  1090. }
  1091. num_axis = master->num_axis;
  1092. name_count = FT_Get_Sfnt_Name_Count(self->face);
  1093. list_axes = PyList_New(num_axis);
  1094. if (list_axes == NULL) {
  1095. FT_Done_MM_Var(library, master);
  1096. return NULL;
  1097. }
  1098. for (i = 0; i < num_axis; i++) {
  1099. axis = master->axis[i];
  1100. list_axis = PyDict_New();
  1101. if (list_axis == NULL) {
  1102. Py_DECREF(list_axes);
  1103. FT_Done_MM_Var(library, master);
  1104. return NULL;
  1105. }
  1106. PyObject *minimum = PyLong_FromLong(axis.minimum / 65536);
  1107. PyDict_SetItemString(list_axis, "minimum", minimum ? minimum : Py_None);
  1108. Py_XDECREF(minimum);
  1109. PyObject *def = PyLong_FromLong(axis.def / 65536);
  1110. PyDict_SetItemString(list_axis, "default", def ? def : Py_None);
  1111. Py_XDECREF(def);
  1112. PyObject *maximum = PyLong_FromLong(axis.maximum / 65536);
  1113. PyDict_SetItemString(list_axis, "maximum", maximum ? maximum : Py_None);
  1114. Py_XDECREF(maximum);
  1115. for (j = 0; j < name_count; j++) {
  1116. error = FT_Get_Sfnt_Name(self->face, j, &name);
  1117. if (error) {
  1118. Py_DECREF(list_axis);
  1119. Py_DECREF(list_axes);
  1120. FT_Done_MM_Var(library, master);
  1121. return geterror(error);
  1122. }
  1123. if (name.name_id == axis.strid) {
  1124. axis_name = Py_BuildValue("y#", name.string, name.string_len);
  1125. PyDict_SetItemString(list_axis, "name", axis_name ? axis_name : Py_None);
  1126. Py_XDECREF(axis_name);
  1127. break;
  1128. }
  1129. }
  1130. PyList_SetItem(list_axes, i, list_axis);
  1131. }
  1132. FT_Done_MM_Var(library, master);
  1133. return list_axes;
  1134. }
  1135. static PyObject *
  1136. font_setvarname(FontObject *self, PyObject *args) {
  1137. int error;
  1138. int instance_index;
  1139. if (!PyArg_ParseTuple(args, "i", &instance_index)) {
  1140. return NULL;
  1141. }
  1142. error = FT_Set_Named_Instance(self->face, instance_index);
  1143. if (error) {
  1144. return geterror(error);
  1145. }
  1146. Py_INCREF(Py_None);
  1147. return Py_None;
  1148. }
  1149. static PyObject *
  1150. font_setvaraxes(FontObject *self, PyObject *args) {
  1151. int error;
  1152. PyObject *axes, *item;
  1153. Py_ssize_t i, num_coords;
  1154. FT_Fixed *coords;
  1155. FT_Fixed coord;
  1156. if (!PyArg_ParseTuple(args, "O", &axes)) {
  1157. return NULL;
  1158. }
  1159. if (!PyList_Check(axes)) {
  1160. PyErr_SetString(PyExc_TypeError, "argument must be a list");
  1161. return NULL;
  1162. }
  1163. num_coords = PyObject_Length(axes);
  1164. coords = (FT_Fixed*)malloc(num_coords * sizeof(FT_Fixed));
  1165. if (coords == NULL) {
  1166. return PyErr_NoMemory();
  1167. }
  1168. for (i = 0; i < num_coords; i++) {
  1169. item = PyList_GET_ITEM(axes, i);
  1170. if (PyFloat_Check(item)) {
  1171. coord = PyFloat_AS_DOUBLE(item);
  1172. } else if (PyLong_Check(item)) {
  1173. coord = (float)PyLong_AS_LONG(item);
  1174. } else if (PyNumber_Check(item)) {
  1175. coord = PyFloat_AsDouble(item);
  1176. } else {
  1177. free(coords);
  1178. PyErr_SetString(PyExc_TypeError, "list must contain numbers");
  1179. return NULL;
  1180. }
  1181. coords[i] = coord * 65536;
  1182. }
  1183. error = FT_Set_Var_Design_Coordinates(self->face, num_coords, coords);
  1184. free(coords);
  1185. if (error) {
  1186. return geterror(error);
  1187. }
  1188. Py_INCREF(Py_None);
  1189. return Py_None;
  1190. }
  1191. #endif
  1192. static void
  1193. font_dealloc(FontObject *self) {
  1194. if (self->face) {
  1195. FT_Done_Face(self->face);
  1196. }
  1197. if (self->font_bytes) {
  1198. PyMem_Free(self->font_bytes);
  1199. }
  1200. PyObject_Del(self);
  1201. }
  1202. static PyMethodDef font_methods[] = {
  1203. {"render", (PyCFunction)font_render, METH_VARARGS},
  1204. {"getsize", (PyCFunction)font_getsize, METH_VARARGS},
  1205. {"getlength", (PyCFunction)font_getlength, METH_VARARGS},
  1206. #if FREETYPE_MAJOR > 2 || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 9) || \
  1207. (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 9 && FREETYPE_PATCH == 1)
  1208. {"getvarnames", (PyCFunction)font_getvarnames, METH_NOARGS},
  1209. {"getvaraxes", (PyCFunction)font_getvaraxes, METH_NOARGS},
  1210. {"setvarname", (PyCFunction)font_setvarname, METH_VARARGS},
  1211. {"setvaraxes", (PyCFunction)font_setvaraxes, METH_VARARGS},
  1212. #endif
  1213. {NULL, NULL}};
  1214. static PyObject *
  1215. font_getattr_family(FontObject *self, void *closure) {
  1216. if (self->face->family_name) {
  1217. return PyUnicode_FromString(self->face->family_name);
  1218. }
  1219. Py_RETURN_NONE;
  1220. }
  1221. static PyObject *
  1222. font_getattr_style(FontObject *self, void *closure) {
  1223. if (self->face->style_name) {
  1224. return PyUnicode_FromString(self->face->style_name);
  1225. }
  1226. Py_RETURN_NONE;
  1227. }
  1228. static PyObject *
  1229. font_getattr_ascent(FontObject *self, void *closure) {
  1230. return PyLong_FromLong(PIXEL(self->face->size->metrics.ascender));
  1231. }
  1232. static PyObject *
  1233. font_getattr_descent(FontObject *self, void *closure) {
  1234. return PyLong_FromLong(-PIXEL(self->face->size->metrics.descender));
  1235. }
  1236. static PyObject *
  1237. font_getattr_height(FontObject *self, void *closure) {
  1238. return PyLong_FromLong(PIXEL(self->face->size->metrics.height));
  1239. }
  1240. static PyObject *
  1241. font_getattr_x_ppem(FontObject *self, void *closure) {
  1242. return PyLong_FromLong(self->face->size->metrics.x_ppem);
  1243. }
  1244. static PyObject *
  1245. font_getattr_y_ppem(FontObject *self, void *closure) {
  1246. return PyLong_FromLong(self->face->size->metrics.y_ppem);
  1247. }
  1248. static PyObject *
  1249. font_getattr_glyphs(FontObject *self, void *closure) {
  1250. return PyLong_FromLong(self->face->num_glyphs);
  1251. }
  1252. static struct PyGetSetDef font_getsetters[] = {
  1253. {"family", (getter)font_getattr_family},
  1254. {"style", (getter)font_getattr_style},
  1255. {"ascent", (getter)font_getattr_ascent},
  1256. {"descent", (getter)font_getattr_descent},
  1257. {"height", (getter)font_getattr_height},
  1258. {"x_ppem", (getter)font_getattr_x_ppem},
  1259. {"y_ppem", (getter)font_getattr_y_ppem},
  1260. {"glyphs", (getter)font_getattr_glyphs},
  1261. {NULL}};
  1262. static PyTypeObject Font_Type = {
  1263. PyVarObject_HEAD_INIT(NULL, 0) "Font", /*tp_name*/
  1264. sizeof(FontObject), /*tp_basicsize*/
  1265. 0, /*tp_itemsize*/
  1266. /* methods */
  1267. (destructor)font_dealloc, /*tp_dealloc*/
  1268. 0, /*tp_vectorcall_offset*/
  1269. 0, /*tp_getattr*/
  1270. 0, /*tp_setattr*/
  1271. 0, /*tp_as_async*/
  1272. 0, /*tp_repr*/
  1273. 0, /*tp_as_number*/
  1274. 0, /*tp_as_sequence*/
  1275. 0, /*tp_as_mapping*/
  1276. 0, /*tp_hash*/
  1277. 0, /*tp_call*/
  1278. 0, /*tp_str*/
  1279. 0, /*tp_getattro*/
  1280. 0, /*tp_setattro*/
  1281. 0, /*tp_as_buffer*/
  1282. Py_TPFLAGS_DEFAULT, /*tp_flags*/
  1283. 0, /*tp_doc*/
  1284. 0, /*tp_traverse*/
  1285. 0, /*tp_clear*/
  1286. 0, /*tp_richcompare*/
  1287. 0, /*tp_weaklistoffset*/
  1288. 0, /*tp_iter*/
  1289. 0, /*tp_iternext*/
  1290. font_methods, /*tp_methods*/
  1291. 0, /*tp_members*/
  1292. font_getsetters, /*tp_getset*/
  1293. };
  1294. static PyMethodDef _functions[] = {
  1295. {"getfont", (PyCFunction)getfont, METH_VARARGS | METH_KEYWORDS}, {NULL, NULL}};
  1296. static int
  1297. setup_module(PyObject *m) {
  1298. PyObject *d;
  1299. PyObject *v;
  1300. int major, minor, patch;
  1301. d = PyModule_GetDict(m);
  1302. /* Ready object type */
  1303. PyType_Ready(&Font_Type);
  1304. if (FT_Init_FreeType(&library)) {
  1305. return 0; /* leave it uninitialized */
  1306. }
  1307. FT_Library_Version(library, &major, &minor, &patch);
  1308. v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);
  1309. PyDict_SetItemString(d, "freetype2_version", v ? v : Py_None);
  1310. Py_XDECREF(v);
  1311. #ifdef HAVE_RAQM
  1312. #if defined(HAVE_RAQM_SYSTEM) || defined(HAVE_FRIBIDI_SYSTEM)
  1313. have_raqm = 1;
  1314. #else
  1315. load_fribidi();
  1316. have_raqm = !!p_fribidi;
  1317. #endif
  1318. #else
  1319. have_raqm = 0;
  1320. #endif
  1321. /* if we have Raqm, we have all three (but possibly no version info) */
  1322. v = PyBool_FromLong(have_raqm);
  1323. PyDict_SetItemString(d, "HAVE_RAQM", v);
  1324. PyDict_SetItemString(d, "HAVE_FRIBIDI", v);
  1325. PyDict_SetItemString(d, "HAVE_HARFBUZZ", v);
  1326. Py_DECREF(v);
  1327. if (have_raqm) {
  1328. v = NULL;
  1329. #ifdef RAQM_VERSION_MAJOR
  1330. v = PyUnicode_FromString(raqm_version_string());
  1331. #endif
  1332. PyDict_SetItemString(d, "raqm_version", v ? v : Py_None);
  1333. Py_XDECREF(v);
  1334. v = NULL;
  1335. #ifdef FRIBIDI_MAJOR_VERSION
  1336. {
  1337. const char *a = strchr(fribidi_version_info, ')');
  1338. const char *b = strchr(fribidi_version_info, '\n');
  1339. if (a && b && a + 2 < b) {
  1340. v = PyUnicode_FromStringAndSize(a + 2, b - (a + 2));
  1341. }
  1342. }
  1343. #endif
  1344. PyDict_SetItemString(d, "fribidi_version", v ? v : Py_None);
  1345. Py_XDECREF(v);
  1346. v = NULL;
  1347. #ifdef HB_VERSION_STRING
  1348. v = PyUnicode_FromString(hb_version_string());
  1349. #endif
  1350. PyDict_SetItemString(d, "harfbuzz_version", v ? v : Py_None);
  1351. Py_XDECREF(v);
  1352. }
  1353. return 0;
  1354. }
  1355. PyMODINIT_FUNC
  1356. PyInit__imagingft(void) {
  1357. PyObject *m;
  1358. static PyModuleDef module_def = {
  1359. PyModuleDef_HEAD_INIT,
  1360. "_imagingft", /* m_name */
  1361. NULL, /* m_doc */
  1362. -1, /* m_size */
  1363. _functions, /* m_methods */
  1364. };
  1365. m = PyModule_Create(&module_def);
  1366. if (setup_module(m) < 0) {
  1367. return NULL;
  1368. }
  1369. return m;
  1370. }