Commit 535abaf8 authored by Tebjan Halm's avatar Tebjan Halm
Browse files

Merge pull request #90 from erdomke/master

Initial Work on W3C Test Compliance
parents 4b1ff3d4 bd05ecbc
Source/bin/
Source/obj/
Source/Svg.csproj.user
Source/Svg.suo
Source/**/bin/
Source/**/obj/
Source/**/*.csproj.user
Source/**/*.suo
Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
Samples/SVGViewer/obj/
Samples/SVGViewer/bin/
Samples/SVGViewer/SVGViewer.OpenCover.Settings
Source/**/*.dll
Source/**/*.pdb
Tests/**/bin/
Tests/**/obj/
Tests/**/*.csproj.user
Tests/**/*.suo
*.trx
Source/TestResults/
\ No newline at end of file
<svg version="1.1" xmlns:user="urn:user-scripts" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:aras="http://www.aras.com" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<marker id="Triangle" viewBox="0 0 10 6" refX="22" refY="3" markerWidth="10" markerHeight="6" markerUnits="userSpaceOnUse" orient="auto" style="fill:#999;">
<path d="M 0 0 L 10 3 L 0 6 z" />
</marker>
</defs>
<rect style="fill:yellow" x="754" y="282" width="36" height="36" />
<path id="path_A135EC81DDA143DC9D28767B2A41B31D" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);" d="M45,212 L109,212" />
<path id="path_6FF994F1BC9F4841950F977A737DDBB8" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M109,212 L246,351" />
<path id="path_E75FD0879CE14583AFBD46320DBCC608" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);" d="M109,212 L246,212" />
<path id="path_FA30736F915A4D328A0052667C5F4CF5" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M109,212 L246,212" />
<path id="path_98C289D25D164A979817EFAEE13CFE5F" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L217,183 L153,183 L109,212" />
<path id="path_72A7FAFD32E048D791AC1BEFCFCEC9D0" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L400,212" />
<path id="path_81970D2DC1D04D529CEE9CD6D56A2976" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L246,351" />
<path id="path_45C39F121DE043C9897CEA599913FF18" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);" d="M246,212 L372,300 L495,300" />
<path id="path_E45EE6187D384A9888495299E8FFA180" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L349,258 L480,258 L527,212" />
<path id="path_5E54C1B6B03C412690130BFD4AA11C29" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L361,426 L771,426" />
<path id="path_493D6CD66BCB4215B64CA95613A8C4E7" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L324,133 L692,133" />
<path id="path_2A4C9573761F4D4082D76D3086C06D14" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M246,212 L351,69" />
<path id="path_F4ADA3A633DA4A2BAC0D1DF37C9E974A" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);" d="M495,300 L772,300" />
<path id="path_BD335878BCD949EDA5BD676D82EE95CD" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M495,300 L461,332 L379,332 L246,212" />
<path id="path_31A2E455215649B0955DF48098DBAFB5" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M772,300 L876,300 L969,212" />
<path id="path_07E281627B9B4E6C88C4F416D00FB4D5" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M772,300 L719,353 L610,353" />
<path id="path_16CEC81123CE4437A34A09B2570A513D" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M772,300 L725,392 L396,392 L246,212" />
<path id="path_1D02F0DB7C444FD3A70B9DC2F0D76C1C" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M772,300 L725,392 L396,392 L246,212" />
<path id="path_002289179A4B46EBA27B28323D0A54C7" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L217,183 L153,183 L109,212" />
<path id="path_E5E1BAFEC28A4C06BDB27AA52F4FEC6D" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L400,212" />
<path id="path_B786DE8A93F34F159B75B7A52D90CE97" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L246,351" />
<path id="path_8B5C82191A9D4D2FAD9B987A487C3BA7" style="stroke: rgb(52%, 52%, 52%); fill:none; stroke-width: 2px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L372,300 L495,300" />
<path id="path_107E0DAA2EB8485586C479087C1AA226" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L349,258 L480,258 L527,212" />
<path id="path_AD1BC5A02C8D477B8169019CAA282F99" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L361,426 L771,426" />
<path id="path_5B6980E8BA6D4D4790BADD421037602A" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L324,133 L692,133" />
<path id="path_E088B696363F4A6783322F24B4FBAAFB" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M246,212 L351,69" />
<path id="path_4DA4A67EFEF2443FA0A4FE24FA477F11" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M351,69 L448,69 L692,133" />
<path id="path_40867780959E496AA36A6555CD3E33D2" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M351,69 L239,69 L109,212" />
<path id="path_89E0FF64C5734D5CBE0DEF15FCB2FC78" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M400,212 L527,212" />
<path id="path_40ABF0BE79D845A9835EEA8946DC5E13" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M400,212 L368,181 L293,181 L246,212" />
<path id="path_77067CF20C6941088FDC9876FD24F7A6" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);&#xA; opacity: 0;&#xA; " d="M400,212 L368,181 L293,181 L246,212" />
<path id="path_C82DC92658654B059AB8CBA528667ADA" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M500,25 L203,25 L109,212" />
<path id="path_5ABCCBB56C4046859522ED2C9ECD33AD" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M500,25 L692,133" />
<path id="path_B91D6F28E4804A498EFBD5A3D6AF250B" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M527,212 L693,212" />
<path id="path_7F9A959CF641418CBCD4873251B812B3" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M610,353 L548,353 L495,300" />
<path id="path_F284CCEE2AFB4B3BAC3554145B3FD262" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M610,353 L663,300 L772,300" />
<path id="path_2E0294E13A684EBD99F1DB80EDDB9840" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M692,133 L583,25 L500,25" />
<path id="path_A9F0267F5B9744508B9437FE4B0200C4" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M692,133 L749,133 L815,212" />
<path id="path_4CBFE74449654265806D8E904B6EE5BE" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M693,212 L660,180 L560,180 L527,212" />
<path id="path_D87477BFC3BF4F909A04B05F7874846E" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M693,212 L815,212" />
<path id="path_461D5FEE97F646DC8CD142A866D0355F" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M613,469 L202,469 L109,212" />
<path id="path_5AE3619D67904B23B1E93CBD7D1E20D7" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M613,469 L771,426" />
<path id="path_DC4157E0DAE84A46BB953E4BF4510ECE" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M815,212 L969,212" />
<path id="path_330EB66D10C646ADB34B33613E516A4E" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M771,426 L1076,426 L1231,212" />
<path id="path_13D8206671ED47AC920091F58EA1687F" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M771,426 L729,469 L613,469" />
<path id="path_A140353DB1E34B67A51D0CD75D23CBE2" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M771,426 L809,388 L910,388 L969,212" />
<path id="path_6670A0725101421090E5F4CA7624571A" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M969,212 L1132,212" />
<path id="path_FB713A1FF8F9424B8612F8088E7B1F11" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M1132,212 L1231,212" />
<path id="path_9EB82A675F344E598ED07614C26A46EA" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M1132,212 L1098,178 L1004,178 L969,212" />
<path id="path_768FCB23D27C4749B32411A7463D54B1" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M1231,212 L1356,212" />
<path id="path_1BF51A8E49774FDD936814D21809AEC2" style="stroke: rgb(60%, 60%, 60%); fill:none; stroke-width: 1px; marker-end: url(#Triangle);" d="M1231,212 L1167,267 L1025,267 L969,212" />
<ellipse style="fill:white" ry="12" rx="12" cx="45" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_7FCC999FEE5248CDB90824E00D1029BB" height="16" width="16" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/16x16/16x16_arrow_right.gif" x="37" y="204" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_7FCC999FEE5248CDB90824E00D1029BB" x="45" y="238">
<desc>Closed</desc>Start</text>
<ellipse style="fill:white" ry="12" rx="12" cx="109" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_0462DCDBBC314295BD899B481F911C81" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="99" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_0462DCDBBC314295BD899B481F911C81" x="109" y="238">
<desc>Closed</desc>Submit ECO</text>
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;&#xA; opacity: 0;&#xA; " id="node_label_1F530B42A24F4155B06747CB8F52A8FE" x="246" y="238">
<desc>Closed</desc>MDM Review</text>
<ellipse style="fill:white" ry="12" rx="12" cx="495" cy="300" />
<image preserveAspectRatio="xMidYMid" id="node_img_946BCC8A04FA42EE8917F02183DBD576" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="485" y="289" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_946BCC8A04FA42EE8917F02183DBD576" x="495" y="326">
<desc>Closed</desc>Need Info</text>
<ellipse style="fill:yellow" ry="12" rx="12" cx="772" cy="300" />
<image preserveAspectRatio="xMidYMid" id="node_img_A394CFFCEF61475ABF6F43D4AAA4F278" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="762" y="289" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_A394CFFCEF61475ABF6F43D4AAA4F278" x="772" y="326">
<desc>Active</desc>ECO Plan Approval</text>
<ellipse style="fill:white" ry="12" rx="12" cx="246" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_75B56693C81D461389AA15D5C8017CBF" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="236" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_75B56693C81D461389AA15D5C8017CBF" x="246" y="238">
<desc>Pending</desc>MDM Review</text>
<ellipse style="fill:white" ry="12" rx="12" cx="351" cy="69" />
<image preserveAspectRatio="xMidYMid" id="node_img_73D771D6831A4F5EA82A766392AB091E" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="341" y="58" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_73D771D6831A4F5EA82A766392AB091E" x="351" y="95">
<desc>Pending</desc>Print/Drawing Update</text>
<ellipse style="fill:white" ry="12" rx="12" cx="400" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_8AF6597A38BB41F288E4EE17F20A8B29" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="390" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_8AF6597A38BB41F288E4EE17F20A8B29" x="400" y="238">
<desc>Pending</desc>ECO Pre-Approval</text>
<ellipse style="fill:white" ry="12" rx="12" cx="500" cy="25" />
<image preserveAspectRatio="xMidYMid" id="node_img_8476C8E170DC47EA9F05AE2164CABD96" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="490" y="14" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_8476C8E170DC47EA9F05AE2164CABD96" x="500" y="51">
<desc>Pending</desc>Interim Workflow Resolution</text>
<ellipse style="fill:white" ry="12" rx="12" cx="527" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_4517B7B7598A44A1969F30290153FA64" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="517" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_4517B7B7598A44A1969F30290153FA64" x="527" y="238">
<desc>Pending</desc>Draft Changes</text>
<ellipse style="fill:white" ry="12" rx="12" cx="610" cy="353" />
<image preserveAspectRatio="xMidYMid" id="node_img_7379A1A219DE468FB61D3F1E84C1B042" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="600" y="342" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_7379A1A219DE468FB61D3F1E84C1B042" x="610" y="379">
<desc>Pending</desc>Approval Resolution</text>
<ellipse style="fill:white" ry="12" rx="12" cx="692" cy="133" />
<image preserveAspectRatio="xMidYMid" id="node_img_18F401FCAACC4E8DAC4014EEA576DE51" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="682" y="122" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_18F401FCAACC4E8DAC4014EEA576DE51" x="692" y="159">
<desc>Pending</desc>Change Review</text>
<ellipse style="fill:white" ry="12" rx="12" cx="693" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_014C7DD975FA4E7EB354F9B81E71CB18" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="683" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_014C7DD975FA4E7EB354F9B81E71CB18" x="693" y="238">
<desc>Pending</desc>Change Review</text>
<ellipse style="fill:white" ry="12" rx="12" cx="613" cy="469" />
<image preserveAspectRatio="xMidYMid" id="node_img_CDE9E46E164645538136D5D120D2593C" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="603" y="458" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_CDE9E46E164645538136D5D120D2593C" x="613" y="495">
<desc>Pending</desc>Pre-Prod Approval Resolution</text>
<ellipse style="fill:white" ry="12" rx="12" cx="815" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_83542AA107564FAABD77DF5C61FBA354" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="805" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_83542AA107564FAABD77DF5C61FBA354" x="815" y="238">
<desc>Pending</desc>Impl. Plan Review</text>
<ellipse style="fill:white" ry="12" rx="12" cx="771" cy="426" />
<image preserveAspectRatio="xMidYMid" id="node_img_64D911B1C1AD41208373D9AF319AB38D" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="761" y="415" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_64D911B1C1AD41208373D9AF319AB38D" x="771" y="452">
<desc>Pending</desc>Pre-Production Approval</text>
<ellipse style="fill:white" ry="12" rx="12" cx="969" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_43578966BE674CC9A7C0D54FE88E0C91" height="16" width="16" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/customer/16x16 Icons 1/icon_clock.gif" x="961" y="204" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_43578966BE674CC9A7C0D54FE88E0C91" x="969" y="238">
<desc>Pending</desc>Effectivity Wait</text>
<ellipse style="fill:white" ry="12" rx="12" cx="1132" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_D21E5FAE6F784BB19EEE40C334473CBB" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="1122" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_D21E5FAE6F784BB19EEE40C334473CBB" x="1132" y="238">
<desc>Pending</desc>Impl. Approval</text>
<ellipse style="fill:white" ry="12" rx="12" cx="1231" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_DB1C8B95B26C4069ACC03F0E3D42C249" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="1221" y="201" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_DB1C8B95B26C4069ACC03F0E3D42C249" x="1231" y="238">
<desc>Pending</desc>Impl. Approved</text>
<ellipse style="fill:white" ry="12" rx="12" cx="246" cy="351" />
<image preserveAspectRatio="xMidYMid" id="node_img_67A00DAAD58D4115A63B45049D2B3986" height="22" width="20" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/Icons/20x20/20x22_gray_ball.gif" x="236" y="340" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_67A00DAAD58D4115A63B45049D2B3986" x="246" y="377">
<desc>Pending</desc>Cancel</text>
<ellipse style="fill:white" ry="12" rx="12" cx="1356" cy="212" />
<image preserveAspectRatio="xMidYMid" id="node_img_CD08C79BB931412A8C31745DF6A4910A" height="16" width="16" xlink:href="http://ct.gentex.com/gentexinnovator/Client/images/customer/16x16 Icons 1/page_favourites.gif" x="1348" y="204" />
<text text-anchor="middle" style="font-family:Verdana;font-size:8pt;fill:Blue;" id="node_label_CD08C79BB931412A8C31745DF6A4910A" x="1356" y="238">
<desc>Pending</desc>Close Change</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_A135EC81DDA143DC9D28767B2A41B31D" x="51" y="208">Go</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_6FF994F1BC9F4841950F977A737DDBB8" x="135" y="278">Cancel ECO</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_E75FD0879CE14583AFBD46320DBCC608" x="132" y="209">Submit</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_98C289D25D164A979817EFAEE13CFE5F" x="162" y="193">Unsubmit</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_72A7FAFD32E048D791AC1BEFCFCEC9D0" x="268" y="209">iLink - Pre-Approval</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_81970D2DC1D04D529CEE9CD6D56A2976" x="204" y="285">Cancel ECO</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_45C39F121DE043C9897CEA599913FF18" x="368" y="296">Legacy Workflow</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_E45EE6187D384A9888495299E8FFA180" x="350" y="255">iLink - Pre-Approved</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_5E54C1B6B03C412690130BFD4AA11C29" x="363" y="422">Pre-Production Workflow</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_493D6CD66BCB4215B64CA95613A8C4E7" x="324" y="143">Interim Workflow (Approval)</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_2A4C9573761F4D4082D76D3086C06D14" x="226" y="113">Interim Workflow (Prints)</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_F4ADA3A633DA4A2BAC0D1DF37C9E974A" x="508" y="296">Added Info</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_BD335878BCD949EDA5BD676D82EE95CD" x="403" y="341">Re-Review</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_31A2E455215649B0955DF48098DBAFB5" x="783" y="297">Approve ECO</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_07E281627B9B4E6C88C4F416D00FB4D5" x="634" y="362">Need more info</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_16CEC81123CE4437A34A09B2570A513D" x="757" y="342">Reject</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_4DA4A67EFEF2443FA0A4FE24FA477F11" x="358" y="65">Prints Updated</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_40867780959E496AA36A6555CD3E33D2" x="282" y="66">Unsubmit</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_89E0FF64C5734D5CBE0DEF15FCB2FC78" x="414" y="208">Approve</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_40ABF0BE79D845A9835EEA8946DC5E13" x="333" y="190">Reject</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_C82DC92658654B059AB8CBA528667ADA" x="429" y="21">Unsubmit</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_5ABCCBB56C4046859522ED2C9ECD33AD" x="513" y="68">Redo Approval</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_B91D6F28E4804A498EFBD5A3D6AF250B" x="543" y="208">Submit for Review</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_7F9A959CF641418CBCD4873251B812B3" x="496" y="364">Repeat Need Info</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_F284CCEE2AFB4B3BAC3554145B3FD262" x="601" y="323">Repeat Approval</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_2E0294E13A684EBD99F1DB80EDDB9840" x="664" y="104">Reject</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_A9F0267F5B9744508B9437FE4B0200C4" x="702" y="128">Approve</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_4CBFE74449654265806D8E904B6EE5BE" x="619" y="190">Rework</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_D87477BFC3BF4F909A04B05F7874846E" x="706" y="207">Approve</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_461D5FEE97F646DC8CD142A866D0355F" x="544" y="479">Unsubmit</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_5AE3619D67904B23B1E93CBD7D1E20D7" x="608" y="445">Redo Approval</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_DC4157E0DAE84A46BB953E4BF4510ECE" x="825" y="207">Approve Plan</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_330EB66D10C646ADB34B33613E516A4E" x="788" y="421">Approve &amp; Implement</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_13D8206671ED47AC920091F58EA1687F" x="741" y="467">Reject ECO</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_A140353DB1E34B67A51D0CD75D23CBE2" x="810" y="384">Approve &amp; Wait</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_6670A0725101421090E5F4CA7624571A" x="989" y="209">Req. Impl. Approval</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_FB713A1FF8F9424B8612F8088E7B1F11" x="1144" y="208">Ready</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_9EB82A675F344E598ED07614C26A46EA" x="1043" y="188">Not Ready</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_768FCB23D27C4749B32411A7463D54B1" x="1242" y="208">Fully Impl/Close</text>
<text style="font-family: Verdana;font-size:8pt; fill:Black;" text-anchor="start" id="path_label_1BF51A8E49774FDD936814D21809AEC2" x="1086" y="277">Continue Wait</text>
</svg>
......@@ -81,7 +81,7 @@ namespace Svg
/// <value>The rectangular bounds of the circle.</value>
public override RectangleF Bounds
{
get { return this.Path.GetBounds(); }
get { return this.Path(null).GetBounds(); }
}
/// <summary>
......@@ -98,24 +98,19 @@ namespace Svg
/// <summary>
/// Gets the <see cref="GraphicsPath"/> representing this element.
/// </summary>
public override GraphicsPath Path
public override GraphicsPath Path(SvgRenderer renderer)
{
get
if (this._path == null || this.IsPathDirty)
{
if (this._path == null || this.IsPathDirty)
{
_path = new GraphicsPath();
_path.StartFigure();
_path.AddEllipse(this.Center.ToDeviceValue().X - this.Radius.ToDeviceValue(), this.Center.ToDeviceValue().Y - this.Radius.ToDeviceValue(), 2 * this.Radius.ToDeviceValue(), 2 * this.Radius.ToDeviceValue());
_path.CloseFigure();
this.IsPathDirty = false;
}
return _path;
}
protected set
{
_path = value;
_path = new GraphicsPath();
_path.StartFigure();
var center = this.Center.ToDeviceValue(renderer, this);
var radius = this.Radius.ToDeviceValue(renderer, UnitRenderingType.Other, this);
_path.AddEllipse(center.X - radius, center.Y - radius, 2 * radius, 2 * radius);
_path.CloseFigure();
this.IsPathDirty = false;
}
return _path;
}
/// <summary>
......
......@@ -95,34 +95,27 @@ namespace Svg
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return this.Path.GetBounds(); }
get { return this.Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
/// <value></value>
public override GraphicsPath Path
public override GraphicsPath Path(SvgRenderer renderer)
{
get
if (this._path == null || this.IsPathDirty)
{
if (this._path == null || this.IsPathDirty)
{
PointF center = new PointF(this._centerX.ToDeviceValue(this), this._centerY.ToDeviceValue(this, true));
PointF radius = new PointF(this._radiusX.ToDeviceValue(this), this._radiusY.ToDeviceValue(this, true));
var center = SvgUnit.GetDevicePoint(this._centerX, this._centerY, renderer, this);
var radius = SvgUnit.GetDevicePoint(this._radiusX, this._radiusY, renderer, this);
this._path = new GraphicsPath();
_path.StartFigure();
_path.AddEllipse(center.X - radius.X, center.Y - radius.Y, 2 * radius.X, 2 * radius.Y);
_path.CloseFigure();
this.IsPathDirty = false;
}
return _path;
}
protected set
{
_path = value;
this._path = new GraphicsPath();
_path.StartFigure();
_path.AddEllipse(center.X - radius.X, center.Y - radius.Y, 2 * radius.X, 2 * radius.Y);
_path.CloseFigure();
this.IsPathDirty = false;
}
return _path;
}
/// <summary>
......
......@@ -29,6 +29,17 @@ namespace Svg
public SvgPoint Location
{
get { return new SvgPoint(X, Y); }
}
/// <summary>
/// Gets or sets the aspect of the viewport.
/// </summary>
/// <value></value>
[SvgAttribute("preserveAspectRatio")]
public SvgAspectRatio AspectRatio
{
get { return this.Attributes.GetAttribute<SvgAspectRatio>("preserveAspectRatio"); }
set { this.Attributes["preserveAspectRatio"] = value; }
}
[SvgAttribute("x")]
......@@ -75,21 +86,17 @@ namespace Svg
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return new RectangleF(this.Location.ToDeviceValue(), new SizeF(this.Width, this.Height)); }
get { return new RectangleF(this.Location.ToDeviceValue(null, this),
new SizeF(this.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, this),
this.Height.ToDeviceValue(null, UnitRenderingType.Vertical, this))); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path
/// </summary>
public override GraphicsPath Path(SvgRenderer renderer)
{
get
{
return null;
}
protected set
{
}
return null;
}
/// <summary>
......@@ -106,13 +113,72 @@ namespace Svg
{
if (b != null)
{
var srcRect = new RectangleF(0, 0, b.Width, b.Height);
var destClip = new RectangleF(this.Location.ToDeviceValue(renderer, this),
new SizeF(Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this)));
RectangleF destRect = destClip;
this.PushTransforms(renderer);
renderer.AddClip(new Region(destClip));
this.SetClip(renderer);
RectangleF srcRect = new RectangleF(0, 0, b.Width, b.Height);
var destRect = new RectangleF(this.Location.ToDeviceValue(),
new SizeF(Width.ToDeviceValue(), Height.ToDeviceValue()));
if (AspectRatio != null && AspectRatio.Align != SvgPreserveAspectRatio.none)
{
var fScaleX = destClip.Width / srcRect.Width;
var fScaleY = destClip.Height / srcRect.Height;
var xOffset = 0.0f;
var yOffset = 0.0f;
if (AspectRatio.Slice)
{
fScaleX = Math.Max(fScaleX, fScaleY);
fScaleY = Math.Max(fScaleX, fScaleY);
}
else
{
fScaleX = Math.Min(fScaleX, fScaleY);
fScaleY = Math.Min(fScaleX, fScaleY);
}
switch (AspectRatio.Align)
{
case SvgPreserveAspectRatio.xMinYMin:
break;
case SvgPreserveAspectRatio.xMidYMin:
xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
break;
case SvgPreserveAspectRatio.xMaxYMin:
xOffset = (destClip.Width - srcRect.Width * fScaleX);
break;
case SvgPreserveAspectRatio.xMinYMid:
yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
break;
case SvgPreserveAspectRatio.xMidYMid:
xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
break;
case SvgPreserveAspectRatio.xMaxYMid:
xOffset = (destClip.Width - srcRect.Width * fScaleX);
yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2;
break;
case SvgPreserveAspectRatio.xMinYMax:
yOffset = (destClip.Height - srcRect.Height * fScaleY);
break;
case SvgPreserveAspectRatio.xMidYMax:
xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2;
yOffset = (destClip.Height - srcRect.Height * fScaleY);
break;
case SvgPreserveAspectRatio.xMaxYMax:
xOffset = (destClip.Width - srcRect.Width * fScaleX);
yOffset = (destClip.Height - srcRect.Height * fScaleY);
break;
}
destRect = new RectangleF(destClip.X + xOffset, destClip.Y + yOffset,
srcRect.Width * fScaleX, srcRect.Height * fScaleY);
}
renderer.DrawImage(b, destRect, srcRect, GraphicsUnit.Pixel);
this.ResetClip(renderer);
......@@ -129,7 +195,7 @@ namespace Svg
try
{
// handle data/uri embedded images (http://en.wikipedia.org/wiki/Data_URI_scheme)
if (uri.Scheme == "data")
if (uri.IsAbsoluteUri && uri.Scheme == "data")
{
string uriString = uri.OriginalString;
int dataIdx = uriString.IndexOf(",") + 1;
......@@ -143,14 +209,26 @@ namespace Svg
return image;
}
if (!uri.IsAbsoluteUri)
{
uri = new Uri(OwnerDocument.BaseUri, uri);
}
// should work with http: and file: protocol urls
var httpRequest = WebRequest.Create(uri);
using (WebResponse webResponse = httpRequest.GetResponse())
{
MemoryStream ms = BufferToMemoryStream(webResponse.GetResponseStream());
Image image = Bitmap.FromStream(ms);
return image;
if (uri.LocalPath.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase))
{
var doc = SvgDocument.Open<SvgDocument>(ms);
return doc.Draw();
}
else
{
return Bitmap.FromStream(ms);
}
}
}
catch (Exception ex)
......
......@@ -92,30 +92,25 @@ namespace Svg
{
}
public override System.Drawing.Drawing2D.GraphicsPath Path
public override System.Drawing.Drawing2D.GraphicsPath Path(SvgRenderer renderer)
{
get
if (this._path == null || this.IsPathDirty)
{
if (this._path == null || this.IsPathDirty)
{
PointF start = new PointF(this.StartX.ToDeviceValue(this), this.StartY.ToDeviceValue(this, true));
PointF end = new PointF(this.EndX.ToDeviceValue(this), this.EndY.ToDeviceValue(this, true));
PointF start = new PointF(this.StartX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
this.StartY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
PointF end = new PointF(this.EndX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
this.EndY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
this._path = new GraphicsPath();
this._path.AddLine(start, end);
this.IsPathDirty = false;
}
return this._path;
}
protected set
{
_path = value;
this._path = new GraphicsPath();
this._path.AddLine(start, end);
this.IsPathDirty = false;
}
return this._path;
}
public override System.Drawing.RectangleF Bounds
{
get { return this.Path.GetBounds(); }
get { return this.Path(null).GetBounds(); }
}
public override SvgElement DeepCopy()
......
......@@ -32,51 +32,44 @@ namespace Svg
get { return true; }
}
public override GraphicsPath Path
public override GraphicsPath Path(SvgRenderer renderer)
{
get
if (this._path == null || this.IsPathDirty)
{
if (this._path == null || this.IsPathDirty)
{
this._path = new GraphicsPath();
this._path.StartFigure();
this._path = new GraphicsPath();
this._path.StartFigure();
try
try
{
for (int i = 2; i < this._points.Count; i+=2)
{
for (int i = 2; i < this._points.Count; i+=2)
{
PointF endPoint = new PointF(this._points[i].ToDeviceValue(this), this._points[i+1].ToDeviceValue(this));
var endPoint = SvgUnit.GetDevicePoint(this._points[i], this._points[i+1], renderer, this);
//first line
if (_path.PointCount == 0)
{
_path.AddLine(new PointF(this._points[i-2].ToDeviceValue(this), this._points[i-1].ToDeviceValue(this)), endPoint);
}
else
{
_path.AddLine(_path.GetLastPoint(), endPoint);
}
//first line
if (_path.PointCount == 0)
{
_path.AddLine(SvgUnit.GetDevicePoint(this._points[i - 2], this._points[i - 1], renderer, this), endPoint);
}
else
{
_path.AddLine(_path.GetLastPoint(), endPoint);
}
}
catch
{
Trace.TraceError("Error parsing points");
}
this._path.CloseFigure();
this.IsPathDirty = false;
}
return this._path;
}
protected set
{
_path = value;
catch
{
Trace.TraceError("Error parsing points");
}
this._path.CloseFigure();
this.IsPathDirty = false;
}
return this._path;
}
public override RectangleF Bounds
{
get { return this.Path.GetBounds(); }
get { return this.Path(null).GetBounds(); }
}
......
......@@ -14,39 +14,37 @@ namespace Svg
public class SvgPolyline : SvgPolygon
{
private GraphicsPath _Path;
public override GraphicsPath Path
public override GraphicsPath Path(SvgRenderer renderer)
{
get
if (_Path == null || this.IsPathDirty)
{
if (_Path == null || this.IsPathDirty)
{
_Path = new GraphicsPath();
_Path = new GraphicsPath();
try
try
{
for (int i = 0; i < Points.Count; i += 2)
{
for (int i = 0; i < Points.Count; i += 2)
{
PointF endPoint = new PointF(Points[i].ToDeviceValue(this), Points[i + 1].ToDeviceValue(this));
PointF endPoint = new PointF(Points[i].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this),
Points[i + 1].ToDeviceValue(renderer, UnitRenderingType.Vertical, this));
// TODO: Remove unrequired first line
if (_Path.PointCount == 0)
{
_Path.AddLine(endPoint, endPoint);
}
else
{
_Path.AddLine(_Path.GetLastPoint(), endPoint);
}
// TODO: Remove unrequired first line
if (_Path.PointCount == 0)
{
_Path.AddLine(endPoint, endPoint);
}
else
{
_Path.AddLine(_Path.GetLastPoint(), endPoint);
}
}
catch (Exception exc)
{
Trace.TraceError("Error rendering points: " + exc.Message);
}
this.IsPathDirty = false;
}
return _Path;
catch (Exception exc)
{
Trace.TraceError("Error rendering points: " + exc.Message);
}
this.IsPathDirty = false;
}
return _Path;
}
}
}
\ No newline at end of file
......@@ -168,101 +168,94 @@ namespace Svg
/// <value>The bounds.</value>
public override RectangleF Bounds
{
get { return Path.GetBounds(); }
get { return Path(null).GetBounds(); }
}
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public override GraphicsPath Path
public override GraphicsPath Path(SvgRenderer renderer)
{
get
if (_path == null || IsPathDirty)
{
if (_path == null || IsPathDirty)
// If the corners aren't to be rounded just create a rectangle
if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f)
{
// If the corners aren't to be rounded just create a rectangle
if (CornerRadiusX.Value == 0.0f && CornerRadiusY.Value == 0.0f)
{
var rectangle = new RectangleF(Location.ToDeviceValue(),
new SizeF(Width.ToDeviceValue(), Height.ToDeviceValue()));
var rectangle = new RectangleF(Location.ToDeviceValue(renderer, this),
SvgUnit.GetDeviceSize(this.Width, this.Height, renderer, this));
_path = new GraphicsPath();
_path.StartFigure();
_path.AddRectangle(rectangle);
_path.CloseFigure();
}
else
{
_path = new GraphicsPath();
var arcBounds = new RectangleF();
var lineStart = new PointF();
var lineEnd = new PointF();
var width = Width.ToDeviceValue();
var height = Height.ToDeviceValue();
var rx = CornerRadiusX.ToDeviceValue() * 2;
var ry = CornerRadiusY.ToDeviceValue() * 2;
var location = Location.ToDeviceValue();
_path = new GraphicsPath();
_path.StartFigure();
_path.AddRectangle(rectangle);
_path.CloseFigure();
}
else
{
_path = new GraphicsPath();
var arcBounds = new RectangleF();
var lineStart = new PointF();
var lineEnd = new PointF();
var width = Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var height = Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
var rx = CornerRadiusX.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this) * 2;
var ry = CornerRadiusY.ToDeviceValue(renderer, UnitRenderingType.Vertical, this) * 2;
var location = Location.ToDeviceValue(renderer, this);
// Start
_path.StartFigure();
// Start
_path.StartFigure();
// Add first arc
arcBounds.Location = location;
arcBounds.Width = rx;
arcBounds.Height = ry;
_path.AddArc(arcBounds, 180, 90);
// Add first arc
arcBounds.Location = location;
arcBounds.Width = rx;
arcBounds.Height = ry;
_path.AddArc(arcBounds, 180, 90);
// Add first line
lineStart.X = Math.Min(location.X + rx, location.X + width * 0.5f);
lineStart.Y = location.Y;
lineEnd.X = Math.Max(location.X + width - rx, location.X + width * 0.5f);
lineEnd.Y = lineStart.Y;
_path.AddLine(lineStart, lineEnd);
// Add first line
lineStart.X = Math.Min(location.X + rx, location.X + width * 0.5f);
lineStart.Y = location.Y;
lineEnd.X = Math.Max(location.X + width - rx, location.X + width * 0.5f);
lineEnd.Y = lineStart.Y;
_path.AddLine(lineStart, lineEnd);
// Add second arc
arcBounds.Location = new PointF(location.X + width - rx, location.Y);
_path.AddArc(arcBounds, 270, 90);
// Add second arc
arcBounds.Location = new PointF(location.X + width - rx, location.Y);
_path.AddArc(arcBounds, 270, 90);
// Add second line
lineStart.X = location.X + width;
lineStart.Y = Math.Min(location.Y + ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
_path.AddLine(lineStart, lineEnd);
// Add second line
lineStart.X = location.X + width;
lineStart.Y = Math.Min(location.Y + ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
_path.AddLine(lineStart, lineEnd);
// Add third arc
arcBounds.Location = new PointF(location.X + width - rx, location.Y + height - ry);
_path.AddArc(arcBounds, 0, 90);
// Add third arc
arcBounds.Location = new PointF(location.X + width - rx, location.Y + height - ry);
_path.AddArc(arcBounds, 0, 90);
// Add third line
lineStart.X = Math.Max(location.X + width - rx, location.X + width * 0.5f);
lineStart.Y = location.Y + height;
lineEnd.X = Math.Min(location.X + rx, location.X + width * 0.5f);
lineEnd.Y = lineStart.Y;
_path.AddLine(lineStart, lineEnd);
// Add third line
lineStart.X = Math.Max(location.X + width - rx, location.X + width * 0.5f);
lineStart.Y = location.Y + height;
lineEnd.X = Math.Min(location.X + rx, location.X + width * 0.5f);
lineEnd.Y = lineStart.Y;
_path.AddLine(lineStart, lineEnd);
// Add third arc
arcBounds.Location = new PointF(location.X, location.Y + height - ry);
_path.AddArc(arcBounds, 90, 90);
// Add third arc
arcBounds.Location = new PointF(location.X, location.Y + height - ry);
_path.AddArc(arcBounds, 90, 90);
// Add fourth line
lineStart.X = location.X;
lineStart.Y = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Min(location.Y + ry, location.Y + height * 0.5f);
_path.AddLine(lineStart, lineEnd);
// Add fourth line
lineStart.X = location.X;
lineStart.Y = Math.Max(location.Y + height - ry, location.Y + height * 0.5f);
lineEnd.X = lineStart.X;
lineEnd.Y = Math.Min(location.Y + ry, location.Y + height * 0.5f);
_path.AddLine(lineStart, lineEnd);
// Close
_path.CloseFigure();
}
IsPathDirty = false;
// Close
_path.CloseFigure();
}
return _path;
}
protected set
{
_path = value;
IsPathDirty = false;
}
return _path;
}
/// <summary>
......
......@@ -16,7 +16,7 @@ namespace Svg
/// <summary>
/// Gets the <see cref="GraphicsPath"/> for this element.
/// </summary>
public abstract GraphicsPath Path { get; protected set; }
public abstract GraphicsPath Path(SvgRenderer renderer);
PointF ISvgBoundable.Location
{
......@@ -105,7 +105,7 @@ namespace Svg
/// <param name="renderer">The <see cref="SvgRenderer"/> object to render to.</param>
protected override void Render(SvgRenderer renderer)
{
if ((this.Path != null) && this.Visible && this.Displayable)
if ((this.Path(renderer) != null) && this.Visible && this.Displayable)
{
this.PushTransforms(renderer);
this.SetClip(renderer);
......@@ -138,12 +138,12 @@ namespace Svg
{
if (this.Fill != null)
{
using (Brush brush = this.Fill.GetBrush(this, this.FillOpacity))
using (Brush brush = this.Fill.GetBrush(this, renderer, Math.Min(Math.Max(this.FillOpacity * this.Opacity, 0), 1)))
{
if (brush != null)
{
this.Path.FillMode = this.FillRule == SvgFillRule.NonZero ? FillMode.Winding : FillMode.Alternate;
renderer.FillPath(brush, this.Path);
this.Path(renderer).FillMode = this.FillRule == SvgFillRule.NonZero ? FillMode.Winding : FillMode.Alternate;
renderer.FillPath(brush, this.Path(renderer));
}
}
}
......@@ -157,8 +157,8 @@ namespace Svg
{
if (this.Stroke != null)
{
float strokeWidth = this.StrokeWidth.ToDeviceValue(this);
using (var pen = new Pen(this.Stroke.GetBrush(this, this.StrokeOpacity), strokeWidth))
float strokeWidth = this.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this);
using (var pen = new Pen(this.Stroke.GetBrush(this, renderer, Math.Min(Math.Max(this.StrokeOpacity * this.Opacity, 0), 1)), strokeWidth))
{
if (this.StrokeDashArray != null && this.StrokeDashArray.Count > 0)
{
......@@ -166,7 +166,7 @@ namespace Svg
pen.DashPattern = this.StrokeDashArray.ConvertAll(u => ((u.Value <= 0) ? 1 : u.Value) / ((strokeWidth <= 0) ? 1 : strokeWidth)).ToArray();
}
renderer.DrawPath(pen, this.Path);
renderer.DrawPath(pen, this.Path(renderer));
}
}
}
......@@ -184,7 +184,7 @@ namespace Svg
if (clipPath != null)
{
renderer.Clip = clipPath.GetClipRegion(this);
renderer.AddClip(clipPath.GetClipRegion(this));
}
}
}
......
......@@ -162,11 +162,7 @@ namespace Svg
public virtual string FontFamily
{
get { return this.Attributes["font-family"] as string; }
set
{
this.Attributes["font-family"] = value;
this.IsPathDirty = true;
}
set { this.Attributes["font-family"] = value; this.IsPathDirty = true; }
}
/// <summary>
......@@ -179,15 +175,6 @@ namespace Svg
set { this.Attributes["font-size"] = value; this.IsPathDirty = true; }
}
public SvgUnit GetInheritedFontSize()
{
var fontSizeElement = (from e in this.ParentsAndSelf.OfType<SvgVisualElement>()
where e.FontSize != SvgUnit.Empty && e.FontSize != SvgUnit.None
select e).FirstOrDefault();
return (fontSizeElement == null ? SvgUnit.None : fontSizeElement.FontSize);
}
/// <summary>
/// Refers to the boldness of the font.
/// </summary>
......@@ -308,5 +295,71 @@ namespace Svg
this.IsPathDirty = true;
}
}
private const string DefaultFontFamily = "Times New Roman";
/// <summary>
/// Get the font information based on data stored with the text object or inherited from the parent.
/// </summary>
/// <returns></returns>
internal System.Drawing.Font GetFont(SvgRenderer renderer)
{
// Get the font-size
float fontSize;
var fontSizeUnit = this.FontSize;
if (fontSizeUnit == SvgUnit.None)
{
fontSize = 1.0f;
}
else
{
fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
}
var fontStyle = System.Drawing.FontStyle.Regular;
// Get the font-weight
switch (this.FontWeight)
{
case SvgFontWeight.bold:
case SvgFontWeight.bolder:
case SvgFontWeight.w700:
case SvgFontWeight.w800:
case SvgFontWeight.w900:
fontStyle |= System.Drawing.FontStyle.Bold;
break;
}
// Get the font-style
switch (this.FontStyle)
{
case SvgFontStyle.italic:
case SvgFontStyle.oblique:
fontStyle |= System.Drawing.FontStyle.Italic;
break;
}
// Get the font-family
string family = ValidateFontFamily(this.FontFamily) ?? DefaultFontFamily;
return new System.Drawing.Font(family, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel);
}
private static string ValidateFontFamily(string fontFamilyList)
{
// Split font family list on "," and then trim start and end spaces and quotes.
var fontParts = (fontFamilyList ?? "").Split(new[] { ',' }).Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' }));
var families = System.Drawing.FontFamily.Families;
// Find a the first font that exists in the list of installed font families.
//styles from IE get sent through as lowercase.
foreach (var f in fontParts.Where(f => families.Any(family => family.Name.ToLower() == f.ToLower())))
{
return f;
}
// No valid font family found from the list requested.
return null;
}
}
}
\ No newline at end of file
......@@ -61,11 +61,11 @@ namespace Svg
{
var graphicsElement = element as SvgVisualElement;
if (graphicsElement != null && graphicsElement.Path != null)
if (graphicsElement != null && graphicsElement.Path(null) != null)
{
path.FillMode = (graphicsElement.ClipRule == SvgClipRule.NonZero) ? FillMode.Winding : FillMode.Alternate;
GraphicsPath childPath = graphicsElement.Path;
GraphicsPath childPath = graphicsElement.Path(null);
if (graphicsElement.Transforms != null)
{
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Fizzler;
using ExCSS;
namespace Svg.Css
{
internal static class CssQuery
{
public static IEnumerable<SvgElement> QuerySelectorAll(this SvgElement elem, string selector)
{
var generator = new SelectorGenerator<SvgElement>(new SvgElementOps());
Fizzler.Parser.Parse(selector, generator);
return generator.Selector(Enumerable.Repeat(elem, 1));
}
public static int GetSpecificity(this BaseSelector selector)
{
if (selector is SimpleSelector)
{
var simpleCode = selector.ToString().ToLowerInvariant();
if (simpleCode.StartsWith(":not("))
{
simpleCode = simpleCode.Substring(5, simpleCode.Length - 6);
return GetSpecificity(new SimpleSelector(simpleCode));
}
else if (simpleCode.StartsWith("#"))
{
// ID selector
return 1 << 12;
}
else if (simpleCode.StartsWith("::") || simpleCode == ":after" || simpleCode == ":before" ||
simpleCode == ":first-letter" || simpleCode == ":first-line" || simpleCode == ":selection")
{
// pseudo-element
return 1 << 4;
}
else if (simpleCode.StartsWith(".") || simpleCode.StartsWith(":") || simpleCode.StartsWith("["))
{
// class, pseudo-class, attribute
return 1 << 8;
}
else if (selector == SimpleSelector.All)
{
// all selector
return 0;
}
else
{
// element selector
return 1 << 4;
}
}
else
{
var list = selector as IEnumerable<BaseSelector>;
if (list != null)
{
return (from s in list select GetSpecificity(s)).Aggregate((p, c) => p + c);
}
else
{
var complex = selector as IEnumerable<CombinatorSelector>;
if (complex != null)
{
return (from s in complex select GetSpecificity(s.Selector)).Aggregate((p, c) => p + c);
}
else
{
return 0;
}
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Fizzler;
namespace Svg.Css
{
internal class SvgElementOps : IElementOps<SvgElement>
{
public Selector<SvgElement> Type(NamespacePrefix prefix, string name)
{
var type = SvgElementFactory.AvailableElements.SingleOrDefault(e => e.ElementName == name);
return nodes => nodes.Where(n => n.GetType() == type.ElementType);
}
public Selector<SvgElement> Universal(NamespacePrefix prefix)
{
return nodes => nodes;
}
public Selector<SvgElement> Id(string id)
{
return nodes => nodes.Where(n => n.ID == id);
}
public Selector<SvgElement> Class(string clazz)
{
return AttributeIncludes(NamespacePrefix.None, "class", clazz);
}
public Selector<SvgElement> AttributeExists(NamespacePrefix prefix, string name)
{
return nodes => nodes.Where(n => n.Attributes.ContainsKey(name) || n.CustomAttributes.ContainsKey(name));
}
public Selector<SvgElement> AttributeExact(NamespacePrefix prefix, string name, string value)
{
return nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val == value) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString() == value);
});
}
public Selector<SvgElement> AttributeIncludes(NamespacePrefix prefix, string name, string value)
{
return nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val.Split(' ').Contains(value)) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Split(' ').Contains(value));
});
}
public Selector<SvgElement> AttributeDashMatch(NamespacePrefix prefix, string name, string value)
{
return string.IsNullOrEmpty(value)
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>())
: (nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val.Split('-').Contains(value)) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Split('-').Contains(value));
}));
}
public Selector<SvgElement> AttributePrefixMatch(NamespacePrefix prefix, string name, string value)
{
return string.IsNullOrEmpty(value)
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>())
: (nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val.StartsWith(value)) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().StartsWith(value));
}));
}
public Selector<SvgElement> AttributeSuffixMatch(NamespacePrefix prefix, string name, string value)
{
return string.IsNullOrEmpty(value)
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>())
: (nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val.EndsWith(value)) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().EndsWith(value));
}));
}
public Selector<SvgElement> AttributeSubstring(NamespacePrefix prefix, string name, string value)
{
return string.IsNullOrEmpty(value)
? (Selector<SvgElement>)(nodes => Enumerable.Empty<SvgElement>())
: (nodes => nodes.Where(n =>
{
string val = null;
object oval = null;
return (n.CustomAttributes.TryGetValue(name, out val) && val.Contains(value)) ||
(n.Attributes.TryGetValue(name, out oval) && oval.ToString().Contains(value));
}));
}
public Selector<SvgElement> FirstChild()
{
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.First() == n);
}
public Selector<SvgElement> LastChild()
{
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.Last() == n);
}
private IEnumerable<T> GetByIds<T>(IList<T> items, IEnumerable<int> indices)
{
foreach (var i in indices)
{
if (i >= 0 && i < items.Count) yield return items[i];
}
}
public Selector<SvgElement> NthChild(int a, int b)
{
return nodes => nodes.Where(n => n.Parent != null && GetByIds(n.Parent.Children, (from i in Enumerable.Range(0, n.Parent.Children.Count / a) select a * i + b)).Contains(n));
}
public Selector<SvgElement> OnlyChild()
{
return nodes => nodes.Where(n => n.Parent == null || n.Parent.Children.Count == 1);
}
public Selector<SvgElement> Empty()
{
return nodes => nodes.Where(n => n.Children.Count == 0);
}
public Selector<SvgElement> Child()
{
return nodes => nodes.SelectMany(n => n.Children);
}
public Selector<SvgElement> Descendant()
{
return nodes => nodes.SelectMany(n => Descendants(n));
}
private IEnumerable<SvgElement> Descendants(SvgElement elem)
{
foreach (var child in elem.Children)
{
yield return child;
foreach (var descendant in child.Descendants())
{
yield return descendant;
}
}
}
public Selector<SvgElement> Adjacent()
{
return nodes => nodes.SelectMany(n => ElementsAfterSelf(n).Take(1));
}
public Selector<SvgElement> GeneralSibling()
{
return nodes => nodes.SelectMany(n => ElementsAfterSelf(n));
}
private IEnumerable<SvgElement> ElementsAfterSelf(SvgElement self)
{
return (self.Parent == null ? Enumerable.Empty<SvgElement>() : self.Parent.Children.Skip(self.Parent.Children.IndexOf(self) + 1));
}
public Selector<SvgElement> NthLastChild(int a, int b)
{
throw new NotImplementedException();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Svg
{
internal interface ISvgSupportsCoordinateUnits
{
SvgCoordinateUnits GetUnits();
}
}
......@@ -11,12 +11,12 @@ namespace Svg
public enum SvgCoordinateUnits
{
/// <summary>
/// Indicates that the coordinate system of the entire document is to be used.
/// Indicates that the coordinate system of the owner element is to be used.
/// </summary>
UserSpaceOnUse,
ObjectBoundingBox,
/// <summary>
/// Indicates that the coordinate system of the owner element is to be used.
/// Indicates that the coordinate system of the entire document is to be used.
/// </summary>
ObjectBoundingBox
UserSpaceOnUse
}
}
......@@ -23,9 +23,9 @@ namespace Svg
set { this.y = value; }
}
public PointF ToDeviceValue()
public PointF ToDeviceValue(SvgRenderer renderer, SvgElement owner)
{
return new PointF(this.X.ToDeviceValue(), this.Y.ToDeviceValue());
return SvgUnit.GetDevicePoint(this.X, this.Y, renderer, owner);
}
public bool IsEmpty()
......
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Drawing;
namespace Svg
{
......@@ -60,26 +62,9 @@ namespace Svg
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <param name="boundable">The container element used as the basis for calculations</param>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue()
{
return this.ToDeviceValue(null);
}
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue(ISvgBoundable boundable)
{
return this.ToDeviceValue(boundable, false);
}
/// <summary>
/// Converts the current unit to one that can be used at render time.
/// </summary>
/// <returns>The representation of the current unit in a device value (usually pixels).</returns>
public float ToDeviceValue(ISvgBoundable boundable, bool vertical)
public float ToDeviceValue(SvgRenderer renderer, UnitRenderingType renderType, SvgElement owner)
{
// If it's already been calculated
if (this._deviceValue.HasValue)
......@@ -99,60 +84,135 @@ namespace Svg
const float cmInInch = 2.54f;
int ppi = SvgDocument.PointsPerInch;
switch (this.Type)
var type = this.Type;
var value = this.Value;
// Deal with fractional pattern units
var coordElem = owner as ISvgSupportsCoordinateUnits;
if (coordElem != null && coordElem.GetUnits() == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage)
{
type = SvgUnitType.Percentage;
value *= 100;
}
var element = owner as SvgElement;
if (element != null)
{
var pattern = element.Parents.OfType<SvgPatternServer>().FirstOrDefault();
if (pattern != null && pattern.PatternContentUnits == SvgCoordinateUnits.ObjectBoundingBox && type != SvgUnitType.Percentage)
{
type = SvgUnitType.Percentage;
value *= 100;
}
}
float points;
Font currFont;
switch (type)
{
case SvgUnitType.Em:
var visualElem = boundable as SvgVisualElement;
if (visualElem == null)
currFont = GetFont(renderer, owner);
if (currFont == null)
{
float points = (float)(this.Value * 9);
points = (float)(value * 9);
_deviceValue = (points / 72) * ppi;
}
else
{
_deviceValue = this.Value * visualElem.GetInheritedFontSize().ToDeviceValue(boundable);
_deviceValue = value * (currFont.SizeInPoints / 72) * ppi;
}
break;
case SvgUnitType.Ex:
currFont = GetFont(renderer, owner);
if (currFont == null)
{
points = (float)(value * 9);
_deviceValue = (points / 72) * ppi / 2;
}
else
{
_deviceValue = value * (currFont.SizeInPoints / 72) * ppi * RelativeXHeight(currFont);
}
break;
case SvgUnitType.Centimeter:
_deviceValue = (float)((this.Value / cmInInch) * ppi);
_deviceValue = (float)((value / cmInInch) * ppi);
break;
case SvgUnitType.Inch:
_deviceValue = this.Value * ppi;
_deviceValue = value * ppi;
break;
case SvgUnitType.Millimeter:
_deviceValue = (float)((this.Value / 10) / cmInInch) * ppi;
_deviceValue = (float)((value / 10) / cmInInch) * ppi;
break;
case SvgUnitType.Pica:
_deviceValue = ((this.Value * 12) / 72) * ppi;
_deviceValue = ((value * 12) / 72) * ppi;
break;
case SvgUnitType.Point:
_deviceValue = (this.Value / 72) * ppi;
_deviceValue = (value / 72) * ppi;
break;
case SvgUnitType.Pixel:
_deviceValue = this.Value;
_deviceValue = value;
break;
case SvgUnitType.User:
_deviceValue = this.Value;
_deviceValue = value;
break;
case SvgUnitType.Percentage:
// Can't calculate if there is no style owner
var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.Boundable());
if (boundable == null)
{
_deviceValue = this.Value;
_deviceValue = value;
break;
}
// TODO : Support height percentages
System.Drawing.SizeF size = boundable.Bounds.Size;
_deviceValue = (((vertical) ? size.Height : size.Width) / 100) * this.Value;
switch (renderType)
{
case UnitRenderingType.Horizontal:
_deviceValue = (size.Width / 100) * value;
break;
case UnitRenderingType.HorizontalOffset:
_deviceValue = (size.Width / 100) * value + boundable.Location.X;
break;
case UnitRenderingType.Vertical:
_deviceValue = (size.Height / 100) * value;
break;
case UnitRenderingType.VerticalOffset:
_deviceValue = (size.Height / 100) * value + boundable.Location.Y;
break;
default:
_deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0);
break;
}
break;
default:
_deviceValue = this.Value;
_deviceValue = value;
break;
}
return this._deviceValue.Value;
}
private Font GetFont(SvgRenderer renderer, SvgElement owner)
{
if (owner == null) return null;
var visual = owner.ParentsAndSelf.OfType<SvgVisualElement>().FirstOrDefault();
return visual.GetFont(renderer);
}
private float RelativeXHeight(Font font)
{
var mediaFont = new System.Windows.Media.FontFamily(font.Name);
var sum = 0.0;
var cnt = 0;
foreach (var tf in mediaFont.FamilyTypefaces)
{
sum += tf.XHeight;
cnt += 1;
}
return (float)(sum / cnt);
}
/// <summary>
/// Converts the current unit to a percentage, if applicable.
/// </summary>
......@@ -249,7 +309,7 @@ namespace Svg
/// <returns>The result of the conversion.</returns>
public static implicit operator float(SvgUnit value)
{
return value.ToDeviceValue();
return value.ToDeviceValue(null, UnitRenderingType.Other, null);
}
/// <summary>
......@@ -286,6 +346,32 @@ namespace Svg
this._isEmpty = (this._value == 0.0f);
this._deviceValue = null;
}
public static System.Drawing.PointF GetDevicePoint(SvgUnit x, SvgUnit y, SvgRenderer renderer, SvgElement owner)
{
return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, owner),
y.ToDeviceValue(renderer, UnitRenderingType.Vertical, owner));
}
public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, SvgRenderer renderer, SvgElement owner)
{
return new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner),
y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner));
}
public static System.Drawing.SizeF GetDeviceSize(SvgUnit width, SvgUnit height, SvgRenderer renderer, SvgElement owner)
{
return new System.Drawing.SizeF(width.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner),
height.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner));
}
}
public enum UnitRenderingType
{
Other,
Horizontal,
HorizontalOffset,
Vertical,
VerticalOffset
}
/// <summary>
......@@ -306,6 +392,10 @@ namespace Svg
/// </summary>
Em,
/// <summary>
/// Indicates that the unit is equal to the x-height of the current font.
/// </summary>
Ex,
/// <summary>
/// Indicates that the unit is a percentage.
/// </summary>
Percentage,
......
......@@ -68,6 +68,8 @@ namespace Svg
return new SvgUnit(SvgUnitType.Percentage, val);
case "em":
return new SvgUnit(SvgUnitType.Em, val);
case "ex":
return new SvgUnit(SvgUnitType.Ex, val);
default:
throw new FormatException("Unit is in an invalid format '" + unit + "'.");
}
......
......@@ -127,20 +127,43 @@ namespace Svg
set { this.Attributes["preserveAspectRatio"] = value; }
}
/// <summary>
/// Refers to the size of the font from baseline to baseline when multiple lines of text are set solid in a multiline layout environment.
/// </summary>
[SvgAttribute("font-size")]
public virtual SvgUnit FontSize
{
get { return (this.Attributes["font-size"] == null) ? SvgUnit.Empty : (SvgUnit)this.Attributes["font-size"]; }
set { this.Attributes["font-size"] = value; }
}
/// <summary>
/// Indicates which font family is to be used to render the text.
/// </summary>
[SvgAttribute("font-family")]
public virtual string FontFamily
{
get { return this.Attributes["font-family"] as string; }
set { this.Attributes["font-family"] = value; }
}
/// <summary>
/// Applies the required transforms to <see cref="SvgRenderer"/>.
/// </summary>
/// <param name="renderer">The <see cref="SvgRenderer"/> to be transformed.</param>
protected internal override void PushTransforms(SvgRenderer renderer)
protected internal override bool PushTransforms(SvgRenderer renderer)
{
base.PushTransforms(renderer);
if (!base.PushTransforms(renderer)) return false;
if (!this.ViewBox.Equals(SvgViewBox.Empty))
{
float fScaleX = this.Width.ToDeviceValue(this, false) / this.ViewBox.Width;
float fScaleY = this.Height.ToDeviceValue(this, true) / this.ViewBox.Height;
float fMinX = -this.ViewBox.MinX;
float fMinY = -this.ViewBox.MinY;
var width = this.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var height = this.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
var fScaleX = width / this.ViewBox.Width;
var fScaleY = height / this.ViewBox.Height;
var fMinX = -this.ViewBox.MinX;
var fMinY = -this.ViewBox.MinY;
if (AspectRatio.Align != SvgPreserveAspectRatio.none)
{
......@@ -156,50 +179,56 @@ namespace Svg
}
float fViewMidX = (this.ViewBox.Width / 2) * fScaleX;
float fViewMidY = (this.ViewBox.Height / 2) * fScaleY;
float fMidX = this.Width.ToDeviceValue(this, false) / 2;
float fMidY = this.Height.ToDeviceValue(this, true) / 2;
float fMidX = width / 2;
float fMidY = height / 2;
switch (AspectRatio.Align)
{
case SvgPreserveAspectRatio.xMinYMin:
break;
case SvgPreserveAspectRatio.xMidYMin:
fMinX += (fMidX - fViewMidX) / fScaleX;
fMinX += fMidX - fViewMidX;
break;
case SvgPreserveAspectRatio.xMaxYMin:
fMinX += (this.Width.ToDeviceValue(this, false) / fScaleX) - this.ViewBox.Width;
fMinX += width - this.ViewBox.Width * fScaleX;
break;
case SvgPreserveAspectRatio.xMinYMid:
fMinY += (fMidY - fViewMidY) / fScaleY;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMidYMid:
fMinX += (fMidX - fViewMidX) / fScaleX;
fMinY += (fMidY - fViewMidY) / fScaleY;
fMinX += fMidX - fViewMidX;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMaxYMid:
fMinX += (this.Width.ToDeviceValue(this, false) / fScaleX) - this.ViewBox.Width;
fMinY += (fMidY - fViewMidY) / fScaleY;
fMinX += width - this.ViewBox.Width * fScaleX;
fMinY += fMidY - fViewMidY;
break;
case SvgPreserveAspectRatio.xMinYMax:
fMinY += (this.Height.ToDeviceValue(this, true) / fScaleY) - this.ViewBox.Height;
fMinY += height - this.ViewBox.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMidYMax:
fMinX += (fMidX - fViewMidX) / fScaleX;
fMinY += (this.Height.ToDeviceValue(this, true) / fScaleY) - this.ViewBox.Height;
fMinX += fMidX - fViewMidX;
fMinY += height - this.ViewBox.Height * fScaleY;
break;
case SvgPreserveAspectRatio.xMaxYMax:
fMinX += (this.Width.ToDeviceValue(this, false) / fScaleX) - this.ViewBox.Width;
fMinY += (this.Height.ToDeviceValue(this, true) / fScaleY) - this.ViewBox.Height;
fMinX += width - this.ViewBox.Width * fScaleX;
fMinY += height - this.ViewBox.Height * fScaleY;
break;
default:
break;
}
}
renderer.TranslateTransform(_x, _y);
var x = _x.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this);
var y = _y.ToDeviceValue(renderer, UnitRenderingType.Vertical, this);
renderer.AddClip(new Region(new RectangleF(x, y, width, height)));
renderer.ScaleTransform(fScaleX, fScaleY, MatrixOrder.Prepend);
renderer.TranslateTransform(x,y);
renderer.TranslateTransform(fMinX, fMinY);
renderer.ScaleTransform(fScaleX, fScaleY);
}
return true;
}
/// <summary>
......@@ -245,18 +274,38 @@ namespace Svg
public SizeF GetDimensions()
{
var w = Width.ToDeviceValue();
var h = Height.ToDeviceValue();
RectangleF bounds = new RectangleF();
float w, h;
var isWidthperc = Width.Type == SvgUnitType.Percentage;
var isHeightperc = Height.Type == SvgUnitType.Percentage;
RectangleF bounds = new RectangleF();
if (isWidthperc || isHeightperc)
{
bounds = this.Bounds; //do just one call to the recursive bounds property
if (isWidthperc) w = (bounds.Width + bounds.X) * (w * 0.01f);
if (isHeightperc) h = (bounds.Height + bounds.Y) * (h * 0.01f);
if (ViewBox.Width > 0 && ViewBox.Height > 0)
{
bounds = new RectangleF(ViewBox.MinX, ViewBox.MinY, ViewBox.Width, ViewBox.Height);
}
else
{
bounds = this.Bounds; //do just one call to the recursive bounds property
}
}
if (isWidthperc)
{
w = (bounds.Width + bounds.X) * (Width.Value * 0.01f);
}
else
{
w = Width.ToDeviceValue(null, UnitRenderingType.Horizontal, this);
}
if (isHeightperc)
{
h = (bounds.Height + bounds.Y) * (Height.Value * 0.01f);
}
else
{
h = Height.ToDeviceValue(null, UnitRenderingType.Vertical, this);
}
return new SizeF(w, h);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment