cl-pslib.lisp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. ;; This software is Copyright (c) cage
  2. ;; cage grants you the rights to distribute
  3. ;; and use this software as governed by the terms
  4. ;; of the Lisp Lesser GNU Public License
  5. ;; (http://opensource.franz.com/preamble.html),
  6. ;; known as the LLGPL
  7. (in-package #:cl-pslib)
  8. (defparameter *is-ps-boot-called* nil)
  9. (defparameter *conversion-metrics* #'millimiter->point)
  10. (defparameter *conversion-metrics-inverse* #'point->millimeter)
  11. (defmacro co-sf (val)
  12. `(coerce ,val 'single-float))
  13. (defmacro conv-mt (val)
  14. `(funcall *conversion-metrics* (co-sf ,val)))
  15. (defmacro conv-mt-inv (val)
  16. `(funcall *conversion-metrics-inverse* (co-sf ,val)))
  17. (defclass psdoc ()
  18. ((psdoc-pointer
  19. :initform nil
  20. :accessor psdoc-pointer
  21. :initarg :psdoc-pointer)
  22. (page-size
  23. :initform (make-instance 'page-size)
  24. :accessor page-size
  25. :initarg :page-size
  26. :type page-size)
  27. (filename
  28. :initform nil
  29. :accessor filename
  30. :type string)
  31. (writeproc
  32. :initform (callback write-to-string)
  33. :accessor writeproc
  34. :initarg :writeproc
  35. :type cffi:callback)))
  36. (defmethod print-object ((object psdoc) stream)
  37. (print-unreadable-object (object stream :type t :identity t)
  38. (format stream "pointer ~s~%sizes: ~a~%" (psdoc-pointer object) (page-size object))))
  39. (defmethod initialize-instance :after ((object psdoc) &key)
  40. (when (not *is-ps-boot-called*)
  41. (ps_boot))
  42. (setf (psdoc-pointer object) (ps_new)))
  43. (defgeneric begin-page (object))
  44. (defgeneric end-page (object))
  45. (defgeneric curveto (object x1 y1 x2 y2 x3 y3))
  46. (defgeneric add-bookmark (object text parent open))
  47. (defgeneric add-kerning (object font-id glyph-name1 glyph-name2 kern))
  48. (defgeneric add-launchlink (object llx lly urx ury file-name))
  49. (defgeneric add-ligature (object font-id glyph-name1 glyph-name2 glyph-name3))
  50. (defgeneric add-locallink (object llx lly urx ury page dest))
  51. (defgeneric add-note (object llx lly urx ury contents title icon open))
  52. (defgeneric add-pdflink (object llx lly urx ury filename page dest))
  53. (defgeneric add-weblink (object llx lly urx ury url))
  54. (defgeneric arc (object x y radius alpha beta))
  55. (defgeneric arcn (object x y radius alpha beta))
  56. (defgeneric begin-font (object font-name reserved a b c d e f opt-list))
  57. (defgeneric begin-glyph (object glyph-name wx llx lly urx ury))
  58. (defgeneric begin-pattern (object width height xstep ystep paint-type))
  59. (defgeneric begin-template (object width height))
  60. (defgeneric circle (object x y radius))
  61. (defgeneric clip (object))
  62. (defgeneric close-doc (object))
  63. (defgeneric close-image (object image-id))
  64. (defgeneric closepath (object))
  65. (defgeneric closepath-stroke (object))
  66. (defgeneric continue-text (object text))
  67. (defgeneric continue-text2 (object text length))
  68. (defgeneric create-gstate (object opt-list))
  69. (defgeneric delete-doc (object))
  70. (defgeneric end-font (object))
  71. (defgeneric end-glyph (object))
  72. (defgeneric end-page (object))
  73. (defgeneric end-pattern (object))
  74. (defgeneric end-template (object))
  75. (defgeneric fill-path (object))
  76. (defgeneric fill-stroke (object))
  77. (defgeneric findfont (object font-name encoding embed))
  78. (defgeneric get-parameter (object name &optional modifier))
  79. (defgeneric get-value (object name &optional modifier))
  80. (defgeneric glyph-show (object glyph-name))
  81. (defgeneric include-file (object ps-filename))
  82. (defgeneric lineto (object x y))
  83. (defgeneric makespotcolor (object name &optional reserved))
  84. (defgeneric moveto (object x y))
  85. (defgeneric open-doc (object path))
  86. (defgeneric open-image-file (object type file-name param int-param))
  87. (defgeneric open-image (object type source data length width height components bpc params))
  88. (defgeneric place-image (object image-id x y scale))
  89. (defgeneric rect (object x y width height))
  90. (defgeneric restore (object))
  91. (defgeneric rotate (object rot))
  92. (defgeneric save (object))
  93. (defgeneric scale (object scale-factor-x scale-factor-y))
  94. (defgeneric stroke (object))
  95. (defgeneric set-border-link-color (object r g b))
  96. (defgeneric set-border-link-dash (object black white))
  97. (defgeneric set-border-link-style (object style width))
  98. (defgeneric setflat (object val))
  99. (defgeneric setgray (object level))
  100. (defgeneric set-info (psdoc key val))
  101. (defgeneric set-parameter (psdoc key val))
  102. (defgeneric set-text-pos (object x y))
  103. (defgeneric set-value (psdoc key val))
  104. (defgeneric setcolor (object type color-space &optional c1 c2 c3 c4))
  105. (defgeneric setfont (object font-id size))
  106. (defgeneric setlinecap (object type))
  107. (defgeneric setlinejoin (object type))
  108. (defgeneric setlinewidth (object type))
  109. (defgeneric setmiterlimit (object type))
  110. (defgeneric setpolydash (object black-white))
  111. (defgeneric shading (object shading-type x0 y0 x1 y1 c1 c2 c3 c4 options))
  112. (defgeneric shading-pattern (object shading-id &optional option-list))
  113. (defgeneric shfill (object shading-id))
  114. (defgeneric show (object text &optional x-len))
  115. (defgeneric show-boxed (object text left top width height h-mode feature))
  116. (defgeneric show-xy (object text x y &optional x-len))
  117. (defgeneric string-geometry (object text size font-id &key end))
  118. (defgeneric font-symbol (object char))
  119. (defgeneric font-symbol-name (object idx name &optional font-id size))
  120. (defgeneric font-symbol-width (object idx &optional font-id size))
  121. (defgeneric translate (object x y))
  122. (defgeneric curve-to (object p1 p2 p3))
  123. (defgeneric bezier-to (object p1 p2 p3 p4 &key threshold))
  124. (defgeneric accomodate-text (object font text box-h box-w
  125. &optional
  126. starting-font-size
  127. horizontal-align))
  128. (defgeneric draw-text-confined-in-box (object font text left top width height
  129. &key
  130. maximum-font-size
  131. horizontal-align))
  132. (defun shutdown ()
  133. (ps_shutdown))
  134. (defun get-majorversion ()
  135. (ps_get_majorversion))
  136. (defun get-minorversion ()
  137. (ps_get_minorversion))
  138. (defmacro define-only-psdoc-method (lispname)
  139. `(progn
  140. ,@(mapcar #'(lambda (name)
  141. `(defmethod ,(alexandria:format-symbol t "~@:(~a~)" name) ((object psdoc))
  142. (with-psdoc-ptr (ptr) object
  143. (,(alexandria:format-symbol t "PS_~a" (cl-ppcre:regex-replace-all "-" (symbol-name name) "_")) ptr))))
  144. lispname)))
  145. (defmacro with-psdoc-ptr ((ptr) object &body body)
  146. `(with-accessors ((,ptr psdoc-pointer)) ,object
  147. ,@body))
  148. (define-only-psdoc-method (end-font end-glyph end-page end-pattern end-template restore save))
  149. (defmethod open-doc ((object psdoc) (file pathname))
  150. (pslib_errornum<0 (open-doc object (namestring file))))
  151. (defmethod open-doc ((object psdoc) (file string))
  152. (with-accessors ((filename filename)
  153. (ptr psdoc-pointer)) object
  154. (setf filename file)
  155. (pslib_errornum<0 (ps_open_file ptr file))))
  156. (defmethod open-doc ((object psdoc) (file (eql nil))) ; open doc in memory
  157. (with-accessors ((ptr psdoc-pointer)
  158. (writeproc writeproc)) object
  159. (pslib_errornum<0 (ps_open_mem ptr writeproc))))
  160. (defmethod close-doc ((object psdoc))
  161. (with-psdoc-ptr (ptr) object
  162. (ps_close ptr)))
  163. (defmethod begin-page ((object psdoc))
  164. (with-accessors ((ptr psdoc-pointer)
  165. (page-size page-size)) object
  166. (ps_begin_page ptr
  167. (millimiter->point (width page-size))
  168. (millimiter->point (height page-size)))))
  169. (defmethod end-page ((object psdoc))
  170. (with-psdoc-ptr (ptr) object
  171. (ps_end_page ptr)))
  172. (defmethod moveto ((object psdoc) (x number) (y number))
  173. (with-psdoc-ptr (ptr) object
  174. (ps_moveto ptr (conv-mt x) (conv-mt y))))
  175. (defmethod closepath ((object psdoc))
  176. (with-psdoc-ptr (ptr) object
  177. (ps_closepath ptr)))
  178. (defmethod lineto ((object psdoc) (x number) (y number))
  179. (with-psdoc-ptr (ptr) object
  180. (ps_lineto ptr (conv-mt x) (conv-mt y))))
  181. (defmethod rect ((object psdoc) (x number) (y number) (width number) (height number))
  182. (with-psdoc-ptr (ptr) object
  183. (ps_rect ptr (conv-mt x) (conv-mt y) (conv-mt width) (conv-mt height))))
  184. (defmethod circle ((object psdoc) (x number) (y number) (radius number))
  185. (with-psdoc-ptr (ptr) object
  186. (ps_circle ptr (conv-mt x) (conv-mt y) (conv-mt radius))))
  187. (defmethod arc ((object psdoc) (x number) (y number) (radius number) (alpha number) (beta number))
  188. (with-psdoc-ptr (ptr) object
  189. (ps_arc ptr (conv-mt x) (conv-mt y) (conv-mt radius) (co-sf alpha) (co-sf beta))))
  190. (defmethod arcn ((object psdoc) (x number) (y number) (radius number) (alpha number) (beta number))
  191. (with-psdoc-ptr (ptr) object
  192. (ps_arcn ptr (conv-mt x) (conv-mt y) (conv-mt radius) (co-sf alpha) (co-sf beta))))
  193. (defmethod curveto ((object psdoc) (x1 number) (y1 number) (x2 number) (y2 number) (x3 number) (y3 number))
  194. (with-psdoc-ptr (ptr) object
  195. (ps_curveto ptr (conv-mt x1) (conv-mt y1) (conv-mt x2) (conv-mt y2) (conv-mt x3) (conv-mt y3))))
  196. (defmethod stroke ((object psdoc))
  197. (with-psdoc-ptr (ptr) object
  198. (ps_stroke ptr)))
  199. (defmethod fill-path ((object psdoc))
  200. (with-psdoc-ptr (ptr) object
  201. (ps_fill ptr)))
  202. (defmethod fill-stroke ((object psdoc))
  203. (with-psdoc-ptr (ptr) object
  204. (ps_fill_stroke ptr)))
  205. (defmethod add-bookmark ((object psdoc) (text string) (parent integer) open)
  206. (with-psdoc-ptr (ptr) object
  207. (let ((bookmark-id (ps_add_bookmark ptr text parent (truth-lisp->c open))))
  208. (if (<= bookmark-id 0)
  209. (error 'bookmark-error
  210. :text (format nil "Can not set bookmark for ~a (parent ~a)"
  211. text parent))
  212. bookmark-id))))
  213. (defmethod add-kerning ((object psdoc) (font-id integer)
  214. (glyph-name1 string) (glyph-name2 string) (kern integer))
  215. (with-psdoc-ptr (ptr) object
  216. (ps_add_kerning ptr font-id glyph-name1 glyph-name2 kern)))
  217. (defmethod add-launchlink ((object psdoc)
  218. (llx number) (lly number)
  219. (urx number) (ury number) (file-name string))
  220. (with-psdoc-ptr (ptr) object
  221. (ps_add_launchlink ptr (conv-mt llx) (conv-mt lly)
  222. (conv-mt urx) (conv-mt ury) file-name)))
  223. (defmethod add-ligature ((object psdoc) (font-id integer)
  224. (glyph-name1 string) (glyph-name2 string) (glyph-name3 string))
  225. (with-psdoc-ptr (ptr) object
  226. (ps_add_ligature ptr font-id glyph-name1 glyph-name2 glyph-name3)))
  227. (defmethod add-locallink ((object psdoc)
  228. (llx number) (lly number)
  229. (urx number) (ury number)
  230. (page integer) (dest string))
  231. (with-psdoc-ptr (ptr) object
  232. (ps_add_locallink ptr
  233. (conv-mt llx) (conv-mt lly)
  234. (conv-mt urx) (conv-mt ury) page dest)))
  235. (defmethod add-note ((object psdoc)
  236. (llx number) (lly number)
  237. (urx number) (ury number)
  238. (contents string)
  239. (title string)
  240. (icon string) open)
  241. (with-psdoc-ptr (ptr) object
  242. (ps_add_note ptr
  243. (conv-mt llx) (conv-mt lly)
  244. (conv-mt urx) (conv-mt ury)
  245. contents title icon
  246. (truth-lisp->c open))))
  247. (defmethod add-pdflink ((object psdoc)
  248. (llx number) (lly number)
  249. (urx number) (ury number)
  250. (file-name string)
  251. (page integer) (dest string))
  252. (with-psdoc-ptr (ptr) object
  253. (ps_add_pdflink ptr
  254. (conv-mt llx) (conv-mt lly)
  255. (conv-mt urx) (conv-mt ury)
  256. file-name page dest)))
  257. (defmethod add-weblink ((object psdoc)
  258. (llx number) (lly number)
  259. (urx number) (ury number)
  260. (url string))
  261. (with-psdoc-ptr (ptr) object
  262. (ps_add_weblink ptr
  263. (conv-mt llx) (conv-mt lly)
  264. (conv-mt urx) (conv-mt ury)
  265. url)))
  266. (defmethod begin-font ((object psdoc)
  267. (font-name string)
  268. (reserved integer)
  269. (a number)
  270. (b number)
  271. (c number)
  272. (d number)
  273. (e number)
  274. (f number) (opt-list string))
  275. (with-psdoc-ptr (ptr) object
  276. (ps_begin_font ptr font-name reserved
  277. (co-sf a)
  278. (co-sf b) (co-sf c)
  279. (co-sf d) (co-sf e) (co-sf f) opt-list)))
  280. (defmethod begin-glyph ((object psdoc)
  281. (glyph-name string)
  282. (wx number)
  283. (llx number)
  284. (lly number)
  285. (urx number)
  286. (ury number))
  287. (with-psdoc-ptr (ptr) object
  288. (ps_begin_glyph ptr glyph-name (conv-mt wx)
  289. (conv-mt llx)
  290. (conv-mt lly)
  291. (conv-mt urx)
  292. (conv-mt ury))))
  293. (defmethod begin-pattern ((object psdoc)
  294. (width number)
  295. (height number)
  296. (xstep number)
  297. (ystep number)
  298. (paint-type integer))
  299. (with-psdoc-ptr (ptr) object
  300. (pslib_errornum<0 (ps_begin_pattern ptr
  301. (conv-mt width)
  302. (conv-mt height)
  303. (conv-mt xstep)
  304. (conv-mt ystep)
  305. paint-type))))
  306. (defmethod begin-template ((object psdoc) (width number) (height number))
  307. (with-psdoc-ptr (ptr) object
  308. (pslib_errornum<0
  309. (ps_begin_template ptr (conv-mt width) (conv-mt height)))))
  310. (defmethod clip ((object psdoc))
  311. (with-psdoc-ptr (ptr) object
  312. (pslib_errornum<0
  313. (ps_clip ptr))))
  314. (defmethod close-image ((object psdoc) (image-id integer))
  315. (with-psdoc-ptr (ptr) object
  316. (ps_close_image ptr image-id)))
  317. (defmethod closepath ((object psdoc))
  318. (with-psdoc-ptr (ptr) object
  319. (ps_closepath ptr)))
  320. (defmethod closepath-stroke ((object psdoc))
  321. (with-psdoc-ptr (ptr) object
  322. (ps_closepath_stroke ptr)))
  323. (defmethod continue-text ((object psdoc) (text string))
  324. (with-psdoc-ptr (ptr) object
  325. (ps_continue_text ptr text)))
  326. (defmethod continue-text2 ((object psdoc) (text string) (length integer))
  327. (with-psdoc-ptr (ptr) object
  328. (ps_continue_text2 ptr text length)))
  329. (defmethod create-gstate ((object psdoc) (opt-list string))
  330. (with-psdoc-ptr (ptr) object
  331. (ps_create_gstate ptr opt-list)))
  332. (defmethod delete-doc ((object psdoc))
  333. (with-psdoc-ptr (ptr) object
  334. (ps_delete ptr)))
  335. (defmethod findfont ((object psdoc) (font-name string) (encoding string) embed)
  336. (with-psdoc-ptr (ptr) object
  337. (ps_findfont ptr font-name encoding (truth-lisp->c embed))))
  338. (defmethod shading ((object psdoc) (shading-type string) (x0 number) (y0 number) (x1 number) (y1 number) (c1 number) (c2 number) (c3 number) (c4 number) (options string))
  339. (with-psdoc-ptr (ptr) object
  340. (ps_shading ptr (conv-mt x0) shading-type (conv-mt y0) (conv-mt x1) (conv-mt y1) (co-sf c1) (co-sf c2) (co-sf c3) (co-sf c4) options)))
  341. (defmethod glyph-show ((object psdoc) (glyph-name string))
  342. (with-psdoc-ptr (ptr) object
  343. (ps_glyph_show ptr glyph-name)))
  344. (defmethod include-file ((object psdoc) (ps-filename string))
  345. (with-psdoc-ptr (ptr) object
  346. (pslib_errornum<0 (ps_include_file ptr ps-filename))))
  347. (defmethod get-parameter ((object psdoc) (name string) &optional (modifier 0.0))
  348. (with-psdoc-ptr (ptr) object
  349. (ps_get_parameter ptr name (float modifier))))
  350. (defmethod get-value ((object psdoc) (name string) &optional (modifier 0.0))
  351. (with-psdoc-ptr (ptr) object
  352. (ps_get_value ptr name (float modifier))))
  353. (defmethod makespotcolor ((object psdoc) (name string) &optional (reserved 0.0))
  354. (with-psdoc-ptr (ptr) object
  355. (let ((color-id (ps_makespotcolor ptr name reserved)))
  356. (if (<= color-id 0)
  357. (error 'spotcolor-error
  358. :text (format nil "Can not set spot color with name ~a" name))
  359. color-id))))
  360. (defmethod open-image-file ((object psdoc) (type string) (file-name string) (param string) (int-param integer))
  361. (with-psdoc-ptr (ptr) object
  362. (let ((image-id (ps_open_image_file ptr type file-name param int-param)))
  363. (if (<= image-id 0)
  364. (error 'image-load-error
  365. :text (format nil "File ~a is not a valid image file of type ~a" file-name type))
  366. (values image-id
  367. (conv-mt-inv (get-value object +value-key-imagewidth+ image-id))
  368. (conv-mt-inv (get-value object +value-key-imageheight+ image-id)))))))
  369. (defmethod open-image ((object psdoc) (type string)
  370. (source string) (data list)
  371. (length integer) (width integer)
  372. (height integer)
  373. (components integer)
  374. (bpc integer)
  375. (params string))
  376. (with-psdoc-ptr (ptr) object
  377. (with-list->foreign-array (data-arr :unsigned-char #'identity) data
  378. (let ((image-id (ps_open_image ptr type source data-arr length
  379. width height components bpc params)))
  380. (if (<= image-id 0)
  381. (error 'image-load-error
  382. :text (format nil "Load of image from memory failed"))
  383. image-id)))))
  384. (defmethod open-image ((object psdoc) (type string)
  385. (source string) (data vector)
  386. (length integer) (width integer)
  387. (height integer)
  388. (components integer)
  389. (bpc integer)
  390. (params string))
  391. (with-psdoc-ptr (ptr) object
  392. (with-vector->foreign-array (data-arr :unsigned-char #'identity) data
  393. (let ((image-id (ps_open_image ptr type source data-arr length
  394. width height components bpc params)))
  395. (if (<= image-id 0)
  396. (error 'image-load-error
  397. :text (format nil "Load of image from memory failed"))
  398. image-id)))))
  399. (defmethod place-image ((object psdoc) (image-id integer) (x number) (y number) (scale number))
  400. (with-psdoc-ptr (ptr) object
  401. (ps_place_image ptr image-id (conv-mt x) (conv-mt y) (co-sf scale))))
  402. (defmethod rotate ((object psdoc) (rot number))
  403. (with-psdoc-ptr (ptr) object
  404. (ps_rotate ptr (co-sf rot))))
  405. (defmethod scale ((object psdoc) (scale-factor-x number) (scale-factor-y number))
  406. (with-psdoc-ptr (ptr) object
  407. (ps_scale ptr (co-sf scale-factor-x) (co-sf scale-factor-y))))
  408. (defmethod set-border-link-color ((object psdoc) (r number) (g number) (b number))
  409. (with-psdoc-ptr (ptr) object
  410. (ps_set_border_color ptr (co-sf r) (co-sf g) (co-sf b))))
  411. (defmethod set-border-link-dash ((object psdoc) (black number) (white number))
  412. (with-psdoc-ptr (ptr) object
  413. (ps_set_border_dash ptr (conv-mt black) (conv-mt white))))
  414. (defmethod set-border-link-style ((object psdoc) (style string) (width number))
  415. (with-psdoc-ptr (ptr) object
  416. (ps_set_border_style ptr style (conv-mt width))))
  417. (defmethod set-info ((object psdoc) (key string) (val string))
  418. (with-psdoc-ptr (ptr) object
  419. (ps_set_info ptr key val)))
  420. (defmethod set-parameter ((object psdoc) (key string) (val string))
  421. (with-psdoc-ptr (ptr) object
  422. (ps_set_parameter ptr key val)))
  423. (defmethod set-text-pos ((object psdoc) (x number) (y number))
  424. (with-psdoc-ptr (ptr) object
  425. (ps_set_text_pos ptr (conv-mt x) (conv-mt y))))
  426. (defmethod set-value ((object psdoc) (key string) (val number))
  427. (with-psdoc-ptr (ptr) object
  428. (ps_set_value ptr key (co-sf val))))
  429. (defmethod setcolor ((object psdoc) (type string) (color-space string)
  430. &optional (c1 0.0) (c2 0.0) (c3 0.0) (c4 0.0))
  431. (with-psdoc-ptr (ptr) object
  432. (ps_setcolor ptr type color-space (co-sf c1) (co-sf c2) (co-sf c3) (co-sf c4))))
  433. (defmethod setcolor ((object psdoc) (type string) (color cl-colors:rgb)
  434. &optional c1 c2 c3 c4)
  435. (declare (ignore c1 c2 c3 c4))
  436. (with-psdoc-ptr (ptr) object
  437. (ps_setcolor ptr type +color-space-rgb+
  438. (co-sf (cl-colors:rgb-red color))
  439. (co-sf (cl-colors:rgb-green color))
  440. (co-sf (cl-colors:rgb-blue color))
  441. 1.0)))
  442. (defmethod setflat ((object psdoc) (val number))
  443. (assert (<= 0.2 val 100)) ;; according to sources
  444. (with-psdoc-ptr (ptr) object
  445. (ps_setflat ptr (co-sf val))))
  446. (defmethod setfont ((object psdoc) (font-id integer) (size number))
  447. (assert (> size 0))
  448. (with-psdoc-ptr (ptr) object
  449. (ps_setfont ptr font-id (conv-mt size))))
  450. (defmethod setgray ((object psdoc) (level number))
  451. (assert (<= 0 level 1)) ;; according to manual
  452. (with-psdoc-ptr (ptr) object
  453. (ps_setgray ptr (co-sf level))))
  454. (defmethod setlinecap ((object psdoc) (type integer))
  455. (with-psdoc-ptr (ptr) object
  456. (ps_setlinecap ptr type)))
  457. (defmethod setlinejoin ((object psdoc) (type integer))
  458. (with-psdoc-ptr (ptr) object
  459. (ps_setlinejoin ptr type)))
  460. (defmethod setlinewidth ((object psdoc) (width number))
  461. (with-psdoc-ptr (ptr) object
  462. (ps_setlinewidth ptr (conv-mt width))))
  463. (defmethod setmiterlimit ((object psdoc) (value number))
  464. (with-psdoc-ptr (ptr) object
  465. (ps_setmiterlimit ptr (conv-mt value))))
  466. (defmethod setpolydash ((object psdoc) (black-white list))
  467. (with-psdoc-ptr (ptr) object
  468. (with-list->foreign-array (arr :float #'(lambda(i) (conv-mt i))) black-white
  469. (ps_setpolydash ptr arr (length black-white)))))
  470. (defmethod shading-pattern ((object psdoc) (shading-id integer) &optional (option-list ""))
  471. (with-psdoc-ptr (ptr) object
  472. (let ((sh-pattern-id (ps_shading_pattern ptr shading-id option-list)))
  473. (if (<= sh-pattern-id 0)
  474. (error 'shading-pattern-error
  475. :text (format nil "Shading pattern from shading-id: ~a failed." shading-id))
  476. sh-pattern-id))))
  477. (defmethod shfill ((object psdoc) (shading-id integer))
  478. (with-psdoc-ptr (ptr) object
  479. (ps_shfill ptr shading-id)))
  480. (defmethod show ((object psdoc) (text string) &optional (x-len 0))
  481. (with-psdoc-ptr (ptr) object
  482. (if (> 0 x-len)
  483. (ps_show2 ptr text (round (conv-mt x-len)))
  484. (ps_show ptr text))))
  485. (defmethod show-boxed ((object psdoc) (text string)
  486. (left number) (top number)
  487. (width number) (height number)
  488. (h-mode string) (feature string))
  489. (with-psdoc-ptr (ptr) object
  490. (values
  491. (ps_show_boxed ptr text (conv-mt left) (conv-mt top) (conv-mt width)
  492. (conv-mt height) h-mode feature)
  493. (conv-mt-inv (get-value object +value-key-boxheight+)))))
  494. (defmethod show-xy ((object psdoc) (text string) (x number) (y number) &optional (x-len 0))
  495. (with-psdoc-ptr (ptr) object
  496. (if (> 0 x-len)
  497. (ps_show_xy2 ptr text (round (conv-mt x-len)) (conv-mt x) (conv-mt y))
  498. (ps_show_xy ptr text (conv-mt x) (conv-mt y)))))
  499. (defclass text-metrics ()
  500. ((width
  501. :initarg :width
  502. :accessor width)
  503. (height
  504. :initarg :height
  505. :accessor height)
  506. (ascent
  507. :initarg :ascent
  508. :accessor ascent)
  509. (descent
  510. :initarg :descent
  511. :accessor descent)))
  512. (defmethod print-object ((object text-metrics) stream)
  513. (print-unreadable-object (object stream :type t :identity t)
  514. (format stream "metrics w: ~a h: ~a ascent: ~s descent: ~a"
  515. (width object) (height object) (ascent object) (descent object))))
  516. (defmethod string-geometry ((object psdoc) (text string) (size number) (font-id integer)
  517. &key (end (length text)))
  518. (with-psdoc-ptr (ptr) object
  519. (with-list->foreign-array (data-arr :float #'identity)
  520. (map-into (make-list 3) #'(lambda() (float 0)))
  521. (ps_string_geometry ptr text end font-id size data-arr)
  522. (let ((metrics-list '()))
  523. (setf metrics-list
  524. (dotimes (i 3 (reverse metrics-list))
  525. (push (point->millimeter (cffi:mem-aref data-arr :float i))
  526. metrics-list)))
  527. (make-instance 'text-metrics
  528. :width (first metrics-list)
  529. :height size
  530. :ascent (third metrics-list)
  531. :descent (second metrics-list))))))
  532. (defmethod font-symbol ((object psdoc) (char integer))
  533. (with-psdoc-ptr (ptr) object
  534. (ps_symbol ptr char)))
  535. (defmethod font-symbol-name ((object psdoc) (idx integer) (name string)
  536. &optional (font-id 0) (size (length name)))
  537. (with-psdoc-ptr (ptr) object
  538. (ps_symbol_name ptr idx font-id name size)))
  539. (defmethod font-symbol-width ((object psdoc) (idx integer)
  540. &optional (font-id 0) (size 0.0))
  541. (with-psdoc-ptr (ptr) object
  542. (ps_symbol_width ptr idx font-id size)))
  543. (defmethod translate ((object psdoc) (x number) (y number))
  544. (with-psdoc-ptr (ptr) object
  545. (ps_translate ptr (conv-mt x) (conv-mt y))))
  546. (defmethod curve-to ((object psdoc) p1 p2 p3)
  547. (curveto object
  548. (conv-mt (first p1)) (conv-mt (second p1))
  549. (conv-mt (first p2)) (conv-mt (second p2))
  550. (conv-mt (first p3)) (conv-mt (second p3))))
  551. (defmethod bezier-to (object p1 p2 p3 p4 &key (threshold 0.1))
  552. (let* ((ct-pts (mapcar #'(lambda (p) (list (conv-mt (first p)) (conv-mt (second p))))
  553. (list p1 p2 p3 p4)))
  554. (pairs (recursive-bezier ct-pts :threshold threshold)))
  555. (format t "~a~%" pairs)
  556. (mapcar #'(lambda (p) (lineto object (first p) (second p))) pairs)))
  557. (defmethod accomodate-text ((object psdoc) font text box-h box-w
  558. &optional
  559. (starting-font-size 20.0)
  560. (horizontal-align +boxed-text-h-mode-center+))
  561. (ps:setfont object font starting-font-size)
  562. (let ((measures (multiple-value-list
  563. (ps:show-boxed object
  564. text
  565. 0
  566. 0
  567. box-w
  568. 0
  569. horizontal-align
  570. +boxed-text-feature-blind+))))
  571. (if (<= (second measures) ;; height
  572. box-h)
  573. (values (second measures) starting-font-size)
  574. (accomodate-text object font text box-h box-w (- starting-font-size .1)))))
  575. (defmethod draw-text-confined-in-box ((object psdoc) (font string) (text string)
  576. (left number) (top number)
  577. (width number) (height number)
  578. &key
  579. (maximum-font-size 20.0)
  580. (vertical-align :center)
  581. (horizontal-align +boxed-text-h-mode-center+))
  582. (let* ((font-handle (ps:findfont object font "" t)))
  583. (draw-text-confined-in-box object
  584. font-handle
  585. text
  586. left
  587. top
  588. width
  589. height
  590. :maximum-font-size maximum-font-size
  591. :vertical-align vertical-align
  592. :horizontal-align horizontal-align)))
  593. (defmethod draw-text-confined-in-box ((object psdoc) font (text string)
  594. (left number) (top number)
  595. (width number) (height number)
  596. &key
  597. (maximum-font-size 20.0)
  598. (vertical-align :center)
  599. (horizontal-align +boxed-text-h-mode-center+))
  600. (ps:save object)
  601. (ps:set-parameter object ps:+value-key-linebreak+ ps:+true+)
  602. (multiple-value-bind (text-h actual-font-size)
  603. (accomodate-text object font text height width maximum-font-size
  604. horizontal-align)
  605. (ps:setfont object font actual-font-size)
  606. (let ((y (ecase vertical-align
  607. (:center
  608. (+ top (- (/ height 2) (/ text-h 2))))
  609. (:bottom
  610. top)
  611. (:top
  612. (- (+ top height) text-h)))))
  613. (ps:show-boxed object
  614. text
  615. left
  616. y
  617. width
  618. text-h
  619. horizontal-align
  620. ""))
  621. (ps:restore object)))