classes.py 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048
  1. '''
  2. Extra information to customise how we wrap MuPDF structs into C++ classes.
  3. '''
  4. import textwrap
  5. import jlib
  6. from . import rename
  7. from . import state
  8. from . import util
  9. class ExtraMethod:
  10. '''
  11. Defines a prototype and implementation of a custom method in a generated
  12. class.
  13. '''
  14. def __init__( self, return_, name_args, body, comment, overload=None):
  15. '''
  16. return_:
  17. Return type as a string.
  18. name_args:
  19. A string describing name and args of the method:
  20. <method-name>(<args>)
  21. body:
  22. Implementation code including the enclosing '{...}'.
  23. comment:
  24. Optional comment; should include /* and */ or //.
  25. overload:
  26. If true, we allow auto-generation of methods with same name.
  27. '''
  28. assert name_args
  29. self.return_ = return_
  30. self.name_args = name_args
  31. self.body = body
  32. self.comment = comment
  33. self.overload = overload
  34. assert '\t' not in body
  35. def __str__(self):
  36. return f'{self.name_args} => {self.return_}'
  37. class ExtraConstructor:
  38. '''
  39. Defines a prototype and implementation of a custom constructor in a
  40. generated class.
  41. '''
  42. def __init__( self, name_args, body, comment):
  43. '''
  44. name_args:
  45. A string of the form: (<args>)
  46. body:
  47. Implementation code including the enclosing '{...}'.
  48. comment:
  49. Optional comment; should include /* and */ or //.
  50. '''
  51. self.return_ = ''
  52. self.name_args = name_args
  53. self.body = body
  54. self.comment = comment
  55. assert '\t' not in body
  56. class ClassExtra:
  57. '''
  58. Extra methods/features when wrapping a particular MuPDF struct into a C++
  59. class.
  60. '''
  61. def __init__( self,
  62. accessors=None,
  63. class_bottom='',
  64. class_post='',
  65. class_pre='',
  66. class_top='',
  67. constructor_default=True,
  68. constructor_excludes=None,
  69. constructor_prefixes=None,
  70. constructor_raw=True,
  71. constructors_extra=None,
  72. constructors_wrappers=None,
  73. copyable=True,
  74. extra_cpp='',
  75. iterator_next=None,
  76. methods_extra=None,
  77. method_wrappers=None,
  78. method_wrappers_static=None,
  79. opaque=False,
  80. pod=False,
  81. virtual_fnptrs=False,
  82. ):
  83. '''
  84. accessors:
  85. If true, we generate accessors methods for all items in the
  86. underlying struct.
  87. Defaults to True if pod is True, else False.
  88. class_bottom:
  89. Extra text at end of class definition, e.g. for member variables.
  90. class_post:
  91. Extra text after class definition, e.g. complete definition of
  92. iterator class.
  93. class_pre:
  94. Extra text before class definition, e.g. forward declaration of
  95. iterator class.
  96. class_top:
  97. Extra text at start of class definition, e.g. for enums.
  98. constructor_default:
  99. If None we set to true if `pod` is true, otherwise false. If
  100. true, we create a default constructor. If `pod` is true this
  101. constructor will default-initialise each member, otherwise it will
  102. set `m_internal` to null.
  103. constructor_excludes:
  104. Lists of constructor functions to ignore.
  105. constructor_prefixes:
  106. Extra fz_*() function name prefixes that can be used by class
  107. constructors_wrappers. We find all functions whose name starts with one of
  108. the specified prefixes and which returns a pointer to the relevant
  109. fz struct.
  110. For each function we find, we make a constructor that takes the
  111. required arguments and set m_internal to what this function
  112. returns.
  113. If there is a '-' item, we omit the default 'fz_new_<type>' prefix.
  114. constructor_raw:
  115. If true, create a constructor that takes a pointer to an instance
  116. of the wrapped fz_ struct. If 'default', this constructor arg
  117. defaults to NULL. If 'declaration_only' we declare the constructor
  118. but do not write out the function definition - typically this will
  119. be instead specified as custom code in <extra_cpp>.
  120. constructors_extra:
  121. List of ExtraConstructor's, allowing arbitrary constructors_wrappers to be
  122. specified.
  123. constructors_wrappers:
  124. List of fns to use as constructors_wrappers.
  125. copyable:
  126. If 'default' we allow default copy constructor to be created by C++
  127. compiler. This is useful for plain structs that are not referenced
  128. counted but can still be copied, but which we don't want to specify
  129. pod=True.
  130. Otherwise if true, generated wrapper class must be copyable. If
  131. pod is false, we generate a copy constructor by looking for a
  132. fz_keep_*() function; it's an error if we can't find this function
  133. [2024-01-24 fixme: actually we don't appear to raise an
  134. error in this case, instead we make class non-copyable.
  135. e.g. FzCompressedBuffer.].
  136. Otherwise if false we create a private copy constructor.
  137. [todo: need to check docs for interaction of pod/copyable.]
  138. extra_cpp:
  139. Extra text for .cpp file, e.g. implementation of iterator class
  140. methods.
  141. iterator_next:
  142. Support for iterating forwards over linked list.
  143. Should be (first, last).
  144. first:
  145. Name of element within the wrapped class that points to the
  146. first item in the linked list. We assume that this element will
  147. have 'next' pointers that terminate in NULL.
  148. If <first> is '', the container is itself the first element in
  149. the linked list.
  150. last:
  151. Currently unused, but could be used for reverse iteration in
  152. the future.
  153. We generate begin() and end() methods, plus a separate iterator
  154. class, to allow iteration over the linked list starting at
  155. <structname>::<first> and iterating to ->next until we reach NULL.
  156. methods_extra:
  157. List of ExtraMethod's, allowing arbitrary methods to be specified.
  158. method_wrappers:
  159. Extra fz_*() function names that should be wrapped in class
  160. methods.
  161. E.g. 'fz_foo_bar' is converted to a method called foo_bar()
  162. that takes same parameters as fz_foo_bar() except context and
  163. any pointer to struct and fz_context*. The implementation calls
  164. fz_foo_bar(), converting exceptions etc.
  165. The first arg that takes underlying fz_*_s type is omitted and
  166. implementation passes <this>.
  167. method_wrappers_static:
  168. Like <method_wrappers>, but generates static methods, where no args
  169. are replaced by <this>.
  170. opaque:
  171. If true, we generate a wrapper even if there's no definition
  172. available for the struct, i.e. it's only available as a forward
  173. declaration.
  174. pod:
  175. If 'inline', there is no m_internal; instead, each member of the
  176. underlying class is placed in the wrapper class and special method
  177. `internal()` returns a fake pointer to underlying class.
  178. If 'none', there is no m_internal member at all. Typically
  179. <extra_cpp> could be used to add in custom members.
  180. If True, underlying class is POD and m_internal is an instance of
  181. the underlying class instead of a pointer to it.
  182. virtual_fnptrs:
  183. If true, should be a dict with these keys:
  184. alloc:
  185. A string containing C++ code to be embedded in the
  186. virtual_fnptrs wrapper class's constructor.
  187. If the wrapper class is a POD, the MuPDF struct is already
  188. available as part of the wrapper class instance (as
  189. m_internal, or `internal()` if inline). Otherwise this
  190. code should set `m_internal` to point to a newly allocated
  191. instance of the MuPDF struct.
  192. Should typically set up the MuPDF struct so that `self_()`
  193. can return the original C++ wrapper class instance.
  194. comment:
  195. Extra comment for the wrapper class.
  196. free:
  197. Optional code for freeing the virtual_fnptrs wrapper
  198. class. If specified this causes creation of a destructor
  199. function.
  200. This is only needed for non-ref-counted classes that are
  201. not marked as POD. In this case the wrapper class has a
  202. pointer `m_internal` member that will not be automatically
  203. freed by the destructor, and `alloc` will usually have set
  204. it to a newly allocated struct.
  205. self_:
  206. A callable that returns a string containing C++ code for
  207. embedding in each low-level callback. It should returns a
  208. pointer to the original C++ virtual_fnptrs wrapper class.
  209. If `self_n` is None, this callable takes no args. Otherwise
  210. it takes the name of the `self_n`'th arg.
  211. self_n:
  212. Index of arg in each low-level callback, for the arg that
  213. should be passed to `self_`. We use the same index for all
  214. low-level callbacks. If not specified, default is 1 (we
  215. generally expect args to be (fz_context* ctx, void*, ...).
  216. If None, `self_` is called with no arg; this is for if we
  217. use a different mechanism such as a global variable.
  218. We generate a virtual_fnptrs wrapper class, derived from the main
  219. wrapper class, where the main wrapper class's function pointers end
  220. up calling the virtual_fnptrs wrapper class's virtual methods. We
  221. then use SWIG's 'Director' support to allow these virtual methods
  222. to be overridden in Python/C#. Thus one can make MuPDF function
  223. pointers call Python/C# code.
  224. '''
  225. if accessors is None and pod is True:
  226. accessors = True
  227. if constructor_default is None:
  228. constructor_default = pod
  229. self.accessors = accessors
  230. self.class_bottom = class_bottom
  231. self.class_post = class_post
  232. self.class_pre = class_pre
  233. self.class_top = class_top
  234. self.constructor_default = constructor_default
  235. self.constructor_excludes = constructor_excludes or []
  236. self.constructor_prefixes = constructor_prefixes or []
  237. self.constructor_raw = constructor_raw
  238. self.constructors_extra = constructors_extra or []
  239. self.constructors_wrappers = constructors_wrappers or []
  240. self.copyable = copyable
  241. self.extra_cpp = extra_cpp
  242. self.iterator_next = iterator_next
  243. self.methods_extra = methods_extra or []
  244. self.method_wrappers = method_wrappers or []
  245. self.method_wrappers_static = method_wrappers_static or []
  246. self.opaque = opaque
  247. self.pod = pod
  248. self.virtual_fnptrs = virtual_fnptrs
  249. assert self.pod in (False, True, 'inline', 'none'), f'{self.pod}'
  250. def assert_list_of( items, type_):
  251. assert isinstance( items, list)
  252. for item in items:
  253. assert isinstance( item, type_)
  254. assert_list_of( self.constructor_prefixes, str)
  255. assert_list_of( self.method_wrappers, str)
  256. assert_list_of( self.method_wrappers_static, str)
  257. assert_list_of( self.methods_extra, ExtraMethod)
  258. assert_list_of( self.constructors_extra, ExtraConstructor)
  259. if virtual_fnptrs:
  260. assert isinstance(virtual_fnptrs, dict), f'virtual_fnptrs={virtual_fnptrs!r}'
  261. def __str__( self):
  262. ret = ''
  263. ret += f' accessors={self.accessors}'
  264. ret += f' class_bottom={self.class_bottom}'
  265. ret += f' class_post={self.class_post}'
  266. ret += f' class_pre={self.class_pre}'
  267. ret += f' class_top={self.class_top}'
  268. ret += f' constructor_default={self.constructor_default}'
  269. ret += f' constructor_excludes={self.constructor_excludes}'
  270. ret += f' constructor_prefixes={self.constructor_prefixes}'
  271. ret += f' constructor_raw={self.constructor_raw}'
  272. ret += f' constructors_extra={self.constructors_extra}'
  273. ret += f' constructors_wrappers={self.constructors_wrappers}'
  274. ret += f' copyable={self.copyable}'
  275. ret += f' extra_cpp={self.extra_cpp}'
  276. ret += f' iterator_next={self.iterator_next}'
  277. ret += f' methods_extra={self.methods_extra}'
  278. ret += f' method_wrappers={self.method_wrappers}'
  279. ret += f' method_wrappers_static={self.method_wrappers_static}'
  280. ret += f' opaque={self.opaque}'
  281. ret += f' pod={self.pod}'
  282. ret += f' virtual_fnptrs={self.virtual_fnptrs}'
  283. return ret
  284. class ClassExtras:
  285. '''
  286. Extra methods/features for each of our auto-generated C++ wrapper classes.
  287. '''
  288. def __init__( self, **namevalues):
  289. '''
  290. namevalues:
  291. Named args mapping from struct name (e.g. fz_document) to a
  292. ClassExtra.
  293. '''
  294. self.items = dict()
  295. for name, value in namevalues.items():
  296. self.items[ name] = value
  297. def get( self, tu, name):
  298. '''
  299. Searches for <name> and returns a ClassExtra instance. If <name> is not
  300. found, we insert an empty ClassExtra instance and return it. We do this
  301. for any name, e.g. name could be 'foo *'.
  302. We return None if <name> is a known enum.
  303. '''
  304. verbose = state.state_.show_details( name)
  305. if 0 and verbose:
  306. jlib.log( 'ClassExtras.get(): {=name}')
  307. name = util.clip( name, ('const ', 'struct '))
  308. if 0 and verbose:
  309. jlib.log( 'ClassExtras.get(): {=name}')
  310. if not name.startswith( ('fz_', 'pdf_')):
  311. return
  312. ret = self.items.setdefault( name, ClassExtra())
  313. if name in state.state_.enums[ tu]:
  314. #jlib.log( '*** name is an enum: {name=}')
  315. return None
  316. if ' ' not in name and not ret.pod and ret.copyable and ret.copyable != 'default':
  317. # Check whether there is a _keep() fn.
  318. keep_name = f'fz_keep_{name[3:]}' if name.startswith( 'fz_') else f'pdf_keep_{name[4:]}'
  319. keep_cursor = state.state_.find_function( tu, keep_name, method=True)
  320. if not keep_cursor:
  321. if ret.copyable:
  322. if 0:
  323. jlib.log( '*** Changing .copyable to False for {=name keep_name}')
  324. ret.copyable = False
  325. return ret
  326. def get_or_none( self, name):
  327. return self.items.get( name)
  328. # Customisation information for selected wrapper classes.
  329. #
  330. # We use MuPDF struct names as keys.
  331. #
  332. classextras = ClassExtras(
  333. fz_aa_context = ClassExtra(
  334. pod='inline',
  335. ),
  336. fz_band_writer = ClassExtra(
  337. class_top = '''
  338. /* We use these enums to support construction via all the relevant MuPDF functions. */
  339. enum Cm
  340. {
  341. MONO,
  342. COLOR,
  343. };
  344. enum P
  345. {
  346. PNG,
  347. PNM,
  348. PAM,
  349. PBM,
  350. PKM,
  351. PS,
  352. PSD,
  353. };
  354. ''',
  355. constructors_extra = [
  356. ExtraConstructor(
  357. f'({rename.class_("fz_output")}& out, Cm cm, const {rename.class_("fz_pcl_options")}& options)',
  358. f'''
  359. {{
  360. ::fz_output* out2 = out.m_internal;
  361. const ::fz_pcl_options* options2 = options.m_internal;
  362. if (0) {{}}
  363. else if (cm == MONO) m_internal = {rename.ll_fn('fz_new_mono_pcl_band_writer' )}( out2, options2);
  364. else if (cm == COLOR) m_internal = {rename.ll_fn('fz_new_color_pcl_band_writer')}( out2, options2);
  365. else throw std::runtime_error( "Unrecognised fz_band_writer_s Cm type");
  366. }}
  367. ''',
  368. comment = f'/* Constructor using fz_new_mono_pcl_band_writer() or fz_new_color_pcl_band_writer(). */',
  369. ),
  370. ExtraConstructor(
  371. f'({rename.class_("fz_output")}& out, P p)',
  372. f'''
  373. {{
  374. ::fz_output* out2 = out.m_internal;
  375. if (0) {{}}
  376. else if (p == PNG) m_internal = {rename.ll_fn('fz_new_png_band_writer')}( out2);
  377. else if (p == PNM) m_internal = {rename.ll_fn('fz_new_pnm_band_writer')}( out2);
  378. else if (p == PAM) m_internal = {rename.ll_fn('fz_new_pam_band_writer')}( out2);
  379. else if (p == PBM) m_internal = {rename.ll_fn('fz_new_pbm_band_writer')}( out2);
  380. else if (p == PKM) m_internal = {rename.ll_fn('fz_new_pkm_band_writer')}( out2);
  381. else if (p == PS) m_internal = {rename.ll_fn('fz_new_ps_band_writer' )}( out2);
  382. else if (p == PSD) m_internal = {rename.ll_fn('fz_new_psd_band_writer')}( out2);
  383. else throw std::runtime_error( "Unrecognised fz_band_writer_s P type");
  384. }}
  385. ''',
  386. comment = f'/* Constructor using fz_new_p*_band_writer(). */',
  387. ),
  388. ExtraConstructor(
  389. f'({rename.class_("fz_output")}& out, Cm cm, const {rename.class_("fz_pwg_options")}& options)',
  390. f'''
  391. {{
  392. ::fz_output* out2 = out.m_internal;
  393. const ::fz_pwg_options* options2 = &options.m_internal;
  394. if (0) {{}}
  395. else if (cm == MONO) m_internal = {rename.ll_fn('fz_new_mono_pwg_band_writer' )}( out2, options2);
  396. else if (cm == COLOR) m_internal = {rename.ll_fn('fz_new_pwg_band_writer')}( out2, options2);
  397. else throw std::runtime_error( "Unrecognised fz_band_writer_s Cm type");
  398. }}
  399. ''',
  400. comment = f'/* Constructor using fz_new_mono_pwg_band_writer() or fz_new_pwg_band_writer(). */',
  401. ),
  402. ],
  403. copyable = False,
  404. ),
  405. fz_bitmap = ClassExtra(
  406. accessors = True,
  407. ),
  408. fz_buffer = ClassExtra(
  409. constructor_raw = 'default',
  410. constructors_wrappers = [
  411. 'fz_read_file',
  412. ],
  413. ),
  414. fz_color_params = ClassExtra(
  415. pod='inline',
  416. constructors_extra = [
  417. ExtraConstructor('()',
  418. f'''
  419. {{
  420. this->ri = fz_default_color_params.ri;
  421. this->bp = fz_default_color_params.bp;
  422. this->op = fz_default_color_params.op;
  423. this->opm = fz_default_color_params.opm;
  424. }}
  425. ''',
  426. comment = '/* Equivalent to fz_default_color_params. */',
  427. ),
  428. ],
  429. ),
  430. fz_colorspace = ClassExtra(
  431. constructors_extra = [
  432. ExtraConstructor(
  433. '(Fixed fixed)',
  434. f'''
  435. {{
  436. if (0) {{}}
  437. else if ( fixed == Fixed_GRAY) m_internal = {rename.ll_fn( 'fz_device_gray')}();
  438. else if ( fixed == Fixed_RGB) m_internal = {rename.ll_fn( 'fz_device_rgb' )}();
  439. else if ( fixed == Fixed_BGR) m_internal = {rename.ll_fn( 'fz_device_bgr' )}();
  440. else if ( fixed == Fixed_CMYK) m_internal = {rename.ll_fn( 'fz_device_cmyk')}();
  441. else if ( fixed == Fixed_LAB) m_internal = {rename.ll_fn( 'fz_device_lab' )}();
  442. else {{
  443. std::string message = "Unrecognised fixed colorspace id";
  444. throw {rename.error_class("FZ_ERROR_GENERIC")}(message.c_str());
  445. }}
  446. {rename.ll_fn('fz_keep_colorspace')}(m_internal);
  447. }}
  448. ''',
  449. comment = '/* Construct using one of: fz_device_gray(), fz_device_rgb(), fz_device_bgr(), fz_device_cmyk(), fz_device_lab(). */',
  450. ),
  451. ],
  452. constructor_raw=1,
  453. class_top = '''
  454. /* We use this enums to support construction via all the relevant MuPDF functions. */
  455. enum Fixed
  456. {
  457. Fixed_GRAY,
  458. Fixed_RGB,
  459. Fixed_BGR,
  460. Fixed_CMYK,
  461. Fixed_LAB,
  462. };
  463. ''',
  464. ),
  465. fz_compressed_buffer = ClassExtra(
  466. methods_extra = [
  467. ExtraMethod(
  468. rename.class_('fz_buffer'),
  469. 'get_buffer()',
  470. textwrap.dedent(f'''
  471. {{
  472. return {rename.class_('fz_buffer')}(
  473. {rename.ll_fn('fz_keep_buffer')}(m_internal->buffer)
  474. );
  475. }}
  476. '''),
  477. '/* Returns wrapper class for fz_buffer *m_internal.buffer. */',
  478. ),
  479. ],
  480. ),
  481. fz_context = ClassExtra(
  482. copyable = False,
  483. ),
  484. fz_cookie = ClassExtra(
  485. constructors_extra = [
  486. ExtraConstructor( '()',
  487. '''
  488. {
  489. this->m_internal.abort = 0;
  490. this->m_internal.progress = 0;
  491. this->m_internal.progress_max = (size_t) -1;
  492. this->m_internal.errors = 0;
  493. this->m_internal.incomplete = 0;
  494. }
  495. ''',
  496. comment = '/* Default constructor sets all fields to default values. */',
  497. ),
  498. ],
  499. constructor_raw = False,
  500. methods_extra = [
  501. ExtraMethod(
  502. 'void',
  503. 'set_abort()',
  504. '{ m_internal.abort = 1; }\n',
  505. '/* Sets m_internal.abort to 1. */',
  506. ),
  507. ExtraMethod(
  508. 'void',
  509. 'increment_errors(int delta)',
  510. '{ m_internal.errors += delta; }\n',
  511. '/* Increments m_internal.errors by <delta>. */',
  512. ),
  513. ],
  514. pod = True,
  515. # Other code asynchronously writes to our fields, so we are not
  516. # copyable. todo: maybe tie us to all objects to which we have
  517. # been associated?
  518. #
  519. copyable=False,
  520. ),
  521. fz_device = ClassExtra(
  522. virtual_fnptrs = dict(
  523. self_ = lambda name: f'(*({rename.class_("fz_device")}2**) ({name} + 1))',
  524. alloc = textwrap.dedent( f'''
  525. m_internal = {rename.ll_fn("fz_new_device_of_size")}(
  526. sizeof(*m_internal) + sizeof({rename.class_("fz_device")}2*)
  527. );
  528. *(({rename.class_("fz_device")}2**) (m_internal + 1)) = this;
  529. '''),
  530. ),
  531. constructor_raw = True,
  532. ),
  533. fz_document = ClassExtra(
  534. constructor_excludes = [
  535. 'fz_new_xhtml_document_from_document',
  536. ],
  537. constructor_prefixes = [
  538. 'fz_open_accelerated_document',
  539. 'fz_open_document',
  540. ],
  541. constructors_extra = [
  542. ExtraConstructor( f'({rename.class_("pdf_document")}& pdfdocument)',
  543. f'''
  544. {{
  545. m_internal = {rename.ll_fn('fz_keep_document')}(&pdfdocument.m_internal->super);
  546. }}
  547. ''',
  548. f'/* Returns a {rename.class_("fz_document")} for pdfdocument.m_internal.super. */',
  549. ),
  550. ],
  551. constructor_raw = 'default',
  552. method_wrappers = [
  553. 'fz_load_outline',
  554. ],
  555. method_wrappers_static = [
  556. 'fz_new_xhtml_document_from_document',
  557. ],
  558. ),
  559. # This is a little complicated. Many of the functions that we would
  560. # like to wrap to form constructors, have the same set of args. C++
  561. # does not support named constructors so we differentiate between
  562. # constructors with identical args using enums.
  563. #
  564. # Also, fz_document_writer is not reference counted so the wrapping
  565. # class is not copyable or assignable, so our normal approach of making
  566. # static class functions that return a newly constructed instance by
  567. # value, does not work.
  568. #
  569. # So instead we define enums that are passed to our constructors,
  570. # allowing the constructor to decide which fz_ function to use to
  571. # create the new fz_document_writer.
  572. #
  573. # There should be no commented-out constructors in the generated code
  574. # marked as 'Disabled because same args as ...'.
  575. #
  576. fz_document_writer = ClassExtra(
  577. class_top = '''
  578. /* Used for constructor that wraps fz_ functions taking (const char *path, const char *options). */
  579. enum PathType
  580. {
  581. PathType_CBZ,
  582. PathType_DOCX,
  583. PathType_ODT,
  584. PathType_PAM_PIXMAP,
  585. PathType_PBM_PIXMAP,
  586. PathType_PCL,
  587. PathType_PCLM,
  588. PathType_PDF,
  589. PathType_PDFOCR,
  590. PathType_PGM_PIXMAP,
  591. PathType_PKM_PIXMAP,
  592. PathType_PNG_PIXMAP,
  593. PathType_PNM_PIXMAP,
  594. PathType_PPM_PIXMAP,
  595. PathType_PS,
  596. PathType_PWG,
  597. PathType_SVG,
  598. };
  599. /* Used for constructor that wraps fz_ functions taking (Output& out, const char *options). */
  600. enum OutputType
  601. {
  602. OutputType_CBZ,
  603. OutputType_DOCX,
  604. OutputType_ODT,
  605. OutputType_PCL,
  606. OutputType_PCLM,
  607. OutputType_PDF,
  608. OutputType_PDFOCR,
  609. OutputType_PS,
  610. OutputType_PWG,
  611. };
  612. /* Used for constructor that wraps fz_ functions taking (const char *format, const char *path, const char *options). */
  613. enum FormatPathType
  614. {
  615. FormatPathType_DOCUMENT,
  616. FormatPathType_TEXT,
  617. };
  618. ''',
  619. # These excludes should match the functions called by the
  620. # extra constructors defined below. This ensures that we don't
  621. # generate commented-out constructors with a comment saying
  622. # 'Disabled because same args as ...'.
  623. constructor_excludes = [
  624. 'fz_new_cbz_writer',
  625. 'fz_new_docx_writer',
  626. 'fz_new_odt_writer',
  627. 'fz_new_pam_pixmap_writer',
  628. 'fz_new_pbm_pixmap_writer',
  629. 'fz_new_pcl_writer',
  630. 'fz_new_pclm_writer',
  631. 'fz_new_pdfocr_writer',
  632. 'fz_new_pdf_writer',
  633. 'fz_new_pgm_pixmap_writer',
  634. 'fz_new_pkm_pixmap_writer',
  635. 'fz_new_png_pixmap_writer',
  636. 'fz_new_pnm_pixmap_writer',
  637. 'fz_new_ppm_pixmap_writer',
  638. 'fz_new_ps_writer',
  639. 'fz_new_pwg_writer',
  640. 'fz_new_svg_writer',
  641. 'fz_new_cbz_writer_with_output',
  642. 'fz_new_docx_writer_with_output',
  643. 'fz_new_odt_writer_with_output',
  644. 'fz_new_pcl_writer_with_output',
  645. 'fz_new_pclm_writer_with_output',
  646. 'fz_new_pdf_writer_with_output',
  647. 'fz_new_pdfocr_writer_with_output',
  648. 'fz_new_ps_writer_with_output',
  649. 'fz_new_pwg_writer_with_output',
  650. 'fz_new_document_writer',
  651. 'fz_new_text_writer',
  652. 'fz_new_document_writer_with_output',
  653. 'fz_new_text_writer_with_output',
  654. ],
  655. copyable=False,
  656. methods_extra = [
  657. # 2022-08-26: we used to provide a custom wrapper of
  658. # fz_begin_page(), but this is not longer necessary
  659. # because function_wrapper_class_aware_body() knows
  660. # that fz_begin_page() returns a borrowed reference.
  661. #
  662. ],
  663. constructors_extra = [
  664. ExtraConstructor(
  665. '(const char *path, const char *options, PathType path_type)',
  666. f'''
  667. {{
  668. if (0) {{}}
  669. else if (path_type == PathType_CBZ) m_internal = {rename.ll_fn( 'fz_new_cbz_writer')}(path, options);
  670. else if (path_type == PathType_DOCX) m_internal = {rename.ll_fn( 'fz_new_docx_writer')}(path, options);
  671. else if (path_type == PathType_ODT) m_internal = {rename.ll_fn( 'fz_new_odt_writer')}(path, options);
  672. else if (path_type == PathType_PAM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_pam_pixmap_writer')}(path, options);
  673. else if (path_type == PathType_PBM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_pbm_pixmap_writer')}(path, options);
  674. else if (path_type == PathType_PCL) m_internal = {rename.ll_fn( 'fz_new_pcl_writer')}(path, options);
  675. else if (path_type == PathType_PCLM) m_internal = {rename.ll_fn( 'fz_new_pclm_writer')}(path, options);
  676. else if (path_type == PathType_PDF) m_internal = {rename.ll_fn( 'fz_new_pdf_writer')}(path, options);
  677. else if (path_type == PathType_PDFOCR) m_internal = {rename.ll_fn( 'fz_new_pdfocr_writer')}(path, options);
  678. else if (path_type == PathType_PGM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_pgm_pixmap_writer')}(path, options);
  679. else if (path_type == PathType_PKM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_pkm_pixmap_writer')}(path, options);
  680. else if (path_type == PathType_PNG_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_png_pixmap_writer')}(path, options);
  681. else if (path_type == PathType_PNM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_pnm_pixmap_writer')}(path, options);
  682. else if (path_type == PathType_PPM_PIXMAP) m_internal = {rename.ll_fn( 'fz_new_ppm_pixmap_writer')}(path, options);
  683. else if (path_type == PathType_PS) m_internal = {rename.ll_fn( 'fz_new_ps_writer')}(path, options);
  684. else if (path_type == PathType_PWG) m_internal = {rename.ll_fn( 'fz_new_pwg_writer')}(path, options);
  685. else if (path_type == PathType_SVG) m_internal = {rename.ll_fn( 'fz_new_svg_writer')}(path, options);
  686. else throw {rename.error_class('FZ_ERROR_ABORT')}( "Unrecognised Type value");
  687. }}
  688. ''',
  689. comment = textwrap.dedent('''
  690. /* Constructor using one of:
  691. fz_new_cbz_writer()
  692. fz_new_docx_writer()
  693. fz_new_odt_writer()
  694. fz_new_pam_pixmap_writer()
  695. fz_new_pbm_pixmap_writer()
  696. fz_new_pcl_writer()
  697. fz_new_pclm_writer()
  698. fz_new_pdf_writer()
  699. fz_new_pdfocr_writer()
  700. fz_new_pgm_pixmap_writer()
  701. fz_new_pkm_pixmap_writer()
  702. fz_new_png_pixmap_writer()
  703. fz_new_pnm_pixmap_writer()
  704. fz_new_ppm_pixmap_writer()
  705. fz_new_ps_writer()
  706. fz_new_pwg_writer()
  707. fz_new_svg_writer()
  708. */'''),
  709. ),
  710. ExtraConstructor(
  711. f'({rename.class_("fz_output")}& out, const char *options, OutputType output_type)',
  712. f'''
  713. {{
  714. /* All fz_new_*_writer_with_output() functions take
  715. ownership of the fz_output, even if they throw an
  716. exception. So we need to set out.m_internal to null
  717. here so its destructor does nothing. */
  718. ::fz_output* out2 = out.m_internal;
  719. out.m_internal = NULL;
  720. if (0) {{}}
  721. else if (output_type == OutputType_CBZ) m_internal = {rename.ll_fn( 'fz_new_cbz_writer_with_output')}(out2, options);
  722. else if (output_type == OutputType_DOCX) m_internal = {rename.ll_fn( 'fz_new_docx_writer_with_output')}(out2, options);
  723. else if (output_type == OutputType_ODT) m_internal = {rename.ll_fn( 'fz_new_odt_writer_with_output')}(out2, options);
  724. else if (output_type == OutputType_PCL) m_internal = {rename.ll_fn( 'fz_new_pcl_writer_with_output')}(out2, options);
  725. else if (output_type == OutputType_PCLM) m_internal = {rename.ll_fn( 'fz_new_pclm_writer_with_output')}(out2, options);
  726. else if (output_type == OutputType_PDF) m_internal = {rename.ll_fn( 'fz_new_pdf_writer_with_output')}(out2, options);
  727. else if (output_type == OutputType_PDFOCR) m_internal = {rename.ll_fn( 'fz_new_pdfocr_writer_with_output')}(out2, options);
  728. else if (output_type == OutputType_PS) m_internal = {rename.ll_fn( 'fz_new_ps_writer_with_output')}(out2, options);
  729. else if (output_type == OutputType_PWG) m_internal = {rename.ll_fn( 'fz_new_pwg_writer_with_output')}(out2, options);
  730. else
  731. {{
  732. /* Ensure that out2 is dropped before we return. */
  733. {rename.ll_fn( 'fz_drop_output')}(out2);
  734. throw {rename.error_class('FZ_ERROR_ABORT')}( "Unrecognised OutputType value");
  735. }}
  736. }}
  737. ''',
  738. comment = textwrap.dedent('''
  739. /* Constructor using one of:
  740. fz_new_cbz_writer_with_output()
  741. fz_new_docx_writer_with_output()
  742. fz_new_odt_writer_with_output()
  743. fz_new_pcl_writer_with_output()
  744. fz_new_pclm_writer_with_output()
  745. fz_new_pdf_writer_with_output()
  746. fz_new_pdfocr_writer_with_output()
  747. fz_new_ps_writer_with_output()
  748. fz_new_pwg_writer_with_output()
  749. This constructor takes ownership of <out> -
  750. out.m_internal is set to NULL after this constructor
  751. returns so <out> must not be used again.
  752. */
  753. '''),
  754. ),
  755. ExtraConstructor(
  756. '(const char *format, const char *path, const char *options, FormatPathType format_path_type)',
  757. f'''
  758. {{
  759. if (0) {{}}
  760. else if (format_path_type == FormatPathType_DOCUMENT) m_internal = {rename.ll_fn( 'fz_new_document_writer')}(format, path, options);
  761. else if (format_path_type == FormatPathType_TEXT) m_internal = {rename.ll_fn( 'fz_new_text_writer')}(format, path, options);
  762. else throw {rename.error_class('FZ_ERROR_ABORT')}( "Unrecognised OutputType value");
  763. }}
  764. ''',
  765. comment = textwrap.dedent('''
  766. /* Constructor using one of:
  767. fz_new_document_writer()
  768. fz_new_text_writer()
  769. */'''),
  770. ),
  771. ExtraConstructor(
  772. f'({rename.class_("fz_output")}& out, const char *format, const char *options)',
  773. f'''
  774. {{
  775. /* Need to transfer ownership of <out>. */
  776. ::fz_output* out2 = out.m_internal;
  777. out.m_internal = NULL;
  778. m_internal = {rename.ll_fn( 'fz_new_document_writer_with_output')}(out2, format, options);
  779. }}
  780. ''',
  781. comment = textwrap.dedent('''
  782. /* Constructor using fz_new_document_writer_with_output().
  783. This constructor takes ownership of <out> -
  784. out.m_internal is set to NULL after this constructor
  785. returns so <out> must not be used again.
  786. */'''),
  787. ),
  788. ExtraConstructor(
  789. f'(const char *format, {rename.class_("fz_output")}& out, const char *options)',
  790. f'''
  791. {{
  792. /* Need to transfer ownership of <out>. */
  793. ::fz_output* out2 = out.m_internal;
  794. out.m_internal = NULL;
  795. m_internal = {rename.ll_fn( 'fz_new_text_writer_with_output')}(format, out2, options);
  796. }}
  797. ''',
  798. comment = textwrap.dedent('''
  799. /* Constructor using fz_new_text_writer_with_output().
  800. This constructor takes ownership of <out> -
  801. out.m_internal is set to NULL after this constructor
  802. returns so <out> must not be used again.
  803. */'''),
  804. ),
  805. ],
  806. ),
  807. fz_draw_options = ClassExtra(
  808. constructors_wrappers = [
  809. 'fz_parse_draw_options',
  810. ],
  811. copyable=False,
  812. pod='inline',
  813. ),
  814. fz_halftone = ClassExtra(
  815. constructor_raw = 'default',
  816. ),
  817. fz_image = ClassExtra(
  818. accessors=True,
  819. ),
  820. fz_install_load_system_font_funcs_args = ClassExtra(
  821. pod = True,
  822. virtual_fnptrs = dict(
  823. alloc = textwrap.dedent( f'''
  824. /*
  825. There can only be one active instance of the wrapper
  826. class so we simply keep a pointer to it in a global
  827. variable.
  828. */
  829. fz_install_load_system_font_funcs2_state = this;
  830. '''),
  831. self_ = lambda: f'({rename.class_("fz_install_load_system_font_funcs_args")}2*) fz_install_load_system_font_funcs2_state',
  832. self_n = None,
  833. ),
  834. ),
  835. fz_irect = ClassExtra(
  836. constructor_prefixes = [
  837. 'fz_irect_from_rect',
  838. 'fz_make_irect',
  839. ],
  840. pod='inline',
  841. constructor_raw = True,
  842. ),
  843. fz_link = ClassExtra(
  844. constructors_extra = [
  845. ExtraConstructor( f'({rename.class_("fz_rect")}& rect, const char *uri)',
  846. f'''
  847. {{
  848. m_internal = {rename.ll_fn('fz_new_link_of_size')}( sizeof(fz_link), *rect.internal(), uri);
  849. }}
  850. ''',
  851. '/* Construct by calling fz_new_link_of_size() with size=sizeof(fz_link). */',
  852. )
  853. ],
  854. accessors = True,
  855. iterator_next = ('', ''),
  856. constructor_raw = 'default',
  857. copyable = True,
  858. ),
  859. fz_location = ClassExtra(
  860. constructor_prefixes = [
  861. 'fz_make_location',
  862. ],
  863. pod='inline',
  864. constructor_raw = True,
  865. ),
  866. fz_matrix = ClassExtra(
  867. constructor_prefixes = [
  868. 'fz_make_matrix',
  869. ],
  870. method_wrappers_static = [
  871. 'fz_concat',
  872. 'fz_scale',
  873. 'fz_shear',
  874. 'fz_rotate',
  875. 'fz_translate',
  876. 'fz_transform_page',
  877. ],
  878. constructors_extra = [
  879. ExtraConstructor( '()',
  880. '''
  881. : a(1), b(0), c(0), d(1), e(0), f(0)
  882. {
  883. }
  884. ''',
  885. comment = '/* Constructs identity matrix (like fz_identity). */'),
  886. ],
  887. pod='inline',
  888. constructor_raw = True,
  889. ),
  890. fz_md5 = ClassExtra(
  891. pod = True,
  892. constructors_extra = [
  893. ExtraConstructor(
  894. '()',
  895. f'''
  896. {{
  897. {rename.ll_fn( 'fz_md5_init')}( &m_internal);
  898. }}
  899. ''',
  900. '/* Default constructor calls md5_init(). */',
  901. )
  902. ],
  903. ),
  904. fz_outline = ClassExtra(
  905. # We add various methods to give depth-first iteration of outlines.
  906. #
  907. constructor_prefixes = [
  908. 'fz_load_outline',
  909. ],
  910. accessors=True,
  911. ),
  912. fz_outline_item = ClassExtra(
  913. class_top = f'''
  914. FZ_FUNCTION bool valid() const;
  915. FZ_FUNCTION const std::string& title() const; /* Will throw if valid() is not true. */
  916. FZ_FUNCTION const std::string& uri() const; /* Will throw if valid() is not true. */
  917. FZ_FUNCTION int is_open() const; /* Will throw if valid() is not true. */
  918. ''',
  919. class_bottom = f'''
  920. private:
  921. bool m_valid;
  922. std::string m_title;
  923. std::string m_uri;
  924. int m_is_open;
  925. ''',
  926. constructors_extra = [
  927. ],
  928. constructor_raw = 'declaration_only',
  929. copyable = 'default',
  930. pod = 'none',
  931. extra_cpp = f'''
  932. FZ_FUNCTION {rename.class_("fz_outline_item")}::{rename.class_("fz_outline_item")}(const ::fz_outline_item* item)
  933. {{
  934. if (item)
  935. {{
  936. m_valid = true;
  937. m_title = item->title;
  938. m_uri = item->uri;
  939. m_is_open = item->is_open;
  940. }}
  941. else
  942. {{
  943. m_valid = false;
  944. }}
  945. }}
  946. FZ_FUNCTION bool {rename.class_("fz_outline_item")}::valid() const
  947. {{
  948. return m_valid;
  949. }}
  950. FZ_FUNCTION const std::string& {rename.class_("fz_outline_item")}::title() const
  951. {{
  952. if (!m_valid) throw {rename.error_class("FZ_ERROR_GENERIC")}("fz_outline_item is invalid");
  953. return m_title;
  954. }}
  955. FZ_FUNCTION const std::string& {rename.class_("fz_outline_item")}::uri() const
  956. {{
  957. if (!m_valid) throw {rename.error_class("FZ_ERROR_GENERIC")}("fz_outline_item is invalid");
  958. return m_uri;
  959. }}
  960. FZ_FUNCTION int {rename.class_("fz_outline_item")}::is_open() const
  961. {{
  962. if (!m_valid) throw {rename.error_class("FZ_ERROR_GENERIC")}("fz_outline_item is invalid");
  963. return m_is_open;
  964. }}
  965. ''',
  966. ),
  967. fz_outline_iterator = ClassExtra(
  968. copyable = False,
  969. methods_extra = [
  970. ExtraMethod(
  971. 'int',
  972. f'{rename.method("fz_outline_iterator", "fz_outline_iterator_insert")}({rename.class_("fz_outline_item")}& item)',
  973. f'''
  974. {{
  975. /* Create a temporary fz_outline_item. */
  976. ::fz_outline_item item2;
  977. item2.title = (char*) item.title().c_str();
  978. item2.uri = (char*) item.uri().c_str();
  979. item2.is_open = item.is_open();
  980. return {rename.ll_fn("fz_outline_iterator_insert")}(m_internal, &item2);
  981. }}
  982. ''',
  983. comment = '/* Custom wrapper for fz_outline_iterator_insert(). */',
  984. ),
  985. ExtraMethod(
  986. 'void',
  987. f'{rename.method("fz_outline_iterator", "fz_outline_iterator_update")}({rename.class_("fz_outline_item")}& item)',
  988. f'''
  989. {{
  990. /* Create a temporary fz_outline_item. */
  991. ::fz_outline_item item2;
  992. item2.title = (char*) item.title().c_str();
  993. item2.uri = (char*) item.uri().c_str();
  994. item2.is_open = item.is_open();
  995. return {rename.ll_fn("fz_outline_iterator_update")}(m_internal, &item2);
  996. }}
  997. ''',
  998. comment = '/* Custom wrapper for fz_outline_iterator_update(). */',
  999. ),
  1000. ],
  1001. ),
  1002. fz_output = ClassExtra(
  1003. virtual_fnptrs = dict(
  1004. self_ = lambda name: f'({rename.class_("fz_output")}2*) {name}',
  1005. alloc = f'm_internal = {rename.ll_fn("fz_new_output")}(0 /*bufsize*/, this /*state*/, nullptr /*write*/, nullptr /*close*/, nullptr /*drop*/);\n',
  1006. ),
  1007. constructor_raw = 'default',
  1008. constructor_excludes = [
  1009. # These all have the same prototype, so are used by
  1010. # constructors_extra below.
  1011. 'fz_new_asciihex_output',
  1012. 'fz_new_ascii85_output',
  1013. 'fz_new_rle_output',
  1014. ],
  1015. constructors_extra = [
  1016. ExtraConstructor( '(Fixed out)',
  1017. f'''
  1018. {{
  1019. if (0) {{}}
  1020. else if (out == Fixed_STDOUT) {{
  1021. m_internal = {rename.ll_fn('fz_stdout')}();
  1022. }}
  1023. else if (out == Fixed_STDERR) {{
  1024. m_internal = {rename.ll_fn('fz_stderr')}();
  1025. }}
  1026. else {{
  1027. throw {rename.error_class('FZ_ERROR_ABORT')}("Unrecognised Fixed value");
  1028. }}
  1029. }}
  1030. ''',
  1031. '/* Uses fz_stdout() or fz_stderr(). */',
  1032. # Note that it's ok to call fz_drop_output() on fz_stdout and fz_stderr.
  1033. ),
  1034. ExtraConstructor(
  1035. f'(const {rename.class_("fz_output")}& chain, Filter filter)',
  1036. f'''
  1037. {{
  1038. if (0) {{}}
  1039. else if (filter == Filter_HEX) {{
  1040. m_internal = {rename.ll_fn('fz_new_asciihex_output')}(chain.m_internal);
  1041. }}
  1042. else if (filter == Filter_85) {{
  1043. m_internal = {rename.ll_fn('fz_new_ascii85_output')}(chain.m_internal);
  1044. }}
  1045. else if (filter == Filter_RLE) {{
  1046. m_internal = {rename.ll_fn('fz_new_rle_output')}(chain.m_internal);
  1047. }}
  1048. else {{
  1049. throw {rename.error_class('FZ_ERROR_ABORT')}("Unrecognised Filter value");
  1050. }}
  1051. }}
  1052. ''',
  1053. comment = '/* Calls one of: fz_new_asciihex_output(), fz_new_ascii85_output(), fz_new_rle_output(). */',
  1054. ),
  1055. ],
  1056. class_top = '''
  1057. enum Fixed
  1058. {
  1059. Fixed_STDOUT=1,
  1060. Fixed_STDERR=2,
  1061. };
  1062. enum Filter
  1063. {
  1064. Filter_HEX,
  1065. Filter_85,
  1066. Filter_RLE,
  1067. };
  1068. '''
  1069. ,
  1070. copyable=False, # No fz_keep_output() fn?
  1071. ),
  1072. fz_page = ClassExtra(
  1073. constructor_prefixes = [
  1074. 'fz_load_page',
  1075. 'fz_load_chapter_page',
  1076. ],
  1077. constructors_extra = [
  1078. ExtraConstructor( f'({rename.class_("pdf_page")}& pdfpage)',
  1079. f'''
  1080. {{
  1081. m_internal = {rename.ll_fn('fz_keep_page')}(&pdfpage.m_internal->super);
  1082. }}
  1083. ''',
  1084. f'/* Return {rename.class_("fz_page")} for pdfpage.m_internal.super. */',
  1085. ),
  1086. ],
  1087. methods_extra = [
  1088. ExtraMethod(
  1089. f'{rename.class_("fz_document")}',
  1090. 'doc()',
  1091. f'''
  1092. {{
  1093. return {rename.class_("fz_document")}( {rename.ll_fn('fz_keep_document')}( m_internal->doc));
  1094. }}
  1095. ''',
  1096. f'/* Returns wrapper for .doc member. */',
  1097. ),
  1098. ],
  1099. constructor_raw = True,
  1100. ),
  1101. fz_path_walker = ClassExtra(
  1102. constructor_raw = 'default',
  1103. virtual_fnptrs = dict(
  1104. self_ = lambda name: f'*({rename.class_("fz_path_walker")}2**) ((fz_path_walker*) {name} + 1)',
  1105. alloc = textwrap.dedent( f'''
  1106. m_internal = (::fz_path_walker*) {rename.ll_fn("fz_calloc")}(
  1107. 1,
  1108. sizeof(*m_internal) + sizeof({rename.class_("fz_path_walker")}2*)
  1109. );
  1110. *({rename.class_("fz_path_walker")}2**) (m_internal + 1) = this;
  1111. '''),
  1112. free = f'{rename.ll_fn("fz_free")}(m_internal);\n',
  1113. comment = textwrap.dedent(f'''
  1114. /*
  1115. We require that the `void* arg` passed to callbacks
  1116. is the original `fz_path_walker*`. So, for example,
  1117. class-aware wrapper mupdf::fz_walk_path() should be
  1118. called like:
  1119. mupdf.FzPath path = ...;
  1120. struct Walker : mupdf.FzPathWalker2 {...};
  1121. Walker walker(...);
  1122. mupdf::fz_walk_path(path, walker, walker.m_internal);
  1123. */
  1124. ''')
  1125. ),
  1126. ),
  1127. fz_pcl_options = ClassExtra(
  1128. constructors_wrappers = [
  1129. 'fz_parse_pcl_options',
  1130. ],
  1131. copyable=False,
  1132. ),
  1133. fz_pclm_options = ClassExtra(
  1134. constructor_prefixes = [
  1135. 'fz_parse_pclm_options',
  1136. ],
  1137. copyable=False,
  1138. constructors_extra = [
  1139. ExtraConstructor( '(const char *args)',
  1140. f'''
  1141. {{
  1142. {rename.ll_fn('fz_parse_pclm_options')}(m_internal, args);
  1143. }}
  1144. ''',
  1145. '/* Construct using fz_parse_pclm_options(). */',
  1146. )
  1147. ],
  1148. ),
  1149. fz_pdfocr_options = ClassExtra(
  1150. pod = 'inline',
  1151. methods_extra = [
  1152. ExtraMethod(
  1153. 'void',
  1154. 'language_set2(const char* language)',
  1155. f'''
  1156. {{
  1157. fz_strlcpy(this->language, language, sizeof(this->language));
  1158. }}
  1159. ''',
  1160. '/* Copies <language> into this->language, truncating if necessary. */',
  1161. ),
  1162. ExtraMethod(
  1163. 'void',
  1164. 'datadir_set2(const char* datadir)',
  1165. f'''
  1166. {{
  1167. fz_strlcpy(this->datadir, datadir, sizeof(this->datadir));
  1168. }}
  1169. ''',
  1170. '/* Copies <datadir> into this->datadir, truncating if necessary. */',
  1171. ),
  1172. ],
  1173. ),
  1174. fz_pixmap = ClassExtra(
  1175. constructor_raw = True,
  1176. accessors = True,
  1177. ),
  1178. fz_point = ClassExtra(
  1179. method_wrappers_static = [
  1180. 'fz_transform_point',
  1181. 'fz_transform_point_xy',
  1182. 'fz_transform_vector',
  1183. ],
  1184. constructors_extra = [
  1185. ExtraConstructor( '(float x, float y)',
  1186. '''
  1187. : x(x), y(y)
  1188. {
  1189. }
  1190. ''',
  1191. comment = '/* Construct using specified values. */',
  1192. ),
  1193. ],
  1194. methods_extra = [
  1195. ExtraMethod(
  1196. f'{rename.class_("fz_point")}&',
  1197. f'transform(const {rename.class_("fz_matrix")}& m)',
  1198. '''
  1199. {
  1200. double old_x = x;
  1201. x = old_x * m.a + y * m.c + m.e;
  1202. y = old_x * m.b + y * m.d + m.f;
  1203. return *this;
  1204. }
  1205. ''',
  1206. comment = '/* Post-multiply *this by <m> and return *this. */',
  1207. ),
  1208. ],
  1209. pod='inline',
  1210. constructor_raw = True,
  1211. ),
  1212. fz_pwg_options = ClassExtra(
  1213. pod=True,
  1214. ),
  1215. fz_quad = ClassExtra(
  1216. constructor_prefixes = [
  1217. 'fz_transform_quad',
  1218. 'fz_quad_from_rect'
  1219. ],
  1220. pod='inline',
  1221. constructor_raw = True,
  1222. ),
  1223. fz_rect = ClassExtra(
  1224. constructor_prefixes = [
  1225. 'fz_transform_rect',
  1226. 'fz_bound_display_list',
  1227. 'fz_rect_from_irect',
  1228. 'fz_rect_from_quad',
  1229. ],
  1230. method_wrappers_static = [
  1231. 'fz_intersect_rect',
  1232. 'fz_union_rect',
  1233. ],
  1234. constructors_extra = [
  1235. ExtraConstructor(
  1236. '(double x0, double y0, double x1, double y1)',
  1237. '''
  1238. :
  1239. x0(x0),
  1240. x1(x1),
  1241. y0(y0),
  1242. y1(y1)
  1243. {
  1244. }
  1245. ''',
  1246. comment = '/* Construct from specified values. */',
  1247. ),
  1248. ExtraConstructor(
  1249. f'(const {rename.class_("fz_rect")}& rhs)',
  1250. '''
  1251. :
  1252. x0(rhs.x0),
  1253. y0(rhs.y0),
  1254. x1(rhs.x1),
  1255. y1(rhs.y1)
  1256. {
  1257. }
  1258. ''',
  1259. comment = '/* Copy constructor using plain copy. */',
  1260. ),
  1261. ExtraConstructor( '(Fixed fixed)',
  1262. f'''
  1263. {{
  1264. if (0) {{}}
  1265. else if (fixed == Fixed_UNIT) *this->internal() = {rename.c_fn('fz_unit_rect')};
  1266. else if (fixed == Fixed_EMPTY) *this->internal() = {rename.c_fn('fz_empty_rect')};
  1267. else if (fixed == Fixed_INFINITE) *this->internal() = {rename.c_fn('fz_infinite_rect')};
  1268. else throw {rename.error_class('FZ_ERROR_ABORT')}( "Unrecognised From value");
  1269. }}
  1270. ''',
  1271. comment = '/* Construct from fz_unit_rect, fz_empty_rect or fz_infinite_rect. */',
  1272. ),
  1273. ],
  1274. methods_extra = [
  1275. ExtraMethod(
  1276. 'void',
  1277. f'transform(const {rename.class_("fz_matrix")}& m)',
  1278. f'''
  1279. {{
  1280. *(::fz_rect*) &this->x0 = {rename.c_fn('fz_transform_rect')}(*(::fz_rect*) &this->x0, *(::fz_matrix*) &m.a);
  1281. }}
  1282. ''',
  1283. comment = '/* Transforms *this using fz_transform_rect() with <m>. */',
  1284. ),
  1285. ExtraMethod( 'bool', 'contains(double x, double y)',
  1286. '''
  1287. {
  1288. if (is_empty()) {
  1289. return false;
  1290. }
  1291. return true
  1292. && x >= x0
  1293. && x < x1
  1294. && y >= y0
  1295. && y < y1
  1296. ;
  1297. }
  1298. ''',
  1299. comment = '/* Convenience method using fz_contains_rect(). */',
  1300. ),
  1301. ExtraMethod( 'bool', f'contains({rename.class_("fz_rect")}& rhs)',
  1302. f'''
  1303. {{
  1304. return {rename.c_fn('fz_contains_rect')}(*(::fz_rect*) &x0, *(::fz_rect*) &rhs.x0);
  1305. }}
  1306. ''',
  1307. comment = '/* Uses fz_contains_rect(*this, rhs). */',
  1308. ),
  1309. ExtraMethod( 'bool', 'is_empty()',
  1310. f'''
  1311. {{
  1312. return {rename.c_fn('fz_is_empty_rect')}(*(::fz_rect*) &x0);
  1313. }}
  1314. ''',
  1315. comment = '/* Uses fz_is_empty_rect(). */',
  1316. ),
  1317. ExtraMethod( 'void', f'union_({rename.class_("fz_rect")}& rhs)',
  1318. f'''
  1319. {{
  1320. *(::fz_rect*) &x0 = {rename.c_fn('fz_union_rect')}(*(::fz_rect*) &x0, *(::fz_rect*) &rhs.x0);
  1321. }}
  1322. ''',
  1323. comment = '/* Updates *this using fz_union_rect(). */',
  1324. ),
  1325. ],
  1326. pod='inline',
  1327. constructor_raw = True,
  1328. copyable = True,
  1329. class_top = '''
  1330. enum Fixed
  1331. {
  1332. Fixed_UNIT,
  1333. Fixed_EMPTY,
  1334. Fixed_INFINITE,
  1335. };
  1336. ''',
  1337. ),
  1338. fz_separations = ClassExtra(
  1339. constructor_raw = 'default',
  1340. opaque = True,
  1341. ),
  1342. fz_shade = ClassExtra(
  1343. methods_extra = [
  1344. ExtraMethod( 'void',
  1345. f'{rename.method( "fz_shade", "fz_paint_shade_no_cache")}('
  1346. + f' const {rename.class_("fz_colorspace")}& override_cs'
  1347. + f', {rename.class_("fz_matrix")}& ctm'
  1348. + f', const {rename.class_("fz_pixmap")}& dest'
  1349. + f', {rename.class_("fz_color_params")}& color_params'
  1350. + f', {rename.class_("fz_irect")}& bbox'
  1351. + f', const {rename.class_("fz_overprint")}& eop'
  1352. + f')'
  1353. ,
  1354. f'''
  1355. {{
  1356. return {rename.ll_fn('fz_paint_shade')}(
  1357. this->m_internal,
  1358. override_cs.m_internal,
  1359. *(::fz_matrix*) &ctm.a,
  1360. dest.m_internal,
  1361. *(::fz_color_params*) &color_params.ri,
  1362. *(::fz_irect*) &bbox.x0,
  1363. eop.m_internal,
  1364. NULL /*cache*/
  1365. );
  1366. }}
  1367. ''',
  1368. comment = f'/* Extra wrapper for fz_paint_shade(), passing cache=NULL. */',
  1369. ),
  1370. ],
  1371. ),
  1372. fz_shade_color_cache = ClassExtra(
  1373. ),
  1374. # Our wrappers of the fz_stext_* structs all have a default copy
  1375. # constructor - there are no fz_keep_stext_*() functions.
  1376. #
  1377. # We define explicit accessors for fz_stext_block::u.i.* because SWIG
  1378. # does not handle nested unions.
  1379. #
  1380. fz_stext_block = ClassExtra(
  1381. iterator_next = ('u.t.first_line', 'u.t.last_line'),
  1382. copyable='default',
  1383. methods_extra = [
  1384. ExtraMethod( f'{rename.class_("fz_matrix")}', 'i_transform()',
  1385. f'''
  1386. {{
  1387. if (m_internal->type != FZ_STEXT_BLOCK_IMAGE) {{
  1388. throw std::runtime_error("Not an image");
  1389. }}
  1390. return m_internal->u.i.transform;
  1391. }}
  1392. ''',
  1393. comment=f'/* Returns m_internal.u.i.transform if m_internal->type is FZ_STEXT_BLOCK_IMAGE, else throws. */',
  1394. ),
  1395. ExtraMethod( f'{rename.class_("fz_image")}', 'i_image()',
  1396. f'''
  1397. {{
  1398. if (m_internal->type != FZ_STEXT_BLOCK_IMAGE) {{
  1399. throw std::runtime_error("Not an image");
  1400. }}
  1401. return {rename.class_("fz_image")}({rename.ll_fn('fz_keep_image')}(m_internal->u.i.image));
  1402. }}
  1403. ''',
  1404. comment=f'/* Returns m_internal.u.i.image if m_internal->type is FZ_STEXT_BLOCK_IMAGE, else throws. */',
  1405. ),
  1406. ],
  1407. ),
  1408. fz_stext_char = ClassExtra(
  1409. copyable='default',
  1410. ),
  1411. fz_stext_line = ClassExtra(
  1412. iterator_next = ('first_char', 'last_char'),
  1413. copyable='default',
  1414. constructor_raw=True,
  1415. ),
  1416. fz_stext_options = ClassExtra(
  1417. constructors_extra = [
  1418. ExtraConstructor( '(int flags, float scale=1.0)',
  1419. '''
  1420. :
  1421. flags(flags),
  1422. scale(scale)
  1423. {
  1424. assert(!(flags & FZ_STEXT_CLIP_RECT));
  1425. }
  1426. ''',
  1427. comment = '/* Construct with .flags, .scale but no clip. */',
  1428. ),
  1429. ExtraConstructor( '(int flags, fz_rect clip, float scale=1.0)',
  1430. '''
  1431. :
  1432. flags(flags | FZ_STEXT_CLIP_RECT),
  1433. scale(scale),
  1434. clip(clip)
  1435. {
  1436. }
  1437. ''',
  1438. comment =
  1439. '/* Construct with .flags, .scale and .clip; FZ_STEXT_CLIP_RECT\n'
  1440. 'is automatically set in .flags. */'
  1441. ,
  1442. ),
  1443. ],
  1444. pod='inline',
  1445. ),
  1446. fz_stext_page = ClassExtra(
  1447. methods_extra = [
  1448. ExtraMethod(
  1449. 'std::string',
  1450. f'{rename.method( "fz_stext_page", "fz_copy_selection")}('
  1451. + f'{rename.class_("fz_point")}& a'
  1452. + f', {rename.class_("fz_point")}& b'
  1453. + f', int crlf'
  1454. + f')',
  1455. f'''
  1456. {{
  1457. char* text = {rename.ll_fn('fz_copy_selection')}(m_internal, *(::fz_point *) &a.x, *(::fz_point *) &b.x, crlf);
  1458. std::string ret(text);
  1459. {rename.ll_fn('fz_free')}(text);
  1460. return ret;
  1461. }}
  1462. ''',
  1463. comment = f'/* Wrapper for fz_copy_selection() that returns std::string. */',
  1464. ),
  1465. ExtraMethod(
  1466. 'std::string',
  1467. f'{rename.method( "fz_stext_page", "fz_copy_rectangle")}({rename.class_("fz_rect")}& area, int crlf)',
  1468. f'''
  1469. {{
  1470. char* text = {rename.ll_fn('fz_copy_rectangle')}(m_internal, *(::fz_rect*) &area.x0, crlf);
  1471. std::string ret(text);
  1472. {rename.ll_fn('fz_free')}(text);
  1473. return ret;
  1474. }}
  1475. ''',
  1476. comment = f'/* Wrapper for fz_copy_rectangle() that returns a std::string. */',
  1477. ),
  1478. ExtraMethod(
  1479. f'std::vector<{rename.class_("fz_quad")}>',
  1480. f'{rename.method( "fz_stext_page", "search_stext_page")}(const char* needle, int *hit_mark, int max_quads)',
  1481. f'''
  1482. {{
  1483. std::vector<{rename.class_("fz_quad")}> ret(max_quads);
  1484. int n = {rename.ll_fn('fz_search_stext_page')}(m_internal, needle, hit_mark, ret[0].internal(), max_quads);
  1485. ret.resize(n);
  1486. return ret;
  1487. }}
  1488. ''',
  1489. '/* Wrapper for fz_search_stext_page() that returns std::vector of Quads. */',
  1490. )
  1491. ],
  1492. iterator_next = ('first_block', 'last_block'),
  1493. copyable=False,
  1494. constructor_raw = True,
  1495. ),
  1496. fz_text_span = ClassExtra(
  1497. copyable=False,
  1498. methods_extra = [
  1499. # We provide class-aware accessors where possible. (Some
  1500. # types' wrapper classes are not copyable so we can't do
  1501. # this for all data).
  1502. ExtraMethod(
  1503. f'{rename.class_("fz_font")}',
  1504. f'font()',
  1505. f'''
  1506. {{
  1507. return {rename.class_("fz_font")}( ll_fz_keep_font( m_internal->font));
  1508. }}
  1509. ''',
  1510. f'/* Gives class-aware access to m_internal->font. */',
  1511. ),
  1512. ExtraMethod(
  1513. f'{rename.class_("fz_matrix")}',
  1514. f'trm()',
  1515. f'''
  1516. {{
  1517. return {rename.class_("fz_matrix")}( m_internal->trm);
  1518. }}
  1519. ''',
  1520. f'/* Gives class-aware access to m_internal->trm. */',
  1521. ),
  1522. ExtraMethod(
  1523. f'fz_text_item&',
  1524. f'items( int i)',
  1525. f'''
  1526. {{
  1527. assert( i < m_internal->len);
  1528. return m_internal->items[i];
  1529. }}
  1530. ''',
  1531. '''
  1532. /* Gives access to m_internal->items[i].
  1533. Returned reference is only valid as long as `this`.
  1534. Provided mainly for use by SWIG bindings.
  1535. */
  1536. ''',
  1537. ),
  1538. ],
  1539. ),
  1540. fz_stream = ClassExtra(
  1541. constructor_prefixes = [
  1542. 'fz_open_file',
  1543. 'fz_open_memory',
  1544. ],
  1545. constructors_extra = [
  1546. ExtraConstructor( '(const std::string& filename)',
  1547. f'''
  1548. : m_internal({rename.ll_fn('fz_open_file')}(filename.c_str()))
  1549. {{
  1550. }}
  1551. ''',
  1552. comment = '/* Construct using fz_open_file(). */',
  1553. )
  1554. ],
  1555. ),
  1556. fz_story_element_position = ClassExtra(
  1557. pod='inline',
  1558. ),
  1559. fz_transition = ClassExtra(
  1560. pod='inline',
  1561. constructor_raw = True,
  1562. ),
  1563. pdf_annot = ClassExtra(
  1564. constructor_raw = 'default',
  1565. ),
  1566. pdf_clean_options = ClassExtra(
  1567. constructors_extra = [
  1568. ExtraConstructor( '()',
  1569. f'''
  1570. {{
  1571. /* Use memcpy() otherwise we get 'invalid array assignment' errors. */
  1572. memcpy(&this->internal()->write, &pdf_default_write_options, sizeof(this->internal()->write));
  1573. memset(&this->internal()->image, 0, sizeof(this->internal()->image));
  1574. }}
  1575. ''',
  1576. comment = '/* Default constructor, makes copy of pdf_default_write_options. */'
  1577. ),
  1578. ExtraConstructor(
  1579. f'(const {rename.class_("pdf_clean_options")}& rhs)',
  1580. f'''
  1581. {{
  1582. *this = rhs;
  1583. }}
  1584. ''',
  1585. comment = '/* Copy constructor using raw memcopy(). */'
  1586. ),
  1587. ],
  1588. methods_extra = [
  1589. ExtraMethod(
  1590. f'{rename.class_("pdf_clean_options")}&',
  1591. f'operator=(const {rename.class_("pdf_clean_options")}& rhs)',
  1592. f'''
  1593. {{
  1594. memcpy(this->internal(), rhs.internal(), sizeof(*this->internal()));
  1595. return *this;
  1596. }}
  1597. ''',
  1598. comment = '/* Assignment using plain memcpy(). */',
  1599. ),
  1600. ExtraMethod(
  1601. f'void',
  1602. f'write_opwd_utf8_set(const std::string& text)',
  1603. f'''
  1604. {{
  1605. size_t len = std::min(text.size(), sizeof(write.opwd_utf8) - 1);
  1606. memcpy(write.opwd_utf8, text.c_str(), len);
  1607. write.opwd_utf8[len] = 0;
  1608. }}
  1609. ''',
  1610. '/* Copies <text> into write.opwd_utf8[]. */',
  1611. ),
  1612. ExtraMethod(
  1613. f'void',
  1614. f'write_upwd_utf8_set(const std::string& text)',
  1615. f'''
  1616. {{
  1617. size_t len = std::min(text.size(), sizeof(write.upwd_utf8) - 1);
  1618. memcpy(write.upwd_utf8, text.c_str(), len);
  1619. write.upwd_utf8[len] = 0;
  1620. }}
  1621. ''',
  1622. '/* Copies <text> into upwd_utf8[]. */',
  1623. ),
  1624. ],
  1625. pod = 'inline',
  1626. copyable = 'default',
  1627. ),
  1628. pdf_document = ClassExtra(
  1629. constructor_prefixes = [
  1630. 'pdf_open_document',
  1631. 'pdf_create_document',
  1632. 'pdf_document_from_fz_document',
  1633. ],
  1634. methods_extra = [
  1635. ExtraMethod(
  1636. f'{rename.class_("fz_document")}',
  1637. 'super()',
  1638. f'''
  1639. {{
  1640. return {rename.class_("fz_document")}( {rename.ll_fn('fz_keep_document')}( &m_internal->super));
  1641. }}
  1642. ''',
  1643. f'/* Returns wrapper for .super member. */',
  1644. ),
  1645. ],
  1646. ),
  1647. pdf_filter_factory = ClassExtra(
  1648. pod = 'inline',
  1649. virtual_fnptrs = dict(
  1650. self_ = lambda name: f'({rename.class_("pdf_filter_factory")}2*) {name}',
  1651. self_n = 6,
  1652. alloc = f'this->options = this;\n',
  1653. ),
  1654. ),
  1655. pdf_filter_options = ClassExtra(
  1656. pod = 'inline',
  1657. # We don't need to allocate extra space, and because we are a
  1658. # POD class, we can simply let our default constructor run.
  1659. #
  1660. # this->opaque is passed as arg[2].
  1661. #
  1662. virtual_fnptrs = dict(
  1663. self_ = lambda name: f'({rename.class_("pdf_filter_options")}2*) {name}',
  1664. self_n = 2,
  1665. alloc = f'this->opaque = this;\n',
  1666. ),
  1667. constructors_extra = [
  1668. ExtraConstructor( '()',
  1669. f'''
  1670. {{
  1671. this->recurse = 0;
  1672. this->instance_forms = 0;
  1673. this->ascii = 0;
  1674. this->opaque = nullptr;
  1675. this->complete = nullptr;
  1676. this->filters = nullptr;
  1677. pdf_filter_factory eof = {{ nullptr, nullptr}};
  1678. m_filters.push_back( eof);
  1679. this->newlines = 0;
  1680. }}
  1681. ''',
  1682. comment = '/* Default constructor initialises all fields to null/zero. */',
  1683. )
  1684. ],
  1685. methods_extra = [
  1686. ExtraMethod(
  1687. 'void',
  1688. f'add_factory( const pdf_filter_factory& factory)',
  1689. textwrap.dedent( f'''
  1690. {{
  1691. this->m_filters.back() = factory;
  1692. pdf_filter_factory eof = {{ nullptr, nullptr}};
  1693. this->m_filters.push_back( eof);
  1694. this->filters = &this->m_filters[0];
  1695. }}
  1696. '''),
  1697. comment = f'/* Appends `factory` to internal vector and updates this->filters. */',
  1698. ),
  1699. ],
  1700. class_bottom = textwrap.dedent( f'''
  1701. std::vector< pdf_filter_factory> m_filters;
  1702. '''),
  1703. ),
  1704. pdf_lexbuf = ClassExtra(
  1705. constructors_extra = [
  1706. ExtraConstructor( '(int size)',
  1707. f'''
  1708. {{
  1709. m_internal = new ::pdf_lexbuf;
  1710. {rename.ll_fn('pdf_lexbuf_init')}(m_internal, size);
  1711. }}
  1712. ''',
  1713. comment = '/* Constructor that calls pdf_lexbuf_init(size). */',
  1714. ),
  1715. ],
  1716. methods_extra = [
  1717. ExtraMethod(
  1718. '',
  1719. '~()',
  1720. f'''
  1721. {{
  1722. {rename.ll_fn('pdf_lexbuf_fin')}(m_internal);
  1723. delete m_internal;
  1724. }}
  1725. ''',
  1726. comment = '/* Destructor that calls pdf_lexbuf_fin(). */',
  1727. ),
  1728. ],
  1729. ),
  1730. pdf_layer_config = ClassExtra(
  1731. pod = 'inline',
  1732. ),
  1733. pdf_layer_config_ui = ClassExtra(
  1734. pod = 'inline',
  1735. constructors_extra = [
  1736. ExtraConstructor( '()',
  1737. f'''
  1738. {{
  1739. this->text = nullptr;
  1740. this->depth = 0;
  1741. this->type = PDF_LAYER_UI_LABEL;
  1742. this->selected = 0;
  1743. this->locked = 0;
  1744. }}
  1745. ''',
  1746. comment = '/* Default constructor sets .text to null, .type to PDF_LAYER_UI_LABEL, and other fields to zero. */',
  1747. ),
  1748. ],
  1749. ),
  1750. pdf_obj = ClassExtra(
  1751. constructor_raw = 'default',
  1752. methods_extra = [
  1753. ExtraMethod(
  1754. f'{rename.class_("pdf_obj")}',
  1755. f'{rename.method( "pdf_obj", "pdf_dict_get")}(int key)',
  1756. f'''
  1757. {{
  1758. ::pdf_obj* temp = {rename.ll_fn('pdf_dict_get')}(this->m_internal, (::pdf_obj*)(uintptr_t) key);
  1759. {rename.ll_fn('pdf_keep_obj')}(temp);
  1760. auto ret = {rename.class_('pdf_obj')}(temp);
  1761. return ret;
  1762. }}
  1763. ''',
  1764. comment = '/* Typesafe wrapper for looking up things such as PDF_ENUM_NAME_Annots. */',
  1765. overload=True,
  1766. ),
  1767. ExtraMethod(
  1768. f'std::string',
  1769. f'{rename.method( "pdf_obj", "pdf_load_field_name2")}()',
  1770. f'''
  1771. {{
  1772. return {rename.namespace_fn('pdf_load_field_name2')}( *this);
  1773. }}
  1774. ''',
  1775. comment = f'/* Alternative to `{rename.fn("pdf_load_field_name")}()` that returns a std::string. */',
  1776. ),
  1777. ]
  1778. ),
  1779. pdf_page = ClassExtra(
  1780. methods_extra = [
  1781. ExtraMethod(
  1782. f'{rename.class_("fz_page")}',
  1783. 'super()',
  1784. f'''
  1785. {{
  1786. return {rename.class_("fz_page")}( {rename.ll_fn('fz_keep_page')}( &m_internal->super));
  1787. }}
  1788. ''',
  1789. f'/* Returns wrapper for .super member. */',
  1790. ),
  1791. ExtraMethod(
  1792. f'{rename.class_("pdf_document")}',
  1793. 'doc()',
  1794. f'''
  1795. {{
  1796. return {rename.class_("pdf_document")}( {rename.ll_fn('pdf_keep_document')}( m_internal->doc));
  1797. }}
  1798. ''',
  1799. f'/* Returns wrapper for .doc member. */',
  1800. ),
  1801. ExtraMethod(
  1802. f'{rename.class_("pdf_obj")}',
  1803. 'obj()',
  1804. f'''
  1805. {{
  1806. return {rename.class_("pdf_obj")}( {rename.ll_fn('pdf_keep_obj')}( m_internal->obj));
  1807. }}
  1808. ''',
  1809. f'/* Returns wrapper for .obj member. */',
  1810. ),
  1811. ],
  1812. ),
  1813. pdf_image_rewriter_options = ClassExtra(
  1814. pod = 'inline',
  1815. copyable = 'default',
  1816. ),
  1817. pdf_processor = ClassExtra(
  1818. virtual_fnptrs = dict(
  1819. self_ = lambda name: f'(*({rename.class_("pdf_processor")}2**) ({name} + 1))',
  1820. alloc = textwrap.dedent( f'''
  1821. m_internal = (::pdf_processor*) {rename.ll_fn("pdf_new_processor")}(
  1822. sizeof(*m_internal)
  1823. + sizeof({rename.class_("pdf_processor")}2*)
  1824. );
  1825. *(({rename.class_("pdf_processor")}2**) (m_internal + 1)) = this;
  1826. '''),
  1827. ),
  1828. ),
  1829. pdf_recolor_options = ClassExtra(
  1830. pod = 'inline',
  1831. ),
  1832. pdf_redact_options = ClassExtra(
  1833. pod = 'inline',
  1834. ),
  1835. pdf_sanitize_filter_options = ClassExtra(
  1836. pod = 'inline',
  1837. # this->opaque is passed as arg[1].
  1838. virtual_fnptrs = dict(
  1839. self_ = lambda name: f'({rename.class_("pdf_sanitize_filter_options")}2*) {name}',
  1840. alloc = f'this->opaque = this;\n',
  1841. ),
  1842. ),
  1843. pdf_write_options = ClassExtra(
  1844. constructors_extra = [
  1845. ExtraConstructor( '()',
  1846. f'''
  1847. {{
  1848. /* Use memcpy() otherwise we get 'invalid array assignment' errors. */
  1849. memcpy(this->internal(), &pdf_default_write_options, sizeof(*this->internal()));
  1850. }}
  1851. ''',
  1852. comment = '/* Default constructor, makes copy of pdf_default_write_options. */'
  1853. ),
  1854. ExtraConstructor(
  1855. f'(const {rename.class_("pdf_write_options")}& rhs)',
  1856. f'''
  1857. {{
  1858. *this = rhs;
  1859. }}
  1860. ''',
  1861. comment = '/* Copy constructor using raw memcopy(). */'
  1862. ),
  1863. ],
  1864. methods_extra = [
  1865. ExtraMethod(
  1866. f'{rename.class_("pdf_write_options")}&',
  1867. f'operator=(const {rename.class_("pdf_write_options")}& rhs)',
  1868. f'''
  1869. {{
  1870. memcpy(this->internal(), rhs.internal(), sizeof(*this->internal()));
  1871. return *this;
  1872. }}
  1873. ''',
  1874. comment = '/* Assignment using plain memcpy(). */',
  1875. ),
  1876. ExtraMethod(
  1877. # Would prefer to call this opwd_utf8_set() but
  1878. # this conflicts with SWIG-generated accessor for
  1879. # opwd_utf8.
  1880. f'void',
  1881. f'opwd_utf8_set_value(const std::string& text)',
  1882. f'''
  1883. {{
  1884. size_t len = std::min(text.size(), sizeof(opwd_utf8) - 1);
  1885. memcpy(opwd_utf8, text.c_str(), len);
  1886. opwd_utf8[len] = 0;
  1887. }}
  1888. ''',
  1889. '/* Copies <text> into opwd_utf8[]. */',
  1890. ),
  1891. ExtraMethod(
  1892. f'void',
  1893. f'upwd_utf8_set_value(const std::string& text)',
  1894. f'''
  1895. {{
  1896. size_t len = std::min(text.size(), sizeof(upwd_utf8) - 1);
  1897. memcpy(upwd_utf8, text.c_str(), len);
  1898. upwd_utf8[len] = 0;
  1899. }}
  1900. ''',
  1901. '/* Copies <text> into upwd_utf8[]. */',
  1902. ),
  1903. ],
  1904. pod = 'inline',
  1905. copyable = 'default',
  1906. )
  1907. )