mathematical 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -10
  3. data/Rakefile +42 -3
  4. data/lib/mathematical.rb +5 -4
  5. data/lib/mathematical/mathematical.bundle +0 -0
  6. data/lib/mathematical/render.rb +6 -5
  7. data/lib/mathematical/version.rb +1 -1
  8. data/mathematical.gemspec +5 -5
  9. metadata +14 -296
  10. data/.gitignore +0 -24
  11. data/.gitmodules +0 -0
  12. data/Gemfile +0 -4
  13. data/ext/mathematical/README.itex2MML.md +0 -11
  14. data/ext/mathematical/README.lasem.md +0 -11
  15. data/ext/mathematical/extconf.rb +0 -51
  16. data/ext/mathematical/itex2MML.h +0 -63
  17. data/ext/mathematical/lasemrender.c +0 -257
  18. data/ext/mathematical/lex.yy.c +0 -6548
  19. data/ext/mathematical/lsm.c +0 -30
  20. data/ext/mathematical/lsm.h +0 -36
  21. data/ext/mathematical/lsmattributes.c +0 -279
  22. data/ext/mathematical/lsmattributes.h +0 -75
  23. data/ext/mathematical/lsmcairo.c +0 -598
  24. data/ext/mathematical/lsmcairo.h +0 -51
  25. data/ext/mathematical/lsmdebug.c +0 -179
  26. data/ext/mathematical/lsmdebug.h +0 -76
  27. data/ext/mathematical/lsmdom.h +0 -43
  28. data/ext/mathematical/lsmdomcharacterdata.c +0 -114
  29. data/ext/mathematical/lsmdomcharacterdata.h +0 -59
  30. data/ext/mathematical/lsmdomdocument.c +0 -292
  31. data/ext/mathematical/lsmdomdocument.h +0 -82
  32. data/ext/mathematical/lsmdomdocumentfragment.c +0 -81
  33. data/ext/mathematical/lsmdomdocumentfragment.h +0 -55
  34. data/ext/mathematical/lsmdomelement.c +0 -148
  35. data/ext/mathematical/lsmdomelement.h +0 -62
  36. data/ext/mathematical/lsmdomentities.c +0 -2155
  37. data/ext/mathematical/lsmdomentities.h +0 -35
  38. data/ext/mathematical/lsmdomenumtypes.c +0 -99
  39. data/ext/mathematical/lsmdomenumtypes.c.template +0 -39
  40. data/ext/mathematical/lsmdomenumtypes.h +0 -26
  41. data/ext/mathematical/lsmdomenumtypes.h.template +0 -26
  42. data/ext/mathematical/lsmdomimplementation.c +0 -82
  43. data/ext/mathematical/lsmdomimplementation.h +0 -41
  44. data/ext/mathematical/lsmdomnamednodemap.c +0 -118
  45. data/ext/mathematical/lsmdomnamednodemap.h +0 -64
  46. data/ext/mathematical/lsmdomnode.c +0 -725
  47. data/ext/mathematical/lsmdomnode.h +0 -120
  48. data/ext/mathematical/lsmdomnodelist.c +0 -70
  49. data/ext/mathematical/lsmdomnodelist.h +0 -58
  50. data/ext/mathematical/lsmdomparser.c +0 -461
  51. data/ext/mathematical/lsmdomparser.h +0 -54
  52. data/ext/mathematical/lsmdomtext.c +0 -82
  53. data/ext/mathematical/lsmdomtext.h +0 -55
  54. data/ext/mathematical/lsmdomtypes.h +0 -44
  55. data/ext/mathematical/lsmdomview.c +0 -422
  56. data/ext/mathematical/lsmdomview.h +0 -94
  57. data/ext/mathematical/lsmmathml.h +0 -66
  58. data/ext/mathematical/lsmmathmlactionelement.c +0 -93
  59. data/ext/mathematical/lsmmathmlactionelement.h +0 -57
  60. data/ext/mathematical/lsmmathmlaligngroupelement.c +0 -102
  61. data/ext/mathematical/lsmmathmlaligngroupelement.h +0 -56
  62. data/ext/mathematical/lsmmathmlalignmarkelement.c +0 -102
  63. data/ext/mathematical/lsmmathmlalignmarkelement.h +0 -56
  64. data/ext/mathematical/lsmmathmlattributes.c +0 -197
  65. data/ext/mathematical/lsmmathmlattributes.h +0 -126
  66. data/ext/mathematical/lsmmathmldocument.c +0 -306
  67. data/ext/mathematical/lsmmathmldocument.h +0 -61
  68. data/ext/mathematical/lsmmathmlelement.c +0 -491
  69. data/ext/mathematical/lsmmathmlelement.h +0 -107
  70. data/ext/mathematical/lsmmathmlenums.c +0 -429
  71. data/ext/mathematical/lsmmathmlenums.h +0 -182
  72. data/ext/mathematical/lsmmathmlenumtypes.c +0 -666
  73. data/ext/mathematical/lsmmathmlenumtypes.c.template +0 -39
  74. data/ext/mathematical/lsmmathmlenumtypes.h +0 -90
  75. data/ext/mathematical/lsmmathmlenumtypes.h.template +0 -26
  76. data/ext/mathematical/lsmmathmlerrorelement.c +0 -58
  77. data/ext/mathematical/lsmmathmlerrorelement.h +0 -56
  78. data/ext/mathematical/lsmmathmlfencedelement.c +0 -178
  79. data/ext/mathematical/lsmmathmlfencedelement.h +0 -65
  80. data/ext/mathematical/lsmmathmlfractionelement.c +0 -253
  81. data/ext/mathematical/lsmmathmlfractionelement.h +0 -62
  82. data/ext/mathematical/lsmmathmlglyphtableams.c +0 -597
  83. data/ext/mathematical/lsmmathmlglyphtableams.h +0 -45
  84. data/ext/mathematical/lsmmathmlitexelement.c +0 -187
  85. data/ext/mathematical/lsmmathmlitexelement.h +0 -60
  86. data/ext/mathematical/lsmmathmllayoututils.c +0 -191
  87. data/ext/mathematical/lsmmathmllayoututils.h +0 -58
  88. data/ext/mathematical/lsmmathmlmathelement.c +0 -204
  89. data/ext/mathematical/lsmmathmlmathelement.h +0 -81
  90. data/ext/mathematical/lsmmathmloperatordictionary.c +0 -3332
  91. data/ext/mathematical/lsmmathmloperatordictionary.h +0 -54
  92. data/ext/mathematical/lsmmathmloperatorelement.c +0 -307
  93. data/ext/mathematical/lsmmathmloperatorelement.h +0 -73
  94. data/ext/mathematical/lsmmathmlpaddedelement.c +0 -58
  95. data/ext/mathematical/lsmmathmlpaddedelement.h +0 -56
  96. data/ext/mathematical/lsmmathmlphantomelement.c +0 -71
  97. data/ext/mathematical/lsmmathmlphantomelement.h +0 -56
  98. data/ext/mathematical/lsmmathmlpresentationcontainer.c +0 -43
  99. data/ext/mathematical/lsmmathmlpresentationcontainer.h +0 -54
  100. data/ext/mathematical/lsmmathmlpresentationtoken.c +0 -303
  101. data/ext/mathematical/lsmmathmlpresentationtoken.h +0 -83
  102. data/ext/mathematical/lsmmathmlradicalelement.c +0 -266
  103. data/ext/mathematical/lsmmathmlradicalelement.h +0 -71
  104. data/ext/mathematical/lsmmathmlrowelement.c +0 -58
  105. data/ext/mathematical/lsmmathmlrowelement.h +0 -56
  106. data/ext/mathematical/lsmmathmlscriptelement.c +0 -282
  107. data/ext/mathematical/lsmmathmlscriptelement.h +0 -78
  108. data/ext/mathematical/lsmmathmlsemanticselement.c +0 -82
  109. data/ext/mathematical/lsmmathmlsemanticselement.h +0 -56
  110. data/ext/mathematical/lsmmathmlspaceelement.c +0 -142
  111. data/ext/mathematical/lsmmathmlspaceelement.h +0 -60
  112. data/ext/mathematical/lsmmathmlstringelement.c +0 -123
  113. data/ext/mathematical/lsmmathmlstringelement.h +0 -58
  114. data/ext/mathematical/lsmmathmlstyle.c +0 -130
  115. data/ext/mathematical/lsmmathmlstyle.h +0 -81
  116. data/ext/mathematical/lsmmathmlstyleelement.c +0 -307
  117. data/ext/mathematical/lsmmathmlstyleelement.h +0 -87
  118. data/ext/mathematical/lsmmathmltablecellelement.c +0 -122
  119. data/ext/mathematical/lsmmathmltablecellelement.h +0 -62
  120. data/ext/mathematical/lsmmathmltableelement.c +0 -545
  121. data/ext/mathematical/lsmmathmltableelement.h +0 -78
  122. data/ext/mathematical/lsmmathmltablerowelement.c +0 -120
  123. data/ext/mathematical/lsmmathmltablerowelement.h +0 -64
  124. data/ext/mathematical/lsmmathmltraits.c +0 -819
  125. data/ext/mathematical/lsmmathmltraits.h +0 -119
  126. data/ext/mathematical/lsmmathmltypes.h +0 -66
  127. data/ext/mathematical/lsmmathmlunderoverelement.c +0 -485
  128. data/ext/mathematical/lsmmathmlunderoverelement.h +0 -82
  129. data/ext/mathematical/lsmmathmlutils.c +0 -170
  130. data/ext/mathematical/lsmmathmlutils.h +0 -50
  131. data/ext/mathematical/lsmmathmlview.c +0 -1048
  132. data/ext/mathematical/lsmmathmlview.h +0 -164
  133. data/ext/mathematical/lsmproperties.c +0 -418
  134. data/ext/mathematical/lsmproperties.h +0 -85
  135. data/ext/mathematical/lsmstr.c +0 -231
  136. data/ext/mathematical/lsmstr.h +0 -114
  137. data/ext/mathematical/lsmsvg.h +0 -67
  138. data/ext/mathematical/lsmsvgaelement.c +0 -73
  139. data/ext/mathematical/lsmsvgaelement.h +0 -55
  140. data/ext/mathematical/lsmsvgattributes.h +0 -113
  141. data/ext/mathematical/lsmsvgcircleelement.c +0 -153
  142. data/ext/mathematical/lsmsvgcircleelement.h +0 -59
  143. data/ext/mathematical/lsmsvgclippathelement.c +0 -134
  144. data/ext/mathematical/lsmsvgclippathelement.h +0 -59
  145. data/ext/mathematical/lsmsvgcolors.c +0 -212
  146. data/ext/mathematical/lsmsvgcolors.h +0 -39
  147. data/ext/mathematical/lsmsvgdefselement.c +0 -74
  148. data/ext/mathematical/lsmsvgdefselement.h +0 -55
  149. data/ext/mathematical/lsmsvgdocument.c +0 -230
  150. data/ext/mathematical/lsmsvgdocument.h +0 -58
  151. data/ext/mathematical/lsmsvgelement.c +0 -367
  152. data/ext/mathematical/lsmsvgelement.h +0 -81
  153. data/ext/mathematical/lsmsvgellipseelement.c +0 -158
  154. data/ext/mathematical/lsmsvgellipseelement.h +0 -60
  155. data/ext/mathematical/lsmsvgenums.c +0 -544
  156. data/ext/mathematical/lsmsvgenums.h +0 -357
  157. data/ext/mathematical/lsmsvgenumtypes.c +0 -1083
  158. data/ext/mathematical/lsmsvgenumtypes.c.template +0 -39
  159. data/ext/mathematical/lsmsvgenumtypes.h +0 -111
  160. data/ext/mathematical/lsmsvgenumtypes.h.template +0 -26
  161. data/ext/mathematical/lsmsvgfilterblend.c +0 -105
  162. data/ext/mathematical/lsmsvgfilterblend.h +0 -58
  163. data/ext/mathematical/lsmsvgfiltercomposite.c +0 -109
  164. data/ext/mathematical/lsmsvgfiltercomposite.h +0 -58
  165. data/ext/mathematical/lsmsvgfilterelement.c +0 -266
  166. data/ext/mathematical/lsmsvgfilterelement.h +0 -66
  167. data/ext/mathematical/lsmsvgfilterflood.c +0 -86
  168. data/ext/mathematical/lsmsvgfilterflood.h +0 -55
  169. data/ext/mathematical/lsmsvgfiltergaussianblur.c +0 -114
  170. data/ext/mathematical/lsmsvgfiltergaussianblur.h +0 -57
  171. data/ext/mathematical/lsmsvgfiltermerge.c +0 -98
  172. data/ext/mathematical/lsmsvgfiltermerge.h +0 -55
  173. data/ext/mathematical/lsmsvgfiltermergenode.c +0 -87
  174. data/ext/mathematical/lsmsvgfiltermergenode.h +0 -57
  175. data/ext/mathematical/lsmsvgfilteroffset.c +0 -112
  176. data/ext/mathematical/lsmsvgfilteroffset.h +0 -58
  177. data/ext/mathematical/lsmsvgfilterprimitive.c +0 -168
  178. data/ext/mathematical/lsmsvgfilterprimitive.h +0 -66
  179. data/ext/mathematical/lsmsvgfilterspecularlighting.c +0 -127
  180. data/ext/mathematical/lsmsvgfilterspecularlighting.h +0 -60
  181. data/ext/mathematical/lsmsvgfiltersurface.c +0 -455
  182. data/ext/mathematical/lsmsvgfiltersurface.h +0 -66
  183. data/ext/mathematical/lsmsvgfiltertile.c +0 -102
  184. data/ext/mathematical/lsmsvgfiltertile.h +0 -57
  185. data/ext/mathematical/lsmsvggelement.c +0 -73
  186. data/ext/mathematical/lsmsvggelement.h +0 -55
  187. data/ext/mathematical/lsmsvggradientelement.c +0 -151
  188. data/ext/mathematical/lsmsvggradientelement.h +0 -68
  189. data/ext/mathematical/lsmsvgimageelement.c +0 -261
  190. data/ext/mathematical/lsmsvgimageelement.h +0 -67
  191. data/ext/mathematical/lsmsvglength.c +0 -93
  192. data/ext/mathematical/lsmsvglength.h +0 -59
  193. data/ext/mathematical/lsmsvglineargradientelement.c +0 -271
  194. data/ext/mathematical/lsmsvglineargradientelement.h +0 -60
  195. data/ext/mathematical/lsmsvglineelement.c +0 -153
  196. data/ext/mathematical/lsmsvglineelement.h +0 -60
  197. data/ext/mathematical/lsmsvgmarkerelement.c +0 -266
  198. data/ext/mathematical/lsmsvgmarkerelement.h +0 -74
  199. data/ext/mathematical/lsmsvgmaskelement.c +0 -232
  200. data/ext/mathematical/lsmsvgmaskelement.h +0 -64
  201. data/ext/mathematical/lsmsvgmatrix.c +0 -205
  202. data/ext/mathematical/lsmsvgmatrix.h +0 -59
  203. data/ext/mathematical/lsmsvgpathelement.c +0 -115
  204. data/ext/mathematical/lsmsvgpathelement.h +0 -59
  205. data/ext/mathematical/lsmsvgpatternelement.c +0 -398
  206. data/ext/mathematical/lsmsvgpatternelement.h +0 -69
  207. data/ext/mathematical/lsmsvgpolygonelement.c +0 -106
  208. data/ext/mathematical/lsmsvgpolygonelement.h +0 -57
  209. data/ext/mathematical/lsmsvgpolylineelement.c +0 -106
  210. data/ext/mathematical/lsmsvgpolylineelement.h +0 -57
  211. data/ext/mathematical/lsmsvgradialgradientelement.c +0 -323
  212. data/ext/mathematical/lsmsvgradialgradientelement.h +0 -61
  213. data/ext/mathematical/lsmsvgrectelement.c +0 -184
  214. data/ext/mathematical/lsmsvgrectelement.h +0 -62
  215. data/ext/mathematical/lsmsvgstopelement.c +0 -106
  216. data/ext/mathematical/lsmsvgstopelement.h +0 -57
  217. data/ext/mathematical/lsmsvgstyle.c +0 -558
  218. data/ext/mathematical/lsmsvgstyle.h +0 -217
  219. data/ext/mathematical/lsmsvgsvgelement.c +0 -260
  220. data/ext/mathematical/lsmsvgsvgelement.h +0 -71
  221. data/ext/mathematical/lsmsvgswitchelement.c +0 -103
  222. data/ext/mathematical/lsmsvgswitchelement.h +0 -55
  223. data/ext/mathematical/lsmsvgsymbolelement.c +0 -74
  224. data/ext/mathematical/lsmsvgsymbolelement.h +0 -55
  225. data/ext/mathematical/lsmsvgtextelement.c +0 -170
  226. data/ext/mathematical/lsmsvgtextelement.h +0 -58
  227. data/ext/mathematical/lsmsvgtraits.c +0 -1158
  228. data/ext/mathematical/lsmsvgtraits.h +0 -103
  229. data/ext/mathematical/lsmsvgtransformable.c +0 -106
  230. data/ext/mathematical/lsmsvgtransformable.h +0 -54
  231. data/ext/mathematical/lsmsvgtspanelement.c +0 -143
  232. data/ext/mathematical/lsmsvgtspanelement.h +0 -58
  233. data/ext/mathematical/lsmsvgtypes.h +0 -77
  234. data/ext/mathematical/lsmsvguseelement.c +0 -237
  235. data/ext/mathematical/lsmsvguseelement.h +0 -69
  236. data/ext/mathematical/lsmsvgview.c +0 -2400
  237. data/ext/mathematical/lsmsvgview.h +0 -168
  238. data/ext/mathematical/lsmtraits.c +0 -119
  239. data/ext/mathematical/lsmtraits.h +0 -49
  240. data/ext/mathematical/lsmtypes.h +0 -36
  241. data/ext/mathematical/lsmutils.c +0 -54
  242. data/ext/mathematical/lsmutils.h +0 -56
  243. data/ext/mathematical/mathematical.c +0 -122
  244. data/ext/mathematical/y.tab.c +0 -6179
  245. data/ext/mathematical/y.tab.h +0 -389
  246. data/script/bench +0 -21
  247. data/script/bootstrap +0 -9
  248. data/script/single_test +0 -7
  249. data/test/mathematical/basic_test.rb +0 -38
  250. data/test/mathematical/fixtures/after/brackets_display.html +0 -1
  251. data/test/mathematical/fixtures/after/dollar_sign_inline.html +0 -1
  252. data/test/mathematical/fixtures/after/equation_display.html +0 -1
  253. data/test/mathematical/fixtures/after/multiple_dollar_inline.html +0 -1
  254. data/test/mathematical/fixtures/after/parens_inline.html +0 -1
  255. data/test/mathematical/fixtures/before/brackets_display.text +0 -1
  256. data/test/mathematical/fixtures/before/dollar_sign_inline.text +0 -1
  257. data/test/mathematical/fixtures/before/equation_display.text +0 -1
  258. data/test/mathematical/fixtures/before/multiple_dollar_inline.text +0 -1
  259. data/test/mathematical/fixtures/before/parens_inline.text +0 -1
  260. data/test/mathematical/fixtures/performance/big_file.text +0 -1767
  261. data/test/mathematical/fixtures_test.rb +0 -31
  262. data/test/mathematical/performance_test.rb +0 -13
  263. data/test/test_helper.rb +0 -4
@@ -1,77 +0,0 @@
1
- /* Lasem - SVG and Mathml library
2
- *
3
- * Copyright © 2010 Emmanuel Pacaud
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General
16
- * Public License along with this library; if not, write to the
17
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
- * Boston, MA 02111-1307, USA.
19
- *
20
- * Author:
21
- * Emmanuel Pacaud <emmanuel@gnome.org>
22
- */
23
-
24
- #ifndef LSM_SVG_TYPES_H
25
- #define LSM_SVG_TYPES_H
26
-
27
- #include <lsmsvgenums.h>
28
-
29
- G_BEGIN_DECLS
30
-
31
- typedef struct _LsmSvgDocument LsmSvgDocument;
32
- typedef struct _LsmSvgElement LsmSvgElement;
33
- typedef struct _LsmSvgTransformable LsmSvgTransformable;
34
- typedef struct _LsmSvgGraphic LsmSvgGraphic;
35
- typedef struct _LsmSvgClipPathElement LsmSvgClipPathElement;
36
- typedef struct _LsmSvgSvgElement LsmSvgSvgElement;
37
- typedef struct _LsmSvgAElement LsmSvgAElement;
38
- typedef struct _LsmSvgGElement LsmSvgGElement;
39
- typedef struct _LsmSvgDefsElement LsmSvgDefsElement;
40
- typedef struct _LsmSvgUseElement LsmSvgUseElement;
41
- typedef struct _LsmSvgImageElement LsmSvgImageElement;
42
- typedef struct _LsmSvgSymbolElement LsmSvgSymbolElement;
43
- typedef struct _LsmSvgMarkerElement LsmSvgMarkerElement;
44
- typedef struct _LsmSvgRectElement LsmSvgRectElement;
45
- typedef struct _LsmSvgCircleElement LsmSvgCircleElement;
46
- typedef struct _LsmSvgEllipseElement LsmSvgEllipseElement;
47
- typedef struct _LsmSvgFilterElement LsmSvgFilterElement;
48
- typedef struct _LsmSvgFilterPrimitive LsmSvgFilterPrimitive;
49
- typedef struct _LsmSvgFilterBlend LsmSvgFilterBlend;
50
- typedef struct _LsmSvgFilterComposite LsmSvgFilterComposite;
51
- typedef struct _LsmSvgFilterFlood LsmSvgFilterFlood;
52
- typedef struct _LsmSvgFilterGaussianBlur LsmSvgFilterGaussianBlur;
53
- typedef struct _LsmSvgFilterMerge LsmSvgFilterMerge;
54
- typedef struct _LsmSvgFilterMergeNode LsmSvgFilterMergeNode;
55
- typedef struct _LsmSvgFilterOffset LsmSvgFilterOffset;
56
- typedef struct _LsmSvgFilterSpecularLighting LsmSvgFilterSpecularLighting;
57
- typedef struct _LsmSvgFilterTile LsmSvgFilterTile;
58
- typedef struct _LsmSvgLineElement LsmSvgLineElement;
59
- typedef struct _LsmSvgPolylineElement LsmSvgPolylineElement;
60
- typedef struct _LsmSvgPolygonElement LsmSvgPolygonElement;
61
- typedef struct _LsmSvgPathElement LsmSvgPathElement;
62
- typedef struct _LsmSvgTextElement LsmSvgTextElement;
63
- typedef struct _LsmSvgTspanElement LsmSvgTspanElement;
64
- typedef struct _LsmSvgGradientElement LsmSvgGradientElement;
65
- typedef struct _LsmSvgLinearGradientElement LsmSvgLinearGradientElement;
66
- typedef struct _LsmSvgRadialGradientElement LsmSvgRadialGradientElement;
67
- typedef struct _LsmSvgStopElement LsmSvgStopElement;
68
- typedef struct _LsmSvgSwitchElement LsmSvgSwitchElement;
69
- typedef struct _LsmSvgPatternElement LsmSvgPatternElement;
70
- typedef struct _LsmSvgMaskElement LsmSvgMaskElement;
71
-
72
- typedef struct _LsmSvgView LsmSvgView;
73
- typedef struct _LsmSvgStyle LsmSvgStyle;
74
-
75
- G_END_DECLS
76
-
77
- #endif
@@ -1,237 +0,0 @@
1
- /* Lasem
2
- *
3
- * Copyright © 2009 Emmanuel Pacaud
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General
16
- * Public License along with this library; if not, write to the
17
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
- * Boston, MA 02111-1307, USA.
19
- *
20
- * Author:
21
- * Emmanuel Pacaud <emmanuel@gnome.org>
22
- */
23
-
24
- #include <lsmsvguseelement.h>
25
- #include <lsmsvgview.h>
26
- #include <lsmdebug.h>
27
- #include <lsmdomdocument.h>
28
- #include <stdio.h>
29
-
30
- static GObjectClass *parent_class;
31
-
32
- /* GdomNode implementation */
33
-
34
- static const char *
35
- lsm_svg_use_element_get_node_name (LsmDomNode *node)
36
- {
37
- return "use";
38
- }
39
-
40
- static gboolean
41
- lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
42
- {
43
- return FALSE;
44
- }
45
-
46
- /* LsmSvgElement implementation */
47
-
48
- /* LsmSvgGraphic implementation */
49
-
50
- static LsmDomElement *
51
- _get_used_element (LsmSvgUseElement *use_element)
52
- {
53
- LsmDomDocument *document;
54
- LsmDomElement *element;
55
- const char *id;
56
-
57
- document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (use_element));
58
- if (document == NULL) {
59
- lsm_debug_dom ("[LsmSvgUseElement::_get_used_element] Owner document not found");
60
- return NULL;
61
- }
62
-
63
- id = use_element->href.value;
64
- if (id == NULL)
65
- return NULL;
66
-
67
- if (*id == '#')
68
- id++;
69
-
70
- element = lsm_dom_document_get_element_by_id (document, id);
71
- if (!LSM_IS_SVG_ELEMENT (element)) {
72
- lsm_debug_dom ("[LsmSvgUseElement::_get_used_element] Target '%s' not found", id);
73
- return NULL;
74
- }
75
-
76
- return element;
77
- }
78
-
79
- static void
80
- lsm_svg_use_element_render (LsmSvgElement *self, LsmSvgView *view)
81
- {
82
- LsmSvgUseElement *use_element = LSM_SVG_USE_ELEMENT (self);
83
- LsmDomElement *element;
84
- LsmSvgMatrix matrix;
85
- double x, y;
86
-
87
- if (use_element->flags & LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_RENDER) {
88
- lsm_debug_render ("[LsmSvgUseElement::render] Circular reference");
89
- return;
90
- }
91
-
92
- element = _get_used_element (use_element);
93
- if (element == NULL)
94
- return;
95
-
96
- use_element->flags |= LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_RENDER;
97
-
98
- x = lsm_svg_view_normalize_length (view, &use_element->x.length,
99
- LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
100
- y = lsm_svg_view_normalize_length (view, &use_element->y.length,
101
- LSM_SVG_LENGTH_DIRECTION_VERTICAL);
102
-
103
- lsm_svg_matrix_init_translate (&matrix, x, y);
104
-
105
- if (lsm_svg_view_push_matrix (view, &matrix))
106
- lsm_svg_element_render (LSM_SVG_ELEMENT (element), view);
107
-
108
- lsm_svg_view_pop_matrix (view);
109
-
110
- use_element->flags &= ~LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_RENDER;
111
- }
112
-
113
- static void
114
- lsm_svg_use_element_get_extents (LsmSvgElement *self, LsmSvgView *view, LsmExtents *extents)
115
- {
116
- LsmSvgUseElement *use_element = LSM_SVG_USE_ELEMENT (self);
117
- LsmDomElement *element;
118
- LsmSvgMatrix matrix;
119
- double x, y;
120
-
121
- if (use_element->flags & LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_GET_EXTENTS) {
122
- lsm_debug_render ("[LsmSvgUseElement::get_extents] Circular reference");
123
- extents->x1 = 0;
124
- extents->y1 = 0;
125
- extents->x2 = 0;
126
- extents->y2 = 0;
127
- return;
128
- }
129
-
130
- element = _get_used_element (use_element);
131
- if (element == NULL) {
132
- extents->x1 = 0;
133
- extents->y1 = 0;
134
- extents->x2 = 0;
135
- extents->y2 = 0;
136
- return;
137
- }
138
-
139
- use_element->flags |= LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_GET_EXTENTS;
140
-
141
- x = lsm_svg_view_normalize_length (view, &use_element->x.length,
142
- LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
143
- y = lsm_svg_view_normalize_length (view, &use_element->y.length,
144
- LSM_SVG_LENGTH_DIRECTION_VERTICAL);
145
-
146
- lsm_svg_element_transformed_get_extents (LSM_SVG_ELEMENT (element), view, extents);
147
-
148
- lsm_svg_matrix_init_translate (&matrix, x, y);
149
-
150
- if (lsm_svg_view_push_matrix (view, &matrix))
151
- lsm_svg_matrix_transform_bounding_box (&matrix,
152
- &extents->x1, &extents->y1,
153
- &extents->x2, &extents->y2);
154
- lsm_svg_view_pop_matrix (view);
155
-
156
- use_element->flags &= ~LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_GET_EXTENTS;
157
- }
158
-
159
- /* LsmSvgUseElement implementation */
160
-
161
- LsmDomNode *
162
- lsm_svg_use_element_new (void)
163
- {
164
- return g_object_new (LSM_TYPE_SVG_USE_ELEMENT, NULL);
165
- }
166
-
167
- static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
168
-
169
- static void
170
- lsm_svg_use_element_init (LsmSvgUseElement *self)
171
- {
172
- self->x.length = length_default;
173
- self->y.length = length_default;
174
- self->width.length = length_default;
175
- self->height.length = length_default;
176
- }
177
-
178
- /* LsmSvgUseElement class */
179
-
180
- static const LsmAttributeInfos lsm_svg_use_element_attribute_infos[] = {
181
- {
182
- .name = "x",
183
- .attribute_offset = offsetof (LsmSvgUseElement, x),
184
- .trait_class = &lsm_svg_length_trait_class,
185
- .trait_default = &length_default
186
- },
187
- {
188
- .name = "y",
189
- .attribute_offset = offsetof (LsmSvgUseElement, y),
190
- .trait_class = &lsm_svg_length_trait_class,
191
- .trait_default = &length_default
192
- },
193
- {
194
- .name = "width",
195
- .attribute_offset = offsetof (LsmSvgUseElement, width),
196
- .trait_class = &lsm_svg_length_trait_class,
197
- .trait_default = &length_default
198
- },
199
- {
200
- .name = "height",
201
- .attribute_offset = offsetof (LsmSvgUseElement, height),
202
- .trait_class = &lsm_svg_length_trait_class,
203
- .trait_default = &length_default
204
- },
205
- {
206
- .name = "xlink:href",
207
- .attribute_offset = offsetof (LsmSvgUseElement, href),
208
- .trait_class = &lsm_null_trait_class
209
- }
210
- };
211
-
212
- static void
213
- lsm_svg_use_element_class_init (LsmSvgUseElementClass *klass)
214
- {
215
- LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
216
- LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
217
-
218
- parent_class = g_type_class_peek_parent (klass);
219
-
220
- d_node_class->get_node_name = lsm_svg_use_element_get_node_name;
221
- d_node_class->can_append_child = lsm_svg_use_can_append_child;
222
-
223
- s_element_class->category =
224
- LSM_SVG_ELEMENT_CATEGORY_GRAPHICS |
225
- LSM_SVG_ELEMENT_CATEGORY_GRAPHICS_REFERENCING |
226
- LSM_SVG_ELEMENT_CATEGORY_STRUCTURAL;
227
-
228
- s_element_class->render = lsm_svg_use_element_render;
229
- s_element_class->get_extents = lsm_svg_use_element_get_extents;
230
- s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
231
-
232
- lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
233
- G_N_ELEMENTS (lsm_svg_use_element_attribute_infos),
234
- lsm_svg_use_element_attribute_infos);
235
- }
236
-
237
- G_DEFINE_TYPE (LsmSvgUseElement, lsm_svg_use_element, LSM_TYPE_SVG_TRANSFORMABLE)
@@ -1,69 +0,0 @@
1
- /* Lasem
2
- *
3
- * Copyright © 2009-2012 Emmanuel Pacaud
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General
16
- * Public License along with this library; if not, write to the
17
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
- * Boston, MA 02111-1307, USA.
19
- *
20
- * Author:
21
- * Emmanuel Pacaud <emmanuel@gnome.org>
22
- */
23
-
24
- #ifndef LSM_SVG_USE_ELEMENT_H
25
- #define LSM_SVG_USE_ELEMENT_H
26
-
27
- #include <lsmsvgtypes.h>
28
- #include <lsmsvgtransformable.h>
29
-
30
- G_BEGIN_DECLS
31
-
32
- typedef enum {
33
- LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_RENDER = 1 << 0,
34
- LSM_SVG_USE_ELEMENT_FLAGS_IN_USE_FOR_GET_EXTENTS = 1 << 1
35
- } LsmSvgUseElementFlags;
36
-
37
- #define LSM_TYPE_SVG_USE_ELEMENT (lsm_svg_use_element_get_type ())
38
- #define LSM_SVG_USE_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LSM_TYPE_SVG_USE_ELEMENT, LsmSvgUseElement))
39
- #define LSM_SVG_USE_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LSM_TYPE_SVG_USE_ELEMENT, LsmSvgUseElementClass))
40
- #define LSM_IS_SVG_USE_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LSM_TYPE_SVG_USE_ELEMENT))
41
- #define LSM_IS_SVG_USE_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LSM_TYPE_SVG_USE_ELEMENT))
42
- #define LSM_SVG_USE_ELEMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LSM_TYPE_SVG_USE_ELEMENT, LsmSvgUseElementClass))
43
-
44
- typedef struct _LsmSvgUseElementClass LsmSvgUseElementClass;
45
-
46
- struct _LsmSvgUseElement {
47
- LsmSvgTransformable base;
48
-
49
- LsmSvgLengthAttribute x;
50
- LsmSvgLengthAttribute y;
51
- LsmSvgLengthAttribute width;
52
- LsmSvgLengthAttribute height;
53
-
54
- LsmAttribute href;
55
-
56
- LsmSvgUseElementFlags flags;
57
- };
58
-
59
- struct _LsmSvgUseElementClass {
60
- LsmSvgTransformableClass base_class;
61
- };
62
-
63
- GType lsm_svg_use_element_get_type (void);
64
-
65
- LsmDomNode * lsm_svg_use_element_new (void);
66
-
67
- G_END_DECLS
68
-
69
- #endif
@@ -1,2400 +0,0 @@
1
- /* Lasem
2
- *
3
- * Copyright © 2009 Emmanuel Pacaud
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General
16
- * Public License along with this library; if not, write to the
17
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18
- * Boston, MA 02111-1307, USA.
19
- *
20
- * Author:
21
- * Emmanuel Pacaud <emmanuel@gnome.org>
22
- */
23
-
24
- #include <lsmdebug.h>
25
- #include <lsmsvgview.h>
26
- #include <lsmsvgdocument.h>
27
- #include <lsmsvgelement.h>
28
- #include <lsmsvgsvgelement.h>
29
- #include <lsmsvgradialgradientelement.h>
30
- #include <lsmsvgfilterelement.h>
31
- #include <lsmsvglineargradientelement.h>
32
- #include <lsmsvgpatternelement.h>
33
- #include <lsmsvgmarkerelement.h>
34
- #include <lsmsvgclippathelement.h>
35
- #include <lsmsvgmaskelement.h>
36
- #include <lsmsvgfiltersurface.h>
37
- #include <lsmcairo.h>
38
- #include <lsmstr.h>
39
- #include <gdk-pixbuf/gdk-pixbuf.h>
40
- #include <glib/gprintf.h>
41
-
42
- #include <math.h>
43
- #include <string.h>
44
-
45
- static gboolean lsm_svg_view_circular_reference_check (LsmSvgView *view, LsmSvgElement *element);
46
-
47
- static GObjectClass *parent_class;
48
-
49
- typedef struct {
50
- gboolean is_text_path;
51
- gboolean is_extents_defined;
52
- LsmExtents extents;
53
- PangoLayout *pango_layout;
54
- } LsmSvgViewPathInfos;
55
-
56
- static LsmSvgViewPathInfos default_path_infos = {
57
- .is_text_path = FALSE,
58
- .is_extents_defined = FALSE,
59
- .extents = {0.0, 0.0, 0.0, 0.0},
60
- .pango_layout = NULL
61
- };
62
-
63
- struct _LsmSvgViewPatternData {
64
- cairo_t *old_cairo;
65
-
66
- cairo_pattern_t *pattern;
67
-
68
- LsmBox extents;
69
- LsmBox object_extents;
70
-
71
- double opacity;
72
- };
73
-
74
- typedef struct {
75
- cairo_surface_t *surface;
76
- double group_opacity;
77
- gboolean enable_background;
78
- } LsmSvgViewBackground;
79
-
80
- cairo_operator_t cairo_operators[] = {
81
- CAIRO_OPERATOR_CLEAR,
82
- CAIRO_OPERATOR_SOURCE,
83
- CAIRO_OPERATOR_DEST,
84
- CAIRO_OPERATOR_OVER,
85
- CAIRO_OPERATOR_DEST_OVER,
86
- CAIRO_OPERATOR_IN,
87
- CAIRO_OPERATOR_DEST_IN,
88
- CAIRO_OPERATOR_OUT,
89
- CAIRO_OPERATOR_DEST_OUT,
90
- CAIRO_OPERATOR_ATOP,
91
- CAIRO_OPERATOR_DEST_ATOP,
92
- CAIRO_OPERATOR_XOR,
93
- CAIRO_OPERATOR_ADD,
94
- CAIRO_OPERATOR_MULTIPLY,
95
- CAIRO_OPERATOR_SCREEN,
96
- CAIRO_OPERATOR_OVERLAY,
97
- CAIRO_OPERATOR_DARKEN,
98
- CAIRO_OPERATOR_LIGHTEN,
99
- CAIRO_OPERATOR_COLOR_DODGE,
100
- CAIRO_OPERATOR_COLOR_BURN,
101
- CAIRO_OPERATOR_HARD_LIGHT,
102
- CAIRO_OPERATOR_SOFT_LIGHT,
103
- CAIRO_OPERATOR_DIFFERENCE,
104
- CAIRO_OPERATOR_EXCLUSION
105
- };
106
-
107
- void
108
- lsm_cairo_set_comp_op (cairo_t *cairo, LsmSvgCompOp comp_op)
109
- {
110
- if (G_LIKELY (cairo != NULL && comp_op >= LSM_SVG_COMP_OP_CLEAR && comp_op <= LSM_SVG_COMP_OP_EXCLUSION)) {
111
- lsm_log_render ("[lsmSvgView::set_comp_op] Set comp-op to %s", lsm_svg_comp_op_to_string (comp_op));
112
- cairo_set_operator (cairo, cairo_operators[comp_op]);
113
- }
114
- }
115
-
116
- double
117
- lsm_svg_view_normalize_length (LsmSvgView *view, const LsmSvgLength *length, LsmSvgLengthDirection direction)
118
- {
119
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), 0.0);
120
-
121
- return lsm_svg_length_normalize (length, view->viewbox_stack->data, view->style->font_size_px, direction);
122
- }
123
-
124
- static void
125
- _start_pattern (LsmSvgView *view, const LsmBox *extents, const LsmBox *object_extents, double opacity)
126
- {
127
- lsm_debug_render ("[LsmSvgView::start_pattern]");
128
-
129
- view->pattern_stack = g_slist_prepend (view->pattern_stack, view->pattern_data);
130
-
131
- view->pattern_data = g_new (LsmSvgViewPatternData, 1);
132
- view->pattern_data->old_cairo = view->dom_view.cairo;
133
- view->pattern_data->pattern = NULL;
134
- view->pattern_data->extents = *extents;
135
- view->pattern_data->opacity = opacity;
136
- view->pattern_data->object_extents = *object_extents;
137
-
138
- view->dom_view.cairo = NULL;
139
- }
140
-
141
- static void
142
- _end_pattern (LsmSvgView *view)
143
- {
144
- g_return_if_fail (view->pattern_data != NULL);
145
-
146
- if (view->pattern_data->pattern != NULL)
147
- cairo_pattern_destroy (view->pattern_data->pattern);
148
- if (view->dom_view.cairo != NULL)
149
- cairo_destroy (view->dom_view.cairo);
150
-
151
- view->dom_view.cairo = view->pattern_data->old_cairo;
152
-
153
- g_free (view->pattern_data);
154
-
155
- if (view->pattern_stack != NULL) {
156
- view->pattern_data = view->pattern_stack->data;
157
- view->pattern_stack = g_slist_delete_link (view->pattern_stack, view->pattern_stack);
158
- } else
159
- view->pattern_data = NULL;
160
-
161
- lsm_debug_render ("[LsmSvgView::end_pattern]");
162
- }
163
-
164
- static void
165
- _set_pattern (LsmSvgView *view, cairo_pattern_t *pattern)
166
- {
167
- g_return_if_fail (view->pattern_data != NULL);
168
- g_return_if_fail (view->pattern_data->pattern == NULL);
169
-
170
- view->pattern_data->pattern = pattern;
171
- view->last_stop_offset = 0.0;
172
- }
173
-
174
- void
175
- lsm_svg_view_create_radial_gradient (LsmSvgView *view,
176
- double cx, double cy,
177
- double r,
178
- double fx, double fy)
179
- {
180
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
181
-
182
- _set_pattern (view, cairo_pattern_create_radial (fx, fy, 0, cx, cy, r));
183
- }
184
-
185
- void
186
- lsm_svg_view_create_linear_gradient (LsmSvgView *view,
187
- double x1, double y1,
188
- double x2, double y2)
189
- {
190
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
191
-
192
- _set_pattern (view, cairo_pattern_create_linear (x1, y1, x2, y2));
193
- }
194
-
195
- void
196
- lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset)
197
- {
198
- const LsmSvgStyle *style;
199
- const LsmSvgColor *color;
200
-
201
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
202
- g_return_if_fail (view->pattern_data != NULL);
203
- g_return_if_fail (view->pattern_data->pattern != NULL);
204
-
205
- if (offset > 1.0)
206
- offset = 1.0;
207
-
208
- if (offset < view->last_stop_offset)
209
- offset = view->last_stop_offset;
210
- else
211
- view->last_stop_offset = offset;
212
-
213
- style = view->style;
214
-
215
- lsm_debug_render ("[LsmSvgView::add_gradient_color_stop] opacity = %g", style->stop_opacity->value);
216
-
217
- color = &style->stop_color->value;
218
-
219
- if (color->red < 0.0 || color->blue < 0.0 || color->green < 0.0)
220
- color = &style->color->value;
221
-
222
- lsm_debug_render ("[LsmSvgView::add_gradient_color_stop] color = %2x%2x%2x",
223
- (int) (255.0 * color->red),
224
- (int) (255.0 * color->green),
225
- (int) (255.0 * color->blue));
226
-
227
- cairo_pattern_add_color_stop_rgba (view->pattern_data->pattern, offset,
228
- color->red,
229
- color->green,
230
- color->blue,
231
- style->stop_opacity->value * view->pattern_data->opacity);
232
- }
233
-
234
- gboolean
235
- lsm_svg_view_set_gradient_properties (LsmSvgView *view,
236
- LsmSvgSpreadMethod method,
237
- LsmSvgPatternUnits units,
238
- const LsmSvgMatrix *gradient_matrix)
239
- {
240
- cairo_matrix_t matrix;
241
- cairo_matrix_t inv_matrix;
242
- cairo_status_t status;
243
-
244
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), FALSE);
245
- g_return_val_if_fail (view->pattern_data != NULL, FALSE);
246
- g_return_val_if_fail (view->pattern_data->pattern != NULL, FALSE);
247
-
248
- switch (method) {
249
- case LSM_SVG_SPREAD_METHOD_REFLECT:
250
- cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_REFLECT);
251
- break;
252
- case LSM_SVG_SPREAD_METHOD_REPEAT:
253
- cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_REPEAT);
254
- break;
255
- default:
256
- cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_PAD);
257
- }
258
-
259
- if (gradient_matrix != NULL) {
260
- cairo_matrix_init (&matrix,
261
- gradient_matrix->a, gradient_matrix->b,
262
- gradient_matrix->c, gradient_matrix->d,
263
- gradient_matrix->e, gradient_matrix->f);
264
- cairo_matrix_invert (&matrix);
265
- } else
266
- cairo_matrix_init_identity (&matrix);
267
-
268
- if (units == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX &&
269
- view->pattern_data->extents.width > 0.0 &&
270
- view->pattern_data->extents.height > 0.0) {
271
- cairo_matrix_scale (&matrix,
272
- 1.0 / view->pattern_data->extents.width,
273
- 1.0 / view->pattern_data->extents.height);
274
- cairo_matrix_translate (&matrix,
275
- -view->pattern_data->extents.x,
276
- -view->pattern_data->extents.y);
277
-
278
- }
279
-
280
- inv_matrix = matrix;
281
- status = cairo_matrix_invert (&inv_matrix);
282
-
283
- if (status != CAIRO_STATUS_SUCCESS) {
284
- lsm_debug_render ("[LsmSvgView::set_gradient_properties] Not invertible matrix");
285
- return FALSE;
286
- }
287
-
288
- cairo_pattern_set_matrix (view->pattern_data->pattern, &matrix);
289
-
290
- return TRUE;
291
- }
292
-
293
- gboolean
294
- lsm_svg_view_create_surface_pattern (LsmSvgView *view,
295
- const LsmBox *viewport,
296
- const LsmSvgMatrix *pattern_matrix,
297
- LsmSvgViewSurfaceType surface_type)
298
- {
299
- cairo_surface_t *surface;
300
- cairo_pattern_t *pattern;
301
- cairo_matrix_t matrix;
302
- cairo_matrix_t inv_matrix;
303
- cairo_status_t status;
304
- double x1, y1, x2, y2;
305
- double device_width, device_height;
306
- double x_scale, y_scale;
307
-
308
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), FALSE);
309
- g_return_val_if_fail (viewport != NULL, FALSE);
310
- g_return_val_if_fail (view->pattern_data != NULL, FALSE);
311
- g_return_val_if_fail (view->dom_view.cairo == NULL, FALSE);
312
-
313
- x1 = viewport->x;
314
- y1 = viewport->y;
315
- x2 = viewport->x + viewport->width;
316
- y2 = viewport->y;
317
-
318
- cairo_user_to_device (view->pattern_data->old_cairo, &x1, &y1);
319
- cairo_user_to_device (view->pattern_data->old_cairo, &x2, &y2);
320
-
321
- device_width = sqrt ((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
322
-
323
- x2 = viewport->x;
324
- y2 = viewport->y + viewport->height;
325
-
326
- cairo_user_to_device (view->pattern_data->old_cairo, &x2, &y2);
327
-
328
- device_height = sqrt ((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
329
-
330
- if (surface_type == LSM_SVG_VIEW_SURFACE_TYPE_IMAGE) {
331
- device_height = ceil (device_height);
332
- device_width = ceil (device_width);
333
- }
334
-
335
- x_scale = device_width / viewport->width;
336
- y_scale = device_height / viewport->height;
337
-
338
- lsm_debug_render ("[LsmSvgView::create_surface_pattern] pattern size = %g ,%g at %g, %g (scale %g x %g)",
339
- device_width, device_height, viewport->x, viewport->y, x_scale, y_scale);
340
-
341
- switch (surface_type) {
342
- case LSM_SVG_VIEW_SURFACE_TYPE_AUTO:
343
- surface = cairo_surface_create_similar (cairo_get_target (view->pattern_data->old_cairo),
344
- CAIRO_CONTENT_COLOR_ALPHA,
345
- device_width, device_height);
346
- break;
347
- default:
348
- case LSM_SVG_VIEW_SURFACE_TYPE_IMAGE:
349
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, device_width, device_height);
350
- break;
351
- }
352
-
353
- pattern = cairo_pattern_create_for_surface (surface);
354
- view->dom_view.cairo = cairo_create (surface);
355
- cairo_surface_destroy (surface);
356
-
357
- cairo_scale (view->dom_view.cairo, x_scale, y_scale);
358
- cairo_translate (view->dom_view.cairo, -viewport->x, -viewport->y);
359
-
360
- _set_pattern (view, pattern);
361
-
362
- if (pattern_matrix != NULL) {
363
- cairo_matrix_init (&matrix,
364
- pattern_matrix->a, pattern_matrix->b,
365
- pattern_matrix->c, pattern_matrix->d,
366
- pattern_matrix->e + viewport->x, pattern_matrix->f + viewport->y);
367
- cairo_matrix_scale (&matrix, 1.0 / x_scale, 1.0 / y_scale);
368
- cairo_matrix_invert (&matrix);
369
- } else {
370
- cairo_matrix_init_scale (&matrix, x_scale, y_scale);
371
- cairo_matrix_translate (&matrix, -viewport->x, -viewport->y);
372
- }
373
-
374
- inv_matrix = matrix;
375
- status = cairo_matrix_invert (&inv_matrix);
376
-
377
- if (status != CAIRO_STATUS_SUCCESS) {
378
- lsm_debug_render ("[LsmSvgView::create_surface_pattern] Not invertible matrix");
379
- return FALSE;
380
- }
381
-
382
- cairo_pattern_set_matrix (view->pattern_data->pattern, &matrix);
383
- cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_REPEAT);
384
-
385
- lsm_debug_render ("[LsmSvgView::create_surface_pattern] Pattern matrix %g, %g, %g, %g, %g, %g",
386
- matrix.xx, matrix.xy, matrix.yx, matrix.yy,
387
- matrix.x0, matrix.y0);
388
-
389
- return TRUE;
390
- }
391
-
392
- typedef enum {
393
- LSM_SVG_VIEW_PAINT_OPERATION_FILL,
394
- LSM_SVG_VIEW_PAINT_OPERATION_STROKE
395
- } LsmSvgViewPaintOperation;
396
-
397
- static void
398
- _paint_url (LsmSvgView *view,
399
- LsmSvgViewPathInfos *path_infos,
400
- LsmSvgViewPaintOperation operation,
401
- const char *url, double opacity)
402
- {
403
- cairo_t *cairo;
404
- LsmSvgElement *element;
405
- LsmBox extents;
406
-
407
- element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
408
- if ((!LSM_IS_SVG_RADIAL_GRADIENT_ELEMENT (element) &&
409
- !LSM_IS_SVG_LINEAR_GRADIENT_ELEMENT (element) &&
410
- !LSM_IS_SVG_PATTERN_ELEMENT (element)) ||
411
- lsm_svg_view_circular_reference_check (view, element)) {
412
-
413
- cairo_set_source_rgba (view->dom_view.cairo, 0, 0, 0, 0);
414
-
415
- lsm_warning_render ("[LsmSvgView::_paint_url] Paint url not found: %s", url);
416
-
417
- return;
418
- }
419
-
420
- lsm_debug_render ("[LsmSvgView::_paint_url] Paint using '%s'", url);
421
-
422
- if (!path_infos->is_extents_defined) {
423
- cairo_path_extents (view->dom_view.cairo,
424
- &path_infos->extents.x1,
425
- &path_infos->extents.y1,
426
- &path_infos->extents.x2,
427
- &path_infos->extents.y2);
428
- path_infos->is_extents_defined = TRUE;
429
- }
430
-
431
- extents.x = path_infos->extents.x1;
432
- extents.y = path_infos->extents.y1;
433
- extents.width = path_infos->extents.x2 - extents.x;
434
- extents.height = path_infos->extents.y2 - extents.y;
435
-
436
- lsm_debug_render ("[LsmSvgView::_paint_url] Pattern extents x = %g, y = %g, w = %g, h = %g",
437
- extents.x, extents.y, extents.width, extents.height);
438
-
439
- _start_pattern (view, &extents, &extents, opacity);
440
-
441
- lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
442
-
443
- cairo = view->pattern_data->old_cairo;
444
-
445
- if (view->pattern_data->pattern) {
446
- if (view->debug_pattern && view->dom_view.cairo) {
447
- char *filename;
448
-
449
- filename = g_strdup_printf ("pattern-%s).png", url);
450
- cairo_surface_write_to_png (cairo_get_target (view->dom_view.cairo), filename);
451
- g_free (filename);
452
- }
453
-
454
- cairo_set_source (cairo, view->pattern_data->pattern);
455
- } else
456
- cairo_set_source_rgba (cairo, 0.0, 0.0, 0.0, 0.0);
457
-
458
- _end_pattern (view);
459
- }
460
-
461
- static gboolean
462
- _set_color (LsmSvgView *view,
463
- LsmSvgViewPathInfos *path_infos,
464
- LsmSvgViewPaintOperation operation,
465
- const LsmSvgPaint *paint, double opacity)
466
- {
467
- cairo_t *cairo = view->dom_view.cairo;
468
-
469
- switch (paint->type) {
470
- case LSM_SVG_PAINT_TYPE_NONE:
471
- return FALSE;
472
- case LSM_SVG_PAINT_TYPE_RGB_COLOR:
473
- cairo_set_source_rgba (cairo,
474
- paint->color.red,
475
- paint->color.green,
476
- paint->color.blue,
477
- opacity);
478
- break;
479
- case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
480
- cairo_set_source_rgba (cairo,
481
- view->style->color->value.red,
482
- view->style->color->value.green,
483
- view->style->color->value.blue,
484
- opacity);
485
- break;
486
- case LSM_SVG_PAINT_TYPE_URI:
487
- case LSM_SVG_PAINT_TYPE_URI_RGB_COLOR:
488
- case LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR:
489
- case LSM_SVG_PAINT_TYPE_URI_NONE:
490
- _paint_url (view, path_infos, operation, paint->url, opacity);
491
- break;
492
- default:
493
- return FALSE;
494
- }
495
-
496
- return TRUE;
497
- }
498
-
499
- static void
500
- paint_markers (LsmSvgView *view)
501
- {
502
- const LsmSvgStyle *style;
503
- LsmSvgElement *marker;
504
- LsmSvgElement *marker_start;
505
- LsmSvgElement *marker_mid;
506
- LsmSvgElement *marker_end;
507
- cairo_t *cairo;
508
- cairo_path_t *path;
509
- cairo_path_data_t *data;
510
- cairo_path_data_t *next_data;
511
- double stroke_width;
512
- double prev_x, prev_y;
513
- double x = 0;
514
- double y = 0;
515
- double next_x, next_y;
516
- cairo_path_data_type_t type;
517
- cairo_path_data_type_t next_type;
518
- double angle;
519
- int i;
520
-
521
- style = view->style;
522
-
523
- if ((style->marker->value == NULL || strcmp (style->marker->value, "none") == 0) &&
524
- (style->marker_mid->value == NULL || strcmp (style->marker_mid->value, "none") == 0) &&
525
- (style->marker_end->value == NULL || strcmp (style->marker_end->value, "none") == 0) &&
526
- (style->marker_start->value == NULL || strcmp (style->marker_start->value, "none") == 0))
527
- return;
528
-
529
- cairo = view->dom_view.cairo;
530
-
531
- marker = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
532
- style->marker->value);
533
- marker_start = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
534
- style->marker_start->value);
535
- marker_mid = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
536
- style->marker_mid->value);
537
- marker_end = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
538
- style->marker_end->value);
539
- stroke_width = lsm_svg_view_normalize_length (view, &view->style->stroke_width->length,
540
- LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
541
-
542
- if (marker != NULL && lsm_svg_view_circular_reference_check (view, marker))
543
- return;
544
- if (marker_start != NULL && lsm_svg_view_circular_reference_check (view, marker_start))
545
- return;
546
- if (marker_mid != NULL && lsm_svg_view_circular_reference_check (view, marker_mid))
547
- return;
548
- if (marker_end != NULL && lsm_svg_view_circular_reference_check (view, marker_end))
549
- return;
550
-
551
- if (marker_start == NULL)
552
- marker_start = marker;
553
- if (marker_mid == NULL)
554
- marker_mid = marker;
555
- if (marker_end == NULL)
556
- marker_end = marker;
557
-
558
- path = cairo_copy_path (cairo);
559
- cairo_new_path (cairo);
560
-
561
- if (path->num_data > 0) {
562
- next_data = &path->data[0];
563
- next_type = next_data->header.type;
564
-
565
- if (next_type == CAIRO_PATH_CURVE_TO) {
566
- next_x = next_data[3].point.x;
567
- next_y = next_data[3].point.y;
568
- } else {
569
- next_x = next_data[1].point.x;
570
- next_y = next_data[1].point.y;
571
- }
572
-
573
- for (i = 0; i < path->num_data; i += path->data[i].header.length) {
574
- data = next_data;
575
-
576
- prev_x = x;
577
- prev_y = y;
578
- x = next_x;
579
- y = next_y;
580
- type = next_type;
581
-
582
- if (i + path->data[i].header.length < path->num_data) {
583
- next_data = &path->data[i + path->data[i].header.length];
584
- next_type = next_data->header.type;
585
-
586
- if (next_type == CAIRO_PATH_CURVE_TO) {
587
- next_x = next_data[3].point.x;
588
- next_y = next_data[3].point.y;
589
- } else {
590
- next_x = next_data[1].point.x;
591
- next_y = next_data[1].point.y;
592
- }
593
- } else {
594
- next_data = NULL;
595
- next_type = CAIRO_PATH_MOVE_TO;
596
- next_x = 0.0;
597
- next_y = 0.0;
598
- }
599
-
600
- if (data->header.type == CAIRO_PATH_CLOSE_PATH) {
601
- marker = NULL;
602
- } else if (next_data == NULL ||
603
- next_data->header.type == CAIRO_PATH_MOVE_TO) {
604
- marker = marker_end;
605
- if (type == CAIRO_PATH_CURVE_TO) {
606
- if (y != data[2].point.y ||
607
- x != data[2].point.x)
608
- angle = atan2 (y - data[2].point.y,
609
- x - data[2].point.x);
610
- else
611
- angle = atan2 (y - data[1].point.y,
612
- x - data[1].point.x);
613
- } else
614
- angle = atan2 (y - prev_y, x - prev_x);
615
- } else if (data->header.type == CAIRO_PATH_MOVE_TO) {
616
- marker = marker_start;
617
- if (next_type == CAIRO_PATH_CURVE_TO) {
618
- if (next_data[1].point.y != y ||
619
- next_data[1].point.x != x)
620
- angle = atan2 (next_data[1].point.y - y,
621
- next_data[1].point.x - x);
622
- else
623
- angle = atan2 (next_data[2].point.y - y,
624
- next_data[2].point.x - x);
625
- } else
626
- angle = atan2 (next_y - y, next_x - x);
627
- } else {
628
- double xdifin, ydifin, xdifout, ydifout, intot, outtot;
629
-
630
- marker = marker_mid;
631
-
632
- if (type == CAIRO_PATH_CURVE_TO) {
633
- if (x != data[2].point.x ||
634
- y != data[2].point.y) {
635
- xdifin = x - data[2].point.x;
636
- ydifin = y - data[2].point.y;
637
- } else {
638
- xdifin = x - data[1].point.x;
639
- ydifin = y - data[1].point.y;
640
- }
641
- } else {
642
- xdifin = x - prev_x;
643
- ydifin = y - prev_y;
644
- }
645
- if (next_type == CAIRO_PATH_CURVE_TO) {
646
- if (next_data[1].point.x != x ||
647
- next_data[1].point.y != y) {
648
- xdifout = next_data[1].point.x - x;
649
- ydifout = next_data[1].point.y - y;
650
- } else {
651
- xdifout = next_data[2].point.x - x;
652
- ydifout = next_data[2].point.y - y;
653
- }
654
- } else {
655
- xdifout = next_x - x;
656
- ydifout = next_y - y;
657
- }
658
-
659
- intot = sqrt (xdifin * xdifin + ydifin * ydifin);
660
- outtot = sqrt (xdifout * xdifout + ydifout * ydifout);
661
-
662
- xdifin /= intot;
663
- ydifin /= intot;
664
- xdifout /= outtot;
665
- ydifout /= outtot;
666
-
667
- angle = atan2 ((ydifin + ydifout) / 2, (xdifin + xdifout) / 2);
668
- }
669
-
670
- if (marker != NULL) {
671
- cairo_save (cairo);
672
- cairo_translate (cairo, x, y);
673
- lsm_svg_marker_element_render (LSM_SVG_MARKER_ELEMENT (marker), view,
674
- stroke_width, angle);
675
- cairo_restore (cairo);
676
- }
677
- }
678
-
679
- cairo_path_destroy (path);
680
- }
681
- }
682
-
683
- static void
684
- paint (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
685
- {
686
- const LsmSvgStyle *style;
687
- LsmSvgElement *element;
688
- cairo_t *cairo;
689
- gboolean use_group;
690
- double group_opacity;
691
-
692
- element = view->element_stack->data;
693
-
694
- g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
695
-
696
- cairo = view->dom_view.cairo;
697
- style = view->style;
698
-
699
- if ((style->opacity != NULL ||
700
- style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER ) &&
701
- style->ignore_group_opacity &&
702
- g_strcmp0 (style->filter->value, "none") == 0) {
703
- group_opacity = style->opacity->value;
704
-
705
- use_group = ((style->fill->paint.type != LSM_SVG_PAINT_TYPE_NONE &&
706
- style->stroke->paint.type != LSM_SVG_PAINT_TYPE_NONE) ||
707
- style->stroke->paint.type == LSM_SVG_PAINT_TYPE_URI ||
708
- style->stroke->paint.type == LSM_SVG_PAINT_TYPE_URI_RGB_COLOR ||
709
- style->fill->paint.type == LSM_SVG_PAINT_TYPE_URI_RGB_COLOR ||
710
- style->fill->paint.type == LSM_SVG_PAINT_TYPE_URI) &&
711
- (group_opacity < 1.0 || style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER );
712
- } else {
713
- use_group = FALSE;
714
- group_opacity = 1.0;
715
- }
716
-
717
- /* Instead of push_group, we should restrict to the current path bounding box */
718
- if (use_group) {
719
- cairo_push_group (cairo);
720
- } else if (style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
721
- lsm_cairo_set_comp_op (cairo, style->comp_op->value);
722
-
723
- if (_set_color (view,
724
- path_infos,
725
- LSM_SVG_VIEW_PAINT_OPERATION_FILL,
726
- &style->fill->paint,
727
- style->fill_opacity->value * (use_group ? 1.0 : group_opacity))) {
728
-
729
- if (path_infos->is_text_path) {
730
- pango_cairo_show_layout (cairo, path_infos->pango_layout);
731
- } else {
732
- cairo_set_fill_rule (cairo, style->fill_rule->value == LSM_SVG_FILL_RULE_EVEN_ODD ?
733
- CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
734
- cairo_fill_preserve (cairo);
735
- }
736
- }
737
-
738
- if (_set_color (view,
739
- path_infos,
740
- LSM_SVG_VIEW_PAINT_OPERATION_STROKE,
741
- &style->stroke->paint,
742
- style->stroke_opacity->value * (use_group ? 1.0 : group_opacity))) {
743
- double line_width;
744
-
745
- if (path_infos->is_text_path) {
746
- pango_cairo_layout_path (cairo, path_infos->pango_layout);
747
- }
748
-
749
- switch (style->stroke_line_join->value) {
750
- case LSM_SVG_LINE_JOIN_MITER:
751
- cairo_set_line_join (cairo, CAIRO_LINE_JOIN_MITER);
752
- break;
753
- case LSM_SVG_LINE_JOIN_ROUND:
754
- cairo_set_line_join (cairo,CAIRO_LINE_JOIN_ROUND);
755
- break;
756
- default:
757
- cairo_set_line_join (cairo,CAIRO_LINE_JOIN_BEVEL);
758
- }
759
-
760
- switch (style->stroke_line_cap->value) {
761
- case LSM_SVG_LINE_CAP_BUTT:
762
- cairo_set_line_cap (cairo, CAIRO_LINE_CAP_BUTT);
763
- break;
764
- case LSM_SVG_LINE_CAP_ROUND:
765
- cairo_set_line_cap (cairo, CAIRO_LINE_CAP_ROUND);
766
- break;
767
- default:
768
- cairo_set_line_cap (cairo, CAIRO_LINE_CAP_SQUARE);
769
- }
770
-
771
- line_width = lsm_svg_view_normalize_length (view, &style->stroke_width->length,
772
- LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
773
-
774
- cairo_set_miter_limit (cairo, style->stroke_miter_limit->value);
775
- cairo_set_line_width (cairo, line_width);
776
-
777
- if (style->stroke_dash_array->value.n_dashes > 0) {
778
- double dash_offset;
779
- double *dashes;
780
- unsigned int i;
781
-
782
- dash_offset = lsm_svg_view_normalize_length (view, &style->stroke_dash_offset->length,
783
- LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
784
- dashes = g_new (double, style->stroke_dash_array->value.n_dashes);
785
- for (i = 0; i < style->stroke_dash_array->value.n_dashes; i++)
786
- dashes[i] = lsm_svg_view_normalize_length (view,
787
- &style->stroke_dash_array->value.dashes[i],
788
- LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
789
-
790
- cairo_set_dash (cairo, dashes, style->stroke_dash_array->value.n_dashes, dash_offset);
791
- g_free (dashes);
792
- } else
793
- cairo_set_dash (cairo, NULL, 0, 0.0);
794
-
795
- cairo_stroke_preserve (cairo);
796
- }
797
-
798
- paint_markers (view);
799
-
800
- cairo_new_path (cairo);
801
-
802
- if (use_group) {
803
- cairo_pop_group_to_source (cairo);
804
- if (G_UNLIKELY (style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
805
- lsm_cairo_set_comp_op (cairo, style->comp_op->value);
806
- cairo_paint_with_alpha (cairo, group_opacity);
807
- }
808
-
809
- if (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER)
810
- lsm_cairo_set_comp_op (cairo, LSM_SVG_COMP_OP_SRC_OVER);
811
- }
812
-
813
- static void
814
- process_path (LsmSvgView *view, LsmSvgViewPathInfos *path_infos)
815
- {
816
- g_return_if_fail (view->style != NULL);
817
-
818
- if (view->is_clipping) {
819
- if (path_infos->is_text_path)
820
- pango_cairo_layout_path (view->dom_view.cairo, path_infos->pango_layout);
821
- cairo_set_fill_rule (view->dom_view.cairo, view->style->clip_rule->value);
822
- } else
823
- paint (view, path_infos);
824
- }
825
-
826
- void
827
- lsm_svg_view_show_viewport (LsmSvgView*view, const LsmBox *viewport)
828
- {
829
- LsmSvgPaint *paint;
830
-
831
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
832
- g_return_if_fail (viewport != NULL);
833
-
834
- paint = &view->style->viewport_fill->paint;
835
-
836
- switch (paint->type) {
837
- case LSM_SVG_PAINT_TYPE_RGB_COLOR:
838
- cairo_set_source_rgba (view->dom_view.cairo,
839
- paint->color.red,
840
- paint->color.green,
841
- paint->color.blue,
842
- view->style->viewport_fill_opacity->value);
843
- break;
844
- case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
845
- cairo_set_source_rgba (view->dom_view.cairo,
846
- view->style->color->value.red,
847
- view->style->color->value.green,
848
- view->style->color->value.blue,
849
- view->style->viewport_fill_opacity->value);
850
- default:
851
- return;
852
- }
853
-
854
- cairo_rectangle (view->dom_view.cairo, viewport->x, viewport->y, 0, 0);
855
- cairo_paint (view->dom_view.cairo);
856
- }
857
-
858
- /*
859
- * Code for show_rectangle and show ellipse is inspired from
860
- * the librsvg library (rsvg-shapes.c)
861
- *
862
- * Copyright (C) 2000 Eazel, Inc.
863
- * Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
864
- *
865
- * Authors: Raph Levien <raph@artofcode.com>,
866
- * Dom Lachowicz <cinamod@hotmail.com>,
867
- * Caleb Moore <c.moore@student.unsw.edu.au>
868
- */
869
-
870
- void
871
- lsm_svg_view_show_rectangle (LsmSvgView *view,
872
- double x, double y,
873
- double w, double h,
874
- double rx, double ry)
875
- {
876
- LsmSvgViewPathInfos path_infos = default_path_infos;
877
- cairo_t *cairo;
878
-
879
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
880
-
881
- cairo = view->dom_view.cairo;
882
-
883
- if (rx <= 0.0 || ry <= 0.0)
884
- cairo_rectangle (cairo, x, y, w, h);
885
- else {
886
-
887
- if (rx > fabs (w / 2.))
888
- rx = fabs (w / 2.);
889
- if (ry > fabs (h / 2.))
890
- ry = fabs (h / 2.);
891
-
892
- cairo_move_to (cairo, x + rx, y);
893
- cairo_line_to (cairo, x + w - rx, y);
894
- lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w, y + ry);
895
- cairo_line_to (cairo, x + w, y + h -ry);
896
- lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + w - rx, y + h);
897
- cairo_line_to (cairo, x + rx, y + h);
898
- lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x, y + h - ry);
899
- cairo_line_to (cairo, x, y + ry);
900
- lsm_cairo_elliptical_arc (cairo, rx, ry, 0.0, FALSE, TRUE, x + rx, y);
901
- cairo_close_path (cairo);
902
- }
903
-
904
- process_path (view, &path_infos);
905
- }
906
-
907
- void
908
- lsm_svg_view_show_circle (LsmSvgView *view, double cx, double cy, double r)
909
- {
910
- LsmSvgViewPathInfos path_infos = default_path_infos;
911
-
912
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
913
-
914
- cairo_arc (view->dom_view.cairo, cx, cy, r, 0, 2 * M_PI);
915
-
916
- process_path (view, &path_infos);
917
- }
918
-
919
- #define LSM_SVG_ARC_MAGIC ((double) 0.5522847498) /* 4/3 * (1-cos 45)/sin 45 = 4/3 * sqrt(2) - 1 */
920
-
921
- void
922
- lsm_svg_view_show_ellipse (LsmSvgView *view, double cx, double cy, double rx, double ry)
923
- {
924
- LsmSvgViewPathInfos path_infos = default_path_infos;
925
- cairo_t *cairo;
926
-
927
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
928
-
929
- if (rx <= 0 || ry <= 0)
930
- return;
931
-
932
- cairo = view->dom_view.cairo;
933
-
934
- cairo_move_to (cairo, cx + rx, cy);
935
- cairo_curve_to (cairo, cx + rx, cy + LSM_SVG_ARC_MAGIC * ry, cx + LSM_SVG_ARC_MAGIC * rx, cy + ry, cx, cy + ry);
936
- cairo_curve_to (cairo, cx - LSM_SVG_ARC_MAGIC * rx, cy + ry, cx - rx, cy + LSM_SVG_ARC_MAGIC * ry, cx - rx, cy);
937
- cairo_curve_to (cairo, cx - rx, cy - LSM_SVG_ARC_MAGIC * ry, cx - LSM_SVG_ARC_MAGIC * rx, cy - ry, cx, cy - ry);
938
- cairo_curve_to (cairo, cx + LSM_SVG_ARC_MAGIC * rx, cy - ry, cx + rx, cy - LSM_SVG_ARC_MAGIC * ry, cx + rx, cy);
939
- cairo_close_path (cairo);
940
-
941
- process_path (view, &path_infos);
942
- }
943
-
944
- void
945
- lsm_svg_view_show_path (LsmSvgView *view,
946
- const char *d)
947
- {
948
- LsmSvgViewPathInfos path_infos = default_path_infos;
949
-
950
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
951
-
952
- lsm_cairo_emit_svg_path (view->dom_view.cairo, d);
953
-
954
- process_path (view, &path_infos);
955
- }
956
-
957
- void
958
- lsm_svg_view_path_extents (LsmSvgView *view,
959
- const char *path,
960
- LsmExtents *extents)
961
- {
962
- double x1, y1, x2, y2;
963
-
964
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
965
- g_return_if_fail (extents != NULL);
966
-
967
- cairo_new_path (view->dom_view.cairo);
968
- lsm_cairo_emit_svg_path (view->dom_view.cairo, path);
969
- cairo_path_extents (view->dom_view.cairo, &x1, &y1, &x2, &y2);
970
- cairo_new_path (view->dom_view.cairo);
971
-
972
- extents->x1 = x1;
973
- extents->x2 = x2;
974
- extents->y1 = y1;
975
- extents->y2 = y2;
976
- }
977
-
978
- void
979
- lsm_svg_view_show_line (LsmSvgView *view, double x1, double y1, double x2, double y2)
980
- {
981
- LsmSvgViewPathInfos path_infos = default_path_infos;
982
-
983
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
984
-
985
- cairo_move_to (view->dom_view.cairo, x1, y1);
986
- cairo_line_to (view->dom_view.cairo, x2, y2);
987
-
988
- process_path (view, &path_infos);
989
- }
990
-
991
- static void
992
- _show_points (LsmSvgView *view, const char *points, gboolean close_path)
993
- {
994
- LsmSvgViewPathInfos path_infos = default_path_infos;
995
- char *str;
996
- double values[2];
997
- unsigned int n_values;
998
- unsigned int count = 0;
999
-
1000
- if (points == NULL)
1001
- return;
1002
-
1003
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1004
-
1005
- str = (char *) points;
1006
-
1007
- do {
1008
- n_values = lsm_str_parse_double_list (&str, 2, values);
1009
- if (n_values == 2) {
1010
- if (count == 0)
1011
- cairo_move_to (view->dom_view.cairo, values[0], values[1]);
1012
- else
1013
- cairo_line_to (view->dom_view.cairo, values[0], values[1]);
1014
- } else if (n_values != 0) {
1015
- cairo_new_path (view->dom_view.cairo);
1016
- return;
1017
- }
1018
- count++;
1019
- } while (n_values == 2);
1020
-
1021
- if (close_path)
1022
- cairo_close_path (view->dom_view.cairo);
1023
-
1024
- process_path (view, &path_infos);
1025
- }
1026
-
1027
- void
1028
- lsm_svg_view_show_polyline (LsmSvgView *view, const char *points)
1029
- {
1030
- _show_points (view, points, FALSE);
1031
- }
1032
-
1033
- void
1034
- lsm_svg_view_show_polygon (LsmSvgView *view, const char *points)
1035
- {
1036
- _show_points (view, points, TRUE);
1037
- }
1038
-
1039
- static void
1040
- _update_pango_layout (LsmSvgView *view, char const *string, double x, double y, LsmSvgViewPathInfos *path_infos)
1041
- {
1042
- const LsmSvgStyle *style;
1043
- PangoLayout *pango_layout;
1044
- PangoFontDescription *font_description;
1045
- PangoStretch font_stretch;
1046
- PangoStyle font_style;
1047
- PangoLayoutIter *iter;
1048
- PangoRectangle rectangle;
1049
- int baseline;
1050
- double x1, y1;
1051
-
1052
- style = view->style;
1053
-
1054
- pango_layout = view->pango_layout;
1055
- font_description = view->dom_view.font_description;
1056
-
1057
- pango_font_description_set_family (font_description, style->font_family->value);
1058
- pango_font_description_set_size (font_description, PANGO_SCALE * style->font_size_px);
1059
- pango_font_description_set_weight (font_description, style->font_weight->value);
1060
-
1061
- switch (style->font_stretch->value) {
1062
- case LSM_SVG_FONT_STRETCH_ULTRA_CONDENSED:
1063
- font_stretch = PANGO_STRETCH_ULTRA_CONDENSED;
1064
- break;
1065
- case LSM_SVG_FONT_STRETCH_EXTRA_CONDENSED:
1066
- font_stretch = PANGO_STRETCH_EXTRA_CONDENSED;
1067
- break;
1068
- case LSM_SVG_FONT_STRETCH_CONDENSED:
1069
- font_stretch = PANGO_STRETCH_CONDENSED;
1070
- break;
1071
- case LSM_SVG_FONT_STRETCH_SEMI_CONDENSED:
1072
- font_stretch = PANGO_STRETCH_SEMI_CONDENSED;
1073
- break;
1074
- case LSM_SVG_FONT_STRETCH_SEMI_EXPANDED:
1075
- font_stretch = PANGO_STRETCH_SEMI_EXPANDED;
1076
- break;
1077
- case LSM_SVG_FONT_STRETCH_EXPANDED:
1078
- font_stretch = PANGO_STRETCH_EXPANDED;
1079
- break;
1080
- case LSM_SVG_FONT_STRETCH_EXTRA_EXPANDED:
1081
- font_stretch = PANGO_STRETCH_EXTRA_EXPANDED;
1082
- break;
1083
- case LSM_SVG_FONT_STRETCH_ULTRA_EXPANDED:
1084
- font_stretch = PANGO_STRETCH_ULTRA_EXPANDED;
1085
- break;
1086
- case LSM_SVG_FONT_STRETCH_NORMAL:
1087
- default:
1088
- font_stretch = PANGO_STRETCH_NORMAL;
1089
- break;
1090
- }
1091
- pango_font_description_set_stretch (font_description, font_stretch);
1092
-
1093
- switch (style->font_style->value) {
1094
- case LSM_SVG_FONT_STYLE_OBLIQUE:
1095
- font_style = PANGO_STYLE_OBLIQUE;
1096
- break;
1097
- case LSM_SVG_FONT_STYLE_ITALIC:
1098
- font_style = PANGO_STYLE_ITALIC;
1099
- break;
1100
- case LSM_SVG_FONT_STYLE_NORMAL:
1101
- default:
1102
- font_style = PANGO_STYLE_NORMAL;
1103
- break;
1104
- }
1105
- pango_font_description_set_style (font_description, font_style);
1106
-
1107
- pango_layout_set_text (pango_layout, string, -1);
1108
- pango_layout_set_font_description (pango_layout, font_description);
1109
- pango_layout_get_extents (pango_layout, &rectangle, NULL);
1110
-
1111
- iter = pango_layout_get_iter (pango_layout);
1112
- baseline = pango_layout_iter_get_baseline (iter);
1113
- pango_layout_iter_free (iter);
1114
-
1115
- x1 = x - pango_units_to_double (rectangle.x);
1116
- y1 = y - pango_units_to_double (baseline);
1117
-
1118
- switch (style->text_anchor->value) {
1119
- case LSM_SVG_TEXT_ANCHOR_END:
1120
- x1 -= pango_units_to_double (rectangle.width);
1121
- break;
1122
- case LSM_SVG_TEXT_ANCHOR_MIDDLE:
1123
- x1 -= pango_units_to_double (rectangle.width) / 2.0;
1124
- break;
1125
- case LSM_SVG_TEXT_ANCHOR_START:
1126
- default:
1127
- break;
1128
- }
1129
-
1130
- path_infos->is_text_path = TRUE;
1131
- path_infos->is_extents_defined = TRUE;
1132
- path_infos->extents.x1 = x1;
1133
- path_infos->extents.y1 = y1;
1134
- path_infos->extents.x2 = x1 + pango_units_to_double (rectangle.width);
1135
- path_infos->extents.y2 = y1 + pango_units_to_double (rectangle.height);
1136
- path_infos->pango_layout = pango_layout;
1137
- }
1138
-
1139
- static gboolean
1140
- _lock_pango_layout (LsmSvgView *view)
1141
- {
1142
- /* A text may be painted with a text based pattern. In this case,
1143
- * we take care to create a new pango layout if the current one is in use. */
1144
- if (view->is_pango_layout_in_use) {
1145
- PangoContext *pango_context;
1146
-
1147
- pango_context = pango_layout_get_context (view->pango_layout);
1148
- view->pango_layout_stack = g_slist_prepend (view->pango_layout_stack, view->pango_layout);
1149
- view->pango_layout = pango_layout_new (pango_context);
1150
-
1151
- lsm_debug_render ("[LsmSvgView::show_text] Create a new pango layout");
1152
-
1153
- return TRUE;
1154
- }
1155
-
1156
- view->is_pango_layout_in_use = TRUE;
1157
-
1158
- return FALSE;
1159
- }
1160
-
1161
- static void
1162
- _unlock_pango_layout (LsmSvgView *view, gboolean need_pop)
1163
- {
1164
-
1165
- if (need_pop) {
1166
- lsm_debug_render ("[LsmSvgView::show_text] Free the child pango layout");
1167
-
1168
- if (view->pango_layout != NULL) {
1169
- g_object_unref (view->pango_layout);
1170
-
1171
- view->pango_layout = view->pango_layout_stack->data;
1172
- view->pango_layout_stack = g_slist_delete_link (view->pango_layout_stack,
1173
- view->pango_layout_stack);
1174
- } else
1175
- g_warning ("[LsmSvgView::show_text] Pango layout stack empty");
1176
- }
1177
-
1178
- view->is_pango_layout_in_use = FALSE;
1179
- }
1180
-
1181
- void
1182
- lsm_svg_view_show_text (LsmSvgView *view, char const *string, double x, double y)
1183
- {
1184
- LsmSvgViewPathInfos path_infos = default_path_infos;
1185
- const LsmSvgStyle *style;
1186
- gboolean need_pop;
1187
-
1188
- if (string == NULL || string[0] == '\0')
1189
- return;
1190
-
1191
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1192
-
1193
- style = view->style;
1194
-
1195
- lsm_debug_render ("[LsmSvgView::show_text] Show '%s' at %g,%g (%g px)", string, x, y, style->font_size_px);
1196
-
1197
- need_pop = _lock_pango_layout (view);
1198
-
1199
- _update_pango_layout (view, string, x, y, &path_infos);
1200
-
1201
- if (style->writing_mode->value == LSM_SVG_WRITING_MODE_TB ||
1202
- style->writing_mode->value == LSM_SVG_WRITING_MODE_TB_RL) {
1203
-
1204
- cairo_save (view->dom_view.cairo);
1205
- cairo_rotate (view->dom_view.cairo, M_PI / 2.0);
1206
- cairo_move_to (view->dom_view.cairo, path_infos.extents.x1, path_infos.extents.y1);
1207
-
1208
- process_path (view, &path_infos);
1209
-
1210
- cairo_restore (view->dom_view.cairo);
1211
- } else {
1212
- cairo_move_to (view->dom_view.cairo, path_infos.extents.x1, path_infos.extents.y1);
1213
- process_path (view, &path_infos);
1214
- }
1215
-
1216
- _unlock_pango_layout (view, need_pop);
1217
- }
1218
-
1219
- void
1220
- lsm_svg_view_text_extents (LsmSvgView *view, char const *string, double x, double y, LsmExtents *extents)
1221
- {
1222
- LsmSvgViewPathInfos path_infos = default_path_infos;
1223
- gboolean need_pop;
1224
-
1225
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1226
- g_return_if_fail (extents != NULL);
1227
-
1228
- if (string == NULL ||
1229
- string[0] == '\0') {
1230
- extents->x1 = 0;
1231
- extents->y1 = 0;
1232
- extents->y1 = 0;
1233
- extents->y2 = 0;
1234
- }
1235
-
1236
- need_pop = _lock_pango_layout (view);
1237
-
1238
- _update_pango_layout (view, string, x, y, &path_infos);
1239
-
1240
- _unlock_pango_layout (view, need_pop);
1241
-
1242
- *extents = path_infos.extents;
1243
- }
1244
-
1245
- void
1246
- lsm_svg_view_show_pixbuf (LsmSvgView *view, GdkPixbuf *pixbuf)
1247
- {
1248
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1249
- g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1250
-
1251
- lsm_cairo_set_source_pixbuf (view->dom_view.cairo, pixbuf, 0, 0);
1252
- cairo_paint (view->dom_view.cairo);
1253
- }
1254
-
1255
- void
1256
- lsm_svg_view_push_viewbox (LsmSvgView *view, const LsmBox *viewbox)
1257
- {
1258
- LsmSvgViewbox *svg_viewbox;
1259
-
1260
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1261
-
1262
- lsm_debug_render ("[LsmSvgView::push_viewbox] viewbox = %g, %g, %g, %g",
1263
- viewbox->x, viewbox->y, viewbox->width, viewbox->height);
1264
-
1265
- svg_viewbox = lsm_svg_viewbox_new (view->resolution_ppi, viewbox);
1266
-
1267
- view->viewbox_stack = g_slist_prepend (view->viewbox_stack, svg_viewbox);
1268
- }
1269
-
1270
- void
1271
- lsm_svg_view_pop_viewbox (LsmSvgView *view)
1272
- {
1273
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1274
- g_return_if_fail (view->viewbox_stack != NULL);
1275
-
1276
- lsm_debug_render ("[LsmSvgView::pop_viewbox]");
1277
-
1278
- lsm_svg_viewbox_free (view->viewbox_stack->data);
1279
- view->viewbox_stack = g_slist_delete_link (view->viewbox_stack, view->viewbox_stack);
1280
- }
1281
-
1282
- static const LsmBox *
1283
- _compute_viewbox_scale (const LsmBox *viewport, const LsmBox *viewbox,
1284
- const LsmSvgPreserveAspectRatio *aspect_ratio,
1285
- double *x_offset, double *y_offset,
1286
- double *x_scale, double *y_scale)
1287
- {
1288
- if (viewbox != NULL) {
1289
- double x, y;
1290
- double x_ratio;
1291
- double y_ratio;
1292
-
1293
- x_ratio = viewbox->width > 0.0 ? viewport->width / viewbox->width : 0.0;
1294
- y_ratio = viewbox->height > 0.0 ? viewport->height / viewbox->height : 0.0;
1295
-
1296
- if (aspect_ratio != NULL && aspect_ratio->align > LSM_SVG_ALIGN_NONE) {
1297
- if (aspect_ratio->meet_or_slice == LSM_SVG_MEET_OR_SLICE_MEET) {
1298
- *x_scale = MIN (x_ratio, y_ratio);
1299
- *y_scale = *x_scale;
1300
- } else {
1301
- *x_scale = MAX (x_ratio, y_ratio);
1302
- *y_scale = *x_scale;
1303
- }
1304
-
1305
- x = -viewbox->x * *x_scale;
1306
- y = -viewbox->y * *y_scale;
1307
-
1308
- switch (aspect_ratio->align) {
1309
- case LSM_SVG_ALIGN_X_MIN_Y_MIN:
1310
- break;
1311
- case LSM_SVG_ALIGN_X_MIN_Y_MID:
1312
- y += (viewport->height- viewbox->height * *y_scale) * 0.5;
1313
- break;
1314
- case LSM_SVG_ALIGN_X_MIN_Y_MAX:
1315
- y += (viewport->height - viewbox->height * *y_scale);
1316
- break;
1317
- case LSM_SVG_ALIGN_X_MID_Y_MIN:
1318
- x += (viewport->width - viewbox->width * *x_scale) * 0.5;
1319
- break;
1320
- case LSM_SVG_ALIGN_X_MID_Y_MID:
1321
- x += (viewport->width - viewbox->width * *x_scale) * 0.5;
1322
- y += (viewport->height- viewbox->height * *y_scale) * 0.5;
1323
- break;
1324
- case LSM_SVG_ALIGN_X_MID_Y_MAX:
1325
- x += (viewport->width - viewbox->width * *x_scale) * 0.5;
1326
- y += (viewport->height - viewbox->height * *y_scale);
1327
- break;
1328
- case LSM_SVG_ALIGN_X_MAX_Y_MIN:
1329
- x += (viewport->width - viewbox->width * *x_scale);
1330
- break;
1331
- case LSM_SVG_ALIGN_X_MAX_Y_MID:
1332
- x += (viewport->width - viewbox->width * *x_scale);
1333
- y += (viewport->height- viewbox->height * *y_scale) * 0.5;
1334
- break;
1335
- case LSM_SVG_ALIGN_X_MAX_Y_MAX:
1336
- x += (viewport->width - viewbox->width * *x_scale);
1337
- y += (viewport->height - viewbox->height * *y_scale);
1338
- break;
1339
- default:
1340
- break;
1341
- }
1342
-
1343
- *x_offset = x;
1344
- *y_offset = y;
1345
-
1346
- } else {
1347
- *x_scale = x_ratio;
1348
- *y_scale = y_ratio;
1349
-
1350
- *x_offset = -viewbox->x * *x_scale;
1351
- *y_offset = -viewbox->y * *y_scale;
1352
- }
1353
-
1354
- lsm_debug_render ("[LsmSvgView::_compute_viewbox_scale] scale = %g, %g", *x_scale, *y_scale);
1355
-
1356
- return viewbox;
1357
- }
1358
-
1359
- *x_scale = *y_scale = 1.0;
1360
- *x_offset = 0.0;
1361
- *y_offset = 0.0;
1362
-
1363
- return viewport;
1364
- }
1365
-
1366
- void
1367
- lsm_svg_view_push_viewport (LsmSvgView *view, const LsmBox *viewport, const LsmBox *viewbox,
1368
- const LsmSvgPreserveAspectRatio *aspect_ratio,
1369
- LsmSvgOverflow overflow)
1370
- {
1371
- cairo_t *cairo;
1372
- const LsmBox *actual_viewbox;
1373
- double x_offset, y_offset;
1374
- double x_scale, y_scale;
1375
-
1376
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1377
- g_return_if_fail (viewport != NULL);
1378
-
1379
- actual_viewbox = _compute_viewbox_scale (viewport, viewbox, aspect_ratio,
1380
- &x_offset, &y_offset, &x_scale, &y_scale);
1381
- lsm_svg_view_push_viewbox (view, actual_viewbox);
1382
-
1383
- cairo = view->dom_view.cairo;
1384
-
1385
- cairo_save (cairo);
1386
-
1387
- if (lsm_debug_check (&lsm_debug_category_viewport, LSM_DEBUG_LEVEL_LOG)) {
1388
- cairo_save (cairo);
1389
- cairo_set_line_width (cairo, 1.0);
1390
- cairo_set_source_rgb (cairo, 0.0, 0.0, 0.0);
1391
- cairo_rectangle (cairo, viewport->x, viewport->y, viewport->width, viewport->height);
1392
- cairo_stroke (cairo);
1393
- cairo_restore (cairo);
1394
- }
1395
-
1396
- if (overflow == LSM_SVG_OVERFLOW_HIDDEN) {
1397
- cairo_rectangle (cairo, viewport->x, viewport->y, viewport->width, viewport->height);
1398
- cairo_clip (cairo);
1399
- }
1400
-
1401
- cairo_translate (cairo, viewport->x + x_offset, viewport->y + y_offset);
1402
- cairo_scale (cairo, x_scale, y_scale);
1403
- }
1404
-
1405
- void
1406
- lsm_svg_view_pop_viewport (LsmSvgView *view)
1407
- {
1408
- cairo_restore (view->dom_view.cairo);
1409
-
1410
- lsm_svg_view_pop_viewbox (view);
1411
- }
1412
-
1413
- void
1414
- lsm_svg_view_viewbox_to_viewport (LsmSvgView *view, const LsmBox *viewport, const LsmBox *viewbox,
1415
- const LsmSvgPreserveAspectRatio *aspect_ratio,
1416
- double *x, double *y)
1417
- {
1418
- double x_offset, y_offset;
1419
- double x_scale, y_scale;
1420
-
1421
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1422
- g_return_if_fail (viewport != NULL);
1423
-
1424
- _compute_viewbox_scale (viewport, viewbox, aspect_ratio,
1425
- &x_offset, &y_offset, &x_scale, &y_scale);
1426
-
1427
- if (x != NULL)
1428
- *x = *x * x_scale + x_offset;
1429
-
1430
- if (y != NULL)
1431
- *y = *y * y_scale + y_offset;
1432
- }
1433
-
1434
- gboolean
1435
- lsm_svg_view_push_matrix (LsmSvgView *view, const LsmSvgMatrix *matrix)
1436
- {
1437
- cairo_matrix_t cr_matrix;
1438
- cairo_matrix_t cr_inv_matrix;
1439
- cairo_matrix_t *ctm;
1440
- cairo_status_t status;
1441
-
1442
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), FALSE);
1443
-
1444
- ctm = g_new (cairo_matrix_t, 1);
1445
- cairo_get_matrix (view->dom_view.cairo, ctm);
1446
-
1447
- view->matrix_stack = g_slist_prepend (view->matrix_stack, ctm);
1448
-
1449
- lsm_debug_render ("[LsmSvgView::push_matrix] New transform %g, %g, %g, %g, %g, %g",
1450
- matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f);
1451
-
1452
- cairo_matrix_init (&cr_matrix, matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f);
1453
- cr_inv_matrix = cr_matrix;
1454
- status = cairo_matrix_invert (&cr_inv_matrix) == CAIRO_STATUS_SUCCESS;
1455
-
1456
- if (status == CAIRO_STATUS_SUCCESS) {
1457
- lsm_debug_render ("[LsmSvgView::push_matrix] Not invertible matrix");
1458
- return FALSE;
1459
- }
1460
-
1461
- cairo_transform (view->dom_view.cairo, &cr_matrix);
1462
-
1463
- {
1464
- cairo_matrix_t current_ctm;
1465
- cairo_get_matrix (view->dom_view.cairo, &current_ctm);
1466
-
1467
- lsm_debug_render ("[LsmSvgView::push_matrix] Current ctm %g, %g, %g, %g, %g, %g",
1468
- current_ctm.xx, current_ctm.xy, current_ctm.yx, current_ctm.yy,
1469
- current_ctm.x0, current_ctm.y0);
1470
- }
1471
-
1472
- return TRUE;
1473
- }
1474
-
1475
- void
1476
- lsm_svg_view_pop_matrix (LsmSvgView *view)
1477
- {
1478
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1479
-
1480
- if (view->matrix_stack != NULL) {
1481
- cairo_matrix_t *ctm;
1482
-
1483
- ctm = view->matrix_stack->data;
1484
-
1485
- cairo_set_matrix (view->dom_view.cairo, ctm);
1486
-
1487
- lsm_debug_render ("[LsmSvgView::pop_matrix] Restore ctm %g, %g, %g, %g, %g, %g",
1488
- ctm->xx, ctm->xy, ctm->yx, ctm->yy,
1489
- ctm->x0, ctm->y0);
1490
-
1491
- g_free (ctm);
1492
- view->matrix_stack = g_slist_delete_link (view->matrix_stack, view->matrix_stack);
1493
- }
1494
- }
1495
-
1496
- static void
1497
- lsm_svg_view_push_clip (LsmSvgView *view)
1498
- {
1499
- LsmSvgElement *element;
1500
- LsmExtents extents;
1501
- char *url;
1502
-
1503
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1504
- g_return_if_fail (!view->is_clipping);
1505
-
1506
- lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
1507
-
1508
- url = view->style->clip_path->value;
1509
-
1510
- lsm_debug_render ("[LsmSvgView::push_clip] Using '%s'", url);
1511
-
1512
- cairo_save (view->dom_view.cairo);
1513
-
1514
- view->clip_extents.x = extents.x1;
1515
- view->clip_extents.y = extents.y1;
1516
- view->clip_extents.width = extents.x2 - extents.x1;
1517
- view->clip_extents.height = extents.y2 - extents.y1;
1518
-
1519
- lsm_debug_render ("[LsmSvgView::push_clip] x=%g y=%g w=%g h=%g",
1520
- view->clip_extents.x,
1521
- view->clip_extents.y,
1522
- view->clip_extents.width,
1523
- view->clip_extents.height);
1524
-
1525
- element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document), url);
1526
- if (LSM_IS_SVG_CLIP_PATH_ELEMENT (element) &&
1527
- !lsm_svg_view_circular_reference_check (view, element)) {
1528
- view->is_clipping = TRUE;
1529
- lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
1530
- cairo_clip (view->dom_view.cairo);
1531
- view->is_clipping = FALSE;
1532
- } else
1533
- lsm_warning_render ("[LsmSvgView::push_clip] Clip path not found: %s", view->style->clip_path->value);
1534
- }
1535
-
1536
- static void
1537
- lsm_svg_view_pop_clip (LsmSvgView *view)
1538
- {
1539
- lsm_debug_render ("[LsmSvgView::pop_clip");
1540
-
1541
- cairo_restore (view->dom_view.cairo);
1542
- }
1543
-
1544
- static void
1545
- lsm_svg_view_push_mask (LsmSvgView *view)
1546
- {
1547
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1548
-
1549
- cairo_push_group (view->dom_view.cairo);
1550
- }
1551
-
1552
- static void
1553
- lsm_svg_view_pop_mask (LsmSvgView *view)
1554
- {
1555
- LsmSvgElement *mask_element;
1556
-
1557
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1558
-
1559
- mask_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
1560
- view->style->mask->value);
1561
-
1562
- if (LSM_IS_SVG_MASK_ELEMENT (mask_element) &&
1563
- !lsm_svg_view_circular_reference_check (view, mask_element)) {
1564
- LsmExtents extents;
1565
- LsmBox mask_extents;
1566
- cairo_t *cairo;
1567
-
1568
- lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
1569
-
1570
- mask_extents.x = extents.x1;
1571
- mask_extents.y = extents.y1;
1572
- mask_extents.width = extents.x2 - extents.x1;
1573
- mask_extents.height = extents.y2 - extents.y1;
1574
-
1575
- cairo = view->dom_view.cairo;
1576
-
1577
- _start_pattern (view, &mask_extents, &mask_extents, 1.0);
1578
-
1579
- lsm_svg_element_force_render (LSM_SVG_ELEMENT (mask_element), view);
1580
-
1581
- cairo_pop_group_to_source (cairo);
1582
- if (view->pattern_data->pattern != NULL) {
1583
- cairo_surface_t *surface;
1584
- int width, height, row, i, stride;
1585
- unsigned char *pixels;
1586
-
1587
- cairo_pattern_get_surface (view->pattern_data->pattern, &surface);
1588
- pixels = cairo_image_surface_get_data (surface);
1589
- height = cairo_image_surface_get_height (surface);
1590
- width = cairo_image_surface_get_width (surface);
1591
- stride = cairo_image_surface_get_stride (surface);
1592
-
1593
- for (row = 0; row < height; row++) {
1594
- guint8 *row_data = (pixels + (row * stride));
1595
- for (i = 0; i < width; i++) {
1596
- guint32 *pixel = (guint32 *) row_data + i;
1597
- *pixel = ((((*pixel & 0x00ff0000) >> 16) * 13817 +
1598
- ((*pixel & 0x0000ff00) >> 8) * 46518 +
1599
- ((*pixel & 0x000000ff)) * 4688) * 0xff
1600
- /* * opacity */);
1601
- }
1602
- }
1603
-
1604
- cairo_pattern_set_extend (view->pattern_data->pattern, CAIRO_EXTEND_NONE);
1605
-
1606
- if (view->debug_mask && view->dom_view.cairo != NULL) {
1607
- char *filename;
1608
-
1609
- filename = g_strdup_printf ("mask-%s.png", view->style->mask->value);
1610
- cairo_surface_write_to_png (cairo_get_target (view->dom_view.cairo), filename);
1611
- g_free (filename);
1612
- }
1613
-
1614
- cairo_mask (cairo, view->pattern_data->pattern);
1615
- } else {
1616
- cairo_paint (cairo);
1617
- }
1618
-
1619
- _end_pattern (view);
1620
- } else {
1621
- lsm_warning_render ("[LsmSvgView::pop_mask] Mask url nout found: %s", view->style->mask->value);
1622
-
1623
- cairo_pop_group_to_source (view->dom_view.cairo);
1624
- cairo_paint (view->dom_view.cairo);
1625
- }
1626
- }
1627
-
1628
- void
1629
- lsm_svg_view_push_filter (LsmSvgView *view)
1630
- {
1631
- LsmExtents extents;
1632
- LsmBox object_extents;
1633
- LsmBox effect_viewport;
1634
- LsmSvgElement *filter_element;
1635
- gboolean success;
1636
-
1637
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1638
- g_return_if_fail (view->element_stack != NULL);
1639
-
1640
- lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
1641
-
1642
- object_extents.x = extents.x1;
1643
- object_extents.y = extents.y1;
1644
- object_extents.width = extents.x2 - extents.x1;
1645
- object_extents.height = extents.y2 - extents.y1;
1646
-
1647
- filter_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
1648
- view->style->filter->value);
1649
-
1650
- if (LSM_IS_SVG_FILTER_ELEMENT (filter_element)) {
1651
- effect_viewport = lsm_svg_filter_element_get_effect_viewport (LSM_SVG_FILTER_ELEMENT (filter_element),
1652
- &object_extents, view);
1653
-
1654
- _start_pattern (view, &effect_viewport, &object_extents,
1655
- view->style->opacity != NULL ? view->style->opacity->value : 1.0);
1656
-
1657
- success = lsm_svg_view_create_surface_pattern (view,
1658
- &effect_viewport,
1659
- NULL,
1660
- LSM_SVG_VIEW_SURFACE_TYPE_IMAGE);
1661
- } else {
1662
- lsm_warning_render ("LsmSvgView::push_filter] Filter not found: %s", view->style->filter->value);
1663
-
1664
- _start_pattern (view, &object_extents, &object_extents, 0.0);
1665
-
1666
- success = lsm_svg_view_create_surface_pattern (view,
1667
- &object_extents,
1668
- NULL,
1669
- LSM_SVG_VIEW_SURFACE_TYPE_IMAGE);
1670
- }
1671
-
1672
- if (!success)
1673
- lsm_warning_render ("LsmSvgView::push_filter] Failed to create subsurface");
1674
- }
1675
-
1676
- void
1677
- lsm_svg_view_pop_filter (LsmSvgView *view)
1678
- {
1679
- LsmSvgElement *filter_element;
1680
- LsmSvgFilterSurface *filter_surface;
1681
- cairo_surface_t *surface;
1682
- GSList *iter;
1683
-
1684
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1685
-
1686
- filter_element = lsm_svg_document_get_element_by_url (LSM_SVG_DOCUMENT (view->dom_view.document),
1687
- view->style->filter->value);
1688
-
1689
- if (LSM_IS_SVG_FILTER_ELEMENT (filter_element) &&
1690
- view->pattern_data->pattern != NULL) {
1691
- cairo_matrix_t matrix;
1692
- LsmBox subregion;
1693
-
1694
- view->filter_surfaces = NULL;
1695
-
1696
- cairo_pattern_get_surface (view->pattern_data->pattern, &surface);
1697
-
1698
- subregion.x = 0;
1699
- subregion.y = 0;
1700
- subregion.width = cairo_image_surface_get_width (surface);
1701
- subregion.height = cairo_image_surface_get_height (surface);
1702
-
1703
- filter_surface = lsm_svg_filter_surface_new_with_content ("SourceGraphic", surface, &subregion);
1704
- cairo_pattern_get_matrix (view->pattern_data->pattern, &matrix);
1705
-
1706
- view->filter_surfaces = g_slist_prepend (view->filter_surfaces, filter_surface);
1707
-
1708
- lsm_svg_element_force_render (filter_element, view);
1709
-
1710
- if (view->debug_filter) {
1711
- GSList *iter;
1712
- char *filename;
1713
- static int count = 0;
1714
-
1715
- for (iter = view->filter_surfaces; iter != NULL; iter = iter->next) {
1716
- LsmSvgFilterSurface *surface = iter->data;
1717
-
1718
- filename = g_strdup_printf ("filter-%04d-%s-%s.png", count++,
1719
- view->style->filter->value,
1720
- lsm_svg_filter_surface_get_name (surface));
1721
- cairo_surface_write_to_png (lsm_svg_filter_surface_get_cairo_surface (surface), filename);
1722
- g_free (filename);
1723
- }
1724
- }
1725
-
1726
- if (view->filter_surfaces->next != NULL) {
1727
- cairo_pattern_t *pattern;
1728
- cairo_surface_t *surface;
1729
-
1730
- surface = lsm_svg_filter_surface_get_cairo_surface (view->filter_surfaces->data);
1731
- pattern = cairo_pattern_create_for_surface (surface);
1732
- cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
1733
- cairo_pattern_set_matrix (pattern, &matrix);
1734
- cairo_set_source (view->pattern_data->old_cairo, pattern);
1735
- cairo_pattern_destroy (pattern);
1736
- cairo_paint_with_alpha (view->pattern_data->old_cairo, view->style->opacity->value);
1737
- }
1738
-
1739
- for (iter = view->filter_surfaces; iter != NULL; iter = iter->next)
1740
- lsm_svg_filter_surface_unref (iter->data);
1741
- g_slist_free (view->filter_surfaces);
1742
- view->filter_surfaces = NULL;
1743
- }
1744
-
1745
- _end_pattern (view);
1746
- }
1747
-
1748
- static LsmSvgFilterSurface *
1749
- _get_filter_surface (LsmSvgView *view, const char *input)
1750
- {
1751
- GSList *iter;
1752
- LsmSvgFilterSurface *source_surface = NULL;
1753
-
1754
- if (input == NULL)
1755
- return view->filter_surfaces->data;
1756
-
1757
- for (iter = view->filter_surfaces; iter != NULL; iter = iter->next) {
1758
- LsmSvgFilterSurface *surface = iter->data;
1759
-
1760
- if (g_strcmp0 (input, lsm_svg_filter_surface_get_name (surface)) == 0)
1761
- return surface;
1762
-
1763
- source_surface = surface;
1764
- }
1765
-
1766
- if (g_strcmp0 (input, "SourceAlpha") == 0 && source_surface != NULL) {
1767
- LsmSvgFilterSurface *surface;
1768
-
1769
- surface = lsm_svg_filter_surface_new_similar ("SourceAlpha", source_surface, NULL);
1770
- lsm_svg_filter_surface_alpha (source_surface, surface);
1771
- view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);
1772
-
1773
- return surface;
1774
- } else if (g_strcmp0 (input, "BackgroundImage") == 0) {
1775
- LsmSvgFilterSurface *surface;
1776
- LsmSvgViewBackground *background;
1777
- gboolean background_processing = FALSE;
1778
- cairo_matrix_t matrix;
1779
- cairo_matrix_t pattern_matrix;
1780
- cairo_t *cairo;
1781
- GList *iter;
1782
-
1783
- for (iter = view->background_stack; iter != NULL; iter = iter->next) {
1784
- background = iter->data;
1785
-
1786
- if (background->enable_background) {
1787
- background_processing = TRUE;
1788
- break;
1789
- }
1790
- }
1791
-
1792
- if (!background_processing) {
1793
- lsm_debug_render ("[LsmSvgView::_get_filter_surface] Background processing not enabled");
1794
- return NULL;
1795
- }
1796
-
1797
- surface = lsm_svg_filter_surface_new_similar ("BackgroundImage", source_surface, NULL);
1798
- view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);
1799
-
1800
- cairo_get_matrix (view->pattern_data->old_cairo, &matrix);
1801
- cairo_pattern_get_matrix (view->pattern_data->pattern, &pattern_matrix);
1802
-
1803
- cairo_matrix_invert (&matrix);
1804
- cairo_matrix_multiply (&matrix, &matrix, &pattern_matrix);
1805
-
1806
- lsm_debug_render ("[LsmSvgView::_get_filter_surface] Background image matrix %g, %g, %g, %g, %g, %g",
1807
- matrix.xx, matrix.xy, matrix.yx, matrix.yy,
1808
- matrix.x0, matrix.y0);
1809
-
1810
- cairo = cairo_create (lsm_svg_filter_surface_get_cairo_surface (surface));
1811
- cairo_set_matrix (cairo, &matrix);
1812
-
1813
- for (; iter != NULL; iter = iter->prev) {
1814
- background = iter->data;
1815
-
1816
- cairo_set_source_surface (cairo, background->surface, 0, 0);
1817
- cairo_paint_with_alpha (cairo, background->group_opacity);
1818
- }
1819
-
1820
- cairo_destroy (cairo);
1821
-
1822
- return surface;
1823
- } else if (g_strcmp0 (input, "BackgroundAlpha") == 0) {
1824
- LsmSvgFilterSurface *surface;
1825
- LsmSvgFilterSurface *background_surface;
1826
-
1827
- if (view->background_stack == NULL)
1828
- return NULL;
1829
-
1830
- background_surface = _get_filter_surface (view, "BackgroundImage");
1831
-
1832
- surface = lsm_svg_filter_surface_new_similar ("BackgroundAlpha", background_surface, NULL);
1833
- lsm_svg_filter_surface_alpha (background_surface, surface);
1834
- view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);
1835
-
1836
- return surface;
1837
- }
1838
-
1839
- return NULL;
1840
- }
1841
-
1842
- static LsmSvgFilterSurface *
1843
- _create_filter_surface (LsmSvgView *view, const char *output, LsmSvgFilterSurface *input_surface, const LsmBox *subregion)
1844
- {
1845
- LsmSvgFilterSurface *surface;
1846
-
1847
- surface = lsm_svg_filter_surface_new_similar (output, input_surface, subregion);
1848
-
1849
- view->filter_surfaces = g_slist_prepend (view->filter_surfaces, surface);
1850
-
1851
- return surface;
1852
- }
1853
-
1854
- LsmBox
1855
- lsm_svg_view_get_filter_surface_extents (LsmSvgView *view, const char *name)
1856
- {
1857
- static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
1858
- LsmSvgFilterSurface *surface;
1859
- LsmBox extents;
1860
-
1861
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), null_extents);
1862
-
1863
- surface = _get_filter_surface (view, name);
1864
- if (surface == NULL)
1865
- return null_extents;
1866
-
1867
- lsm_cairo_box_device_to_user (view->dom_view.cairo, &extents, lsm_svg_filter_surface_get_subregion (surface));
1868
-
1869
- return extents;
1870
- }
1871
-
1872
- void
1873
- lsm_svg_view_apply_blend (LsmSvgView *view, const char *input_1, const char*input_2, const char *output,
1874
- const LsmBox *subregion, LsmSvgBlendingMode mode)
1875
- {
1876
- LsmSvgFilterSurface *output_surface;
1877
- LsmSvgFilterSurface *input_1_surface;
1878
- LsmSvgFilterSurface *input_2_surface;
1879
- LsmBox subregion_px;
1880
-
1881
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1882
-
1883
- input_1_surface = _get_filter_surface (view, input_1);
1884
- input_2_surface = _get_filter_surface (view, input_2);
1885
-
1886
- if (input_1_surface == NULL || input_2_surface == NULL) {
1887
- lsm_warning_render ("[SvgView::apply_blend] Inputs '%s' or '%s' not found", input_1, input_2);
1888
- return;
1889
- }
1890
-
1891
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
1892
- output_surface = _create_filter_surface (view, output, input_1_surface, &subregion_px);
1893
-
1894
- lsm_log_render ("[SvgView::blend] mode = %s", lsm_svg_blending_mode_to_string (mode));
1895
-
1896
- lsm_svg_filter_surface_blend (input_1_surface, input_2_surface, output_surface, mode);
1897
- }
1898
-
1899
- void
1900
- lsm_svg_view_apply_flood (LsmSvgView *view, const char *output, const LsmBox *subregion)
1901
- {
1902
- LsmSvgFilterSurface *output_surface;
1903
- LsmSvgFilterSurface *input_surface;
1904
- LsmBox subregion_px;
1905
-
1906
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1907
-
1908
- input_surface = _get_filter_surface (view, NULL);
1909
-
1910
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
1911
- output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
1912
-
1913
- lsm_log_render ("[SvgView::apply_flood] subregion %gx%g px at %g,%g px",
1914
- subregion_px.width, subregion_px.height,
1915
- subregion_px.x, subregion_px.y);
1916
-
1917
- lsm_svg_filter_surface_flood (output_surface,
1918
- view->style->flood_color->value.red,
1919
- view->style->flood_color->value.green,
1920
- view->style->flood_color->value.blue,
1921
- view->style->flood_opacity->value);
1922
- }
1923
-
1924
- void
1925
- lsm_svg_view_apply_gaussian_blur (LsmSvgView *view, const char *input, const char *output,
1926
- const LsmBox *subregion, double std_x, double std_y)
1927
- {
1928
- LsmSvgFilterSurface *input_surface;
1929
- LsmSvgFilterSurface *output_surface;
1930
- LsmBox subregion_px;
1931
-
1932
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1933
-
1934
- input_surface = _get_filter_surface (view, input);
1935
-
1936
- if (input_surface == NULL) {
1937
- lsm_debug_render ("[SvgView::apply_gaussian_blur] Input '%s' not found", input);
1938
- return;
1939
- }
1940
-
1941
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
1942
- output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
1943
-
1944
- lsm_log_render ("[SvgView::apply_gaussian_blur] %s -> %s (%g,%g)",
1945
- input != NULL ? input : "previous",
1946
- output != NULL ? output : "next",
1947
- std_x, std_y);
1948
-
1949
- cairo_user_to_device_distance (view->dom_view.cairo, &std_x, &std_y);
1950
-
1951
- lsm_log_render ("[SvgView::apply_gaussian_blur] %g px,%g px",
1952
- std_x, std_y);
1953
-
1954
- lsm_svg_filter_surface_fast_blur (input_surface, output_surface, std_x, std_y);
1955
- }
1956
-
1957
- void
1958
- lsm_svg_view_apply_offset (LsmSvgView *view, const char *input, const char *output,
1959
- const LsmBox *subregion, double dx, double dy)
1960
- {
1961
- LsmSvgFilterSurface *input_surface;
1962
- LsmSvgFilterSurface *output_surface;
1963
- LsmBox subregion_px;
1964
-
1965
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1966
-
1967
- input_surface = _get_filter_surface (view, input);
1968
-
1969
- if (input_surface == NULL) {
1970
- lsm_debug_render ("[SvgView::apply_offset] Input '%s' not found", input);
1971
- return;
1972
- }
1973
-
1974
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
1975
- output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
1976
-
1977
- lsm_log_render ("[SvgView::apply_offset] %s -> %s (dx:%g,dy:%g)", input, output, dx, dy);
1978
-
1979
- cairo_user_to_device_distance (view->dom_view.cairo, &dx, &dy);
1980
-
1981
- lsm_log_render ("[SvgView::apply_offset] %g px,%g px", dx, dy);
1982
-
1983
- lsm_svg_filter_surface_offset (input_surface, output_surface, dx, dy);
1984
- }
1985
-
1986
- void
1987
- lsm_svg_view_apply_merge (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
1988
- {
1989
- LsmSvgFilterSurface *input_surface;
1990
- LsmSvgFilterSurface *output_surface;
1991
- LsmBox subregion_px;
1992
-
1993
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
1994
-
1995
- input_surface = _get_filter_surface (view, input);
1996
-
1997
- if (input_surface == NULL) {
1998
- lsm_debug_render ("[SvgView::apply_offset] Input '%s' not found", input);
1999
- return;
2000
- }
2001
-
2002
- output_surface = _get_filter_surface (view, output);
2003
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
2004
- if (output_surface == NULL)
2005
- output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
2006
-
2007
- if (output_surface != NULL)
2008
- lsm_svg_filter_surface_merge (input_surface, output_surface);
2009
- }
2010
-
2011
- void
2012
- lsm_svg_view_apply_tile (LsmSvgView *view, const char *input, const char *output, const LsmBox *subregion)
2013
- {
2014
- LsmSvgFilterSurface *input_surface;
2015
- LsmSvgFilterSurface *output_surface;
2016
- LsmBox subregion_px;
2017
-
2018
- input_surface = _get_filter_surface (view, input);
2019
-
2020
- if (input_surface == NULL) {
2021
- lsm_debug_render ("[SvgView::apply_offset] Input '%s' not found", input);
2022
- return;
2023
- }
2024
-
2025
- lsm_cairo_box_user_to_device (view->dom_view.cairo, &subregion_px, subregion);
2026
- output_surface = _create_filter_surface (view, output, input_surface, &subregion_px);
2027
-
2028
- lsm_svg_filter_surface_tile (input_surface, output_surface);
2029
- }
2030
-
2031
- void
2032
- lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
2033
- {
2034
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2035
- g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
2036
-
2037
- view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
2038
- }
2039
-
2040
- void
2041
- lsm_svg_view_pop_element (LsmSvgView *view)
2042
- {
2043
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2044
- g_return_if_fail (view->element_stack != NULL);
2045
-
2046
- view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
2047
- }
2048
-
2049
- static gboolean
2050
- lsm_svg_view_circular_reference_check (LsmSvgView *view, LsmSvgElement *element)
2051
- {
2052
- GSList *iter;
2053
-
2054
- for (iter = view->element_stack; iter != NULL; iter = iter->next)
2055
- if (iter->data == element) {
2056
- lsm_debug_render ("[LsmSvgView::circular_reference_check] "
2057
- "Circular reference to %s (id = %s)",
2058
- lsm_dom_element_get_tag_name (LSM_DOM_ELEMENT (element)),
2059
- lsm_dom_element_get_attribute (LSM_DOM_ELEMENT (element), "id"));
2060
- return TRUE;
2061
- }
2062
-
2063
- return FALSE;
2064
- }
2065
-
2066
- void
2067
- lsm_svg_view_push_style (LsmSvgView *view, LsmSvgStyle *style)
2068
- {
2069
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2070
- g_return_if_fail (style != NULL);
2071
-
2072
- lsm_log_render ("[SvgView::push_style]");
2073
-
2074
- if (view->style == NULL || (style->font_size != view->style->font_size)) {
2075
- LsmSvgViewbox font_viewbox;
2076
- LsmSvgViewbox *viewbox;
2077
- double current_font_size_px;
2078
-
2079
- if (view->style != NULL)
2080
- current_font_size_px = view->style->font_size_px;
2081
- else
2082
- current_font_size_px = 0.0;
2083
-
2084
- viewbox = view->viewbox_stack->data;
2085
- font_viewbox.resolution_ppi = viewbox->resolution_ppi;
2086
- font_viewbox.viewbox.x = 0;
2087
- font_viewbox.viewbox.y = 0;
2088
- font_viewbox.viewbox.width = current_font_size_px;
2089
- font_viewbox.viewbox.height = current_font_size_px;
2090
-
2091
- style->font_size_px = lsm_svg_length_normalize (&style->font_size->length, &font_viewbox,
2092
- current_font_size_px, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
2093
-
2094
- if (style->font_size_px < 0.0)
2095
- style->font_size_px = 0.0;
2096
- lsm_log_render ("[SvgView::push_style] Font size = %g pixels", style->font_size_px);
2097
- } else
2098
- style->font_size_px = view->style->font_size_px;
2099
-
2100
- view->style_stack = g_slist_prepend (view->style_stack, (void *) style);
2101
- view->style = style;
2102
-
2103
- }
2104
-
2105
- void
2106
- lsm_svg_view_push_composition (LsmSvgView *view, LsmSvgStyle *style)
2107
- {
2108
- gboolean do_filter;
2109
- gboolean do_mask;
2110
- gboolean do_clip;
2111
-
2112
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2113
- g_return_if_fail (style != NULL);
2114
-
2115
- lsm_svg_view_push_style (view, style);
2116
-
2117
- lsm_log_render ("[SvgView::push_composition]");
2118
-
2119
- do_clip = (g_strcmp0 (style->clip_path->value, "none") != 0);
2120
- do_mask = (g_strcmp0 (style->mask->value, "none") != 0);
2121
- do_filter = (g_strcmp0 (style->filter->value, "none") != 0);
2122
-
2123
- if (G_UNLIKELY((view->style->opacity->value < 1.0 ||
2124
- view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
2125
- view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
2126
- !do_filter &&
2127
- !view->is_clipping &&
2128
- !view->style->ignore_group_opacity &&
2129
- view->dom_view.cairo != NULL)) {
2130
- LsmSvgViewBackground *background;
2131
-
2132
- lsm_debug_render ("[LsmSvgView::push_composition] Push group");
2133
- cairo_push_group (view->dom_view.cairo);
2134
-
2135
- background = g_slice_new (LsmSvgViewBackground);
2136
- background->surface = cairo_get_group_target (view->dom_view.cairo);
2137
- background->group_opacity = view->style->opacity->value;
2138
- background->enable_background = view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW;
2139
-
2140
- view->background_stack = g_list_prepend (view->background_stack, background);
2141
- }
2142
-
2143
- if (G_UNLIKELY (do_clip)) {
2144
- lsm_debug_render ("[LsmSvgView::push_style] Start clip '%s'", style->clip_path->value);
2145
- lsm_svg_view_push_clip (view);
2146
- }
2147
-
2148
- if (G_UNLIKELY (do_mask)) {
2149
- lsm_debug_render ("[LsmSvgView::push_style] Start mask '%s'", style->mask->value);
2150
- lsm_svg_view_push_mask (view);
2151
- }
2152
-
2153
- /* Don't do filtering during a clipping operation, as filter will
2154
- * create a new subsurface, where clipping should occur with the path
2155
- * of the clip-path element. */
2156
- if (G_UNLIKELY (do_filter && !view->is_clipping)) {
2157
- lsm_debug_render ("[LsmSvgView::push_style] Start filter '%s'", style->filter->value);
2158
- lsm_svg_view_push_filter (view);
2159
- }
2160
- }
2161
-
2162
- void lsm_svg_view_pop_style (LsmSvgView *view)
2163
- {
2164
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2165
- g_return_if_fail (view->style_stack != NULL);
2166
-
2167
- view->style_stack = g_slist_delete_link (view->style_stack, view->style_stack);
2168
- view->style = view->style_stack != NULL ? view->style_stack->data : NULL;
2169
-
2170
- lsm_log_render ("[SvgView::pop_style]");
2171
- }
2172
-
2173
- void lsm_svg_view_pop_composition (LsmSvgView *view)
2174
- {
2175
- gboolean do_filter;
2176
- gboolean do_mask;
2177
- gboolean do_clip;
2178
- cairo_t *cairo;
2179
-
2180
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
2181
- g_return_if_fail (view->style != NULL);
2182
-
2183
- lsm_log_render ("[SvgView::pop_composition]");
2184
-
2185
- do_clip = (g_strcmp0 (view->style->clip_path->value, "none") != 0);
2186
- do_mask = (g_strcmp0 (view->style->mask->value, "none") != 0);
2187
- do_filter = (g_strcmp0 (view->style->filter->value, "none") != 0);
2188
-
2189
- /* Don't do filtering during a clipping operation, as filter will
2190
- * create a new subsurface, where clipping should occur with the path
2191
- * of the clip-path element. */
2192
- if (G_UNLIKELY (do_filter && !view->is_clipping))
2193
- lsm_svg_view_pop_filter (view);
2194
-
2195
- if (G_UNLIKELY (do_mask))
2196
- lsm_svg_view_pop_mask (view);
2197
-
2198
- if (G_UNLIKELY (do_clip))
2199
- lsm_svg_view_pop_clip (view);
2200
-
2201
- cairo = view->dom_view.cairo;
2202
-
2203
- if (G_UNLIKELY ((view->style->opacity->value < 1.0 ||
2204
- view->style->enable_background->value == LSM_SVG_ENABLE_BACKGROUND_NEW ||
2205
- view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER) &&
2206
- !do_filter &&
2207
- !view->is_clipping &&
2208
- !view->style->ignore_group_opacity &&
2209
- cairo != NULL)) {
2210
- g_slice_free (LsmSvgViewBackground, view->background_stack->data);
2211
- view->background_stack = g_list_delete_link (view->background_stack, view->background_stack);
2212
-
2213
- cairo_pop_group_to_source (view->dom_view.cairo);
2214
- if (G_UNLIKELY (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
2215
- lsm_cairo_set_comp_op (cairo, view->style->comp_op->value);
2216
- cairo_paint_with_alpha (cairo, view->style->opacity->value);
2217
- if (G_UNLIKELY (view->style->comp_op->value != LSM_SVG_COMP_OP_SRC_OVER))
2218
- lsm_cairo_set_comp_op (cairo, LSM_SVG_COMP_OP_SRC_OVER);
2219
- lsm_debug_render ("[LsmSvgView::pop_composition] Pop group");
2220
- }
2221
-
2222
- lsm_svg_view_pop_style (view);
2223
- }
2224
-
2225
- LsmSvgStyle *
2226
- lsm_svg_view_get_current_style (LsmSvgView *view)
2227
- {
2228
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
2229
-
2230
- return (LsmSvgStyle *) view->style;
2231
- }
2232
-
2233
- const LsmBox *
2234
- lsm_svg_view_get_pattern_extents (LsmSvgView *view)
2235
- {
2236
- static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
2237
-
2238
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), &null_extents);
2239
- g_return_val_if_fail (view->pattern_data != NULL, &null_extents);
2240
-
2241
- return &view->pattern_data->extents;
2242
- }
2243
-
2244
- const LsmBox *
2245
- lsm_svg_view_get_object_extents (LsmSvgView *view)
2246
- {
2247
- static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
2248
-
2249
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), &null_extents);
2250
- g_return_val_if_fail (view->pattern_data != NULL, &null_extents);
2251
-
2252
- return &view->pattern_data->object_extents;
2253
- }
2254
-
2255
- const LsmBox *
2256
- lsm_svg_view_get_clip_extents (LsmSvgView *view)
2257
- {
2258
- static LsmBox null_extents = {.x = 0.0, .y = 0.0, .width = 0.0, .height = 0.0};
2259
-
2260
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), &null_extents);
2261
- g_return_val_if_fail (view->is_clipping, &null_extents);
2262
-
2263
- return &view->clip_extents;
2264
- }
2265
-
2266
- static void
2267
- lsm_svg_view_measure (LsmDomView *view, double *width, double *height, double *baseline)
2268
- {
2269
- LsmSvgSvgElement *svg_element;
2270
-
2271
- svg_element = lsm_svg_document_get_root_element (LSM_SVG_DOCUMENT (view->document));
2272
- if (svg_element == NULL)
2273
- return;
2274
-
2275
- lsm_svg_svg_element_measure (svg_element, LSM_SVG_VIEW (view), width, height);
2276
- if (baseline)
2277
- *baseline = *height;
2278
- }
2279
-
2280
- static void
2281
- lsm_svg_view_render (LsmDomView *view)
2282
- {
2283
- LsmSvgView *svg_view;
2284
- LsmSvgSvgElement *svg_element;
2285
-
2286
- svg_view = LSM_SVG_VIEW (view);
2287
-
2288
- svg_element = lsm_svg_document_get_root_element (LSM_SVG_DOCUMENT (view->document));
2289
- if (svg_element == NULL)
2290
- return;
2291
-
2292
- svg_view->style_stack = NULL;
2293
- svg_view->element_stack = NULL;
2294
- svg_view->viewbox_stack = NULL;
2295
- svg_view->matrix_stack = NULL;
2296
- svg_view->pango_layout_stack = NULL;
2297
- svg_view->background_stack = NULL;
2298
-
2299
- svg_view->is_clipping = FALSE;
2300
- svg_view->is_pango_layout_in_use = FALSE;
2301
- svg_view->pango_layout = view->pango_layout;
2302
-
2303
- svg_view->resolution_ppi = lsm_dom_view_get_resolution (view);
2304
-
2305
- lsm_svg_svg_element_render (svg_element, svg_view);
2306
-
2307
- if (svg_view->is_pango_layout_in_use)
2308
- g_warning ("[LsmSvgView::render] Unfinished text redenring");
2309
-
2310
- if (svg_view->is_clipping)
2311
- g_warning ("[LsmSvgView::render] Unfinished clipping");
2312
-
2313
- if (svg_view->pango_layout_stack != NULL) {
2314
- g_warning ("[LsmSvgView::render] Dangling pango_layout in stack");
2315
- g_slist_free (svg_view->pango_layout_stack);
2316
- svg_view->pango_layout_stack = NULL;
2317
- }
2318
-
2319
- if (svg_view->matrix_stack != NULL) {
2320
- g_warning ("[LsmSvgView::render] Dangling matrix in stack");
2321
- g_slist_free (svg_view->matrix_stack);
2322
- svg_view->matrix_stack = NULL;
2323
- }
2324
- if (svg_view->viewbox_stack != NULL) {
2325
- g_warning ("[LsmSvgView::render] Dangling viewport in stack");
2326
- g_slist_free (svg_view->viewbox_stack);
2327
- svg_view->viewbox_stack = NULL;
2328
- }
2329
- if (svg_view->element_stack != NULL) {
2330
- g_warning ("[LsmSvgView::render] Dangling element in stack");
2331
- g_slist_free (svg_view->element_stack);
2332
- svg_view->element_stack = NULL;
2333
- }
2334
- if (svg_view->style_stack != NULL) {
2335
- g_warning ("[LsmSvgView::render] Dangling style in stack");
2336
- g_slist_free (svg_view->style_stack);
2337
- svg_view->style_stack = NULL;
2338
- }
2339
- if (svg_view->background_stack != NULL) {
2340
- g_warning ("[LsmSvgView::render] Dangling background in stack");
2341
- g_list_free (svg_view->background_stack);
2342
- svg_view->background_stack = NULL;
2343
- }
2344
- }
2345
-
2346
- static void
2347
- lsm_svg_view_set_debug (LsmDomView *view, const char *feature, gboolean enable)
2348
- {
2349
- LsmSvgView *svg_view = LSM_SVG_VIEW (view);
2350
-
2351
- if (g_strcmp0 (feature, "filter") == 0)
2352
- svg_view->debug_filter = enable;
2353
- else if (g_strcmp0 (feature, "mask") == 0)
2354
- svg_view->debug_mask = enable;
2355
- else if (g_strcmp0 (feature, "pattern") == 0)
2356
- svg_view->debug_pattern = enable;
2357
- }
2358
-
2359
- LsmSvgView *
2360
- lsm_svg_view_new (LsmSvgDocument *document)
2361
- {
2362
- LsmSvgView *view;
2363
-
2364
- view = g_object_new (LSM_TYPE_SVG_VIEW, NULL);
2365
-
2366
- lsm_dom_view_set_document (LSM_DOM_VIEW (view), LSM_DOM_DOCUMENT (document));
2367
-
2368
- return view;
2369
- }
2370
-
2371
- static void
2372
- lsm_svg_view_init (LsmSvgView *view)
2373
- {
2374
- view->debug_mask = FALSE;
2375
- view->debug_filter = FALSE;
2376
- view->debug_pattern = FALSE;
2377
- }
2378
-
2379
- static void
2380
- lsm_svg_view_finalize (GObject *object)
2381
- {
2382
- parent_class->finalize (object);
2383
- }
2384
-
2385
- static void
2386
- lsm_svg_view_class_init (LsmSvgViewClass *view_class)
2387
- {
2388
- GObjectClass *object_class = G_OBJECT_CLASS (view_class);
2389
- LsmDomViewClass *d_view_class = LSM_DOM_VIEW_CLASS (view_class);
2390
-
2391
- parent_class = g_type_class_peek_parent (view_class);
2392
-
2393
- object_class->finalize = lsm_svg_view_finalize;
2394
-
2395
- d_view_class->measure = lsm_svg_view_measure;
2396
- d_view_class->render = lsm_svg_view_render;
2397
- d_view_class->set_debug = lsm_svg_view_set_debug;
2398
- }
2399
-
2400
- G_DEFINE_TYPE (LsmSvgView, lsm_svg_view, LSM_TYPE_DOM_VIEW)