mathematical 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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)