123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361 |
- // Copyright (c) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
- /***************************************************************************
- * HTML elements handled in this module:
- *
- * a
- * b
- * body
- * caption
- * div
- * em
- * h1, h2, h3, h4, h5, h6, h7, h8
- * hr
- * html
- * i
- * blockquote
- * img
- * li
- * ol
- * p
- * s
- * span
- * strong
- * style
- * sub
- * sup
- * table
- * tbody
- * td
- * th
- * tr
- * u
- * ul
- * br
- * tt
- * code
- * kbd
- * samp
- * pre
- *
- * HTML elements that are handled by recursively processing descedants
- *
- * article
- * hgroup
- * nav
- * section
- * dd
- * dl
- * dt
- * figure
- * main
- * abbr
- * bdi
- * bdo
- * cite
- * data
- * dfn
- * mark
- * q
- * rp
- * rt
- * ruby
- * small
- * time
- * var
- * wbr
- *
- * HTML elements ignored in this module
- *
- * head
- *
- ***************************************************************************/
- // need to research all of the html attributes that take effect, such as border="1" and somehow work into the rendering system.
- // note that some of these 'inherit' so need to implement correct logic.
- // this module has not been fully engineered to work with RTL languages. This is a pending work item. There are issues involved,
- // including that there is RTL content in HTML that can't be represented in WordprocessingML, although this probably is rare.
- // The reverse is not true - all RTL WordprocessingML can be represented in HTML, but there is some HTML RTL content that can only
- // be approximated in WordprocessingML.
- // have I handled all forms of colors? see GetWmlColorFromExpression in HtmlToWmlCssApplier
- // min-height and max-height not implemented yet.
- // internal hyperlinks are not supported. I believe it possible - bookmarks can be created, hyperlinks to the bookmark can be created.
- // To be supported in future
- // page-break-before:always
- // ************************************************************************
- // ToDo at some point in the future
- // I'm not implementing caption exactly correctly. If caption does not have borders, then there needs to not be a border around the table,
- // otherwise it looks as if caption has a border. See T1200. If there is, per the markup, a table border, but caption does not have a border,
- // then need to make sure that all of the cells below the caption have the border on the appropriate sides so that it looks as if the table
- // has a border.
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Xml.Linq;
- using DocumentFormat.OpenXml.Packaging;
- using OpenXmlPowerTools;
- using OpenXmlPowerTools.HtmlToWml;
- using OpenXmlPowerTools.HtmlToWml.CSS;
- using System.Text.RegularExpressions;
- namespace OpenXmlPowerTools.HtmlToWml
- {
- public class ElementToStyleMap
- {
- public string ElementName;
- public string StyleName;
- }
- public static class LocalExtensions
- {
- public static CssExpression GetProp(this XElement element, string propertyName)
- {
- Dictionary<string, CssExpression> d = element.Annotation<Dictionary<string, CssExpression>>();
- if (d != null)
- {
- if (d.ContainsKey(propertyName))
- return d[propertyName];
- }
- return null;
- }
- }
- public class HtmlToWmlConverterCore
- {
- public static WmlDocument ConvertHtmlToWml(
- string defaultCss,
- string authorCss,
- string userCss,
- XElement xhtml,
- HtmlToWmlConverterSettings settings)
- {
- return ConvertHtmlToWml(defaultCss, authorCss, userCss, xhtml, settings, null, null);
- }
- public static WmlDocument ConvertHtmlToWml(
- string defaultCss,
- string authorCss,
- string userCss,
- XElement xhtml,
- HtmlToWmlConverterSettings settings,
- WmlDocument emptyDocument,
- string annotatedHtmlDumpFileName)
- {
- if (emptyDocument == null)
- emptyDocument = HtmlToWmlConverter.EmptyDocument;
- NextRectId = 1025;
- // clone and transform all element names to lower case
- XElement html = (XElement)TransformToLower(xhtml);
- // add pseudo cells for rowspan
- html = (XElement)AddPseudoCells(html);
- html = (XElement)TransformWhiteSpaceInPreCodeTtKbdSamp(html, false, false);
- CssDocument defaultCssDoc, userCssDoc, authorCssDoc;
- CssApplier.ApplyAllCss(
- defaultCss,
- authorCss,
- userCss,
- html,
- settings,
- out defaultCssDoc,
- out authorCssDoc,
- out userCssDoc,
- annotatedHtmlDumpFileName);
- WmlDocument newWmlDocument;
- using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(emptyDocument))
- {
- using (WordprocessingDocument wDoc = streamDoc.GetWordprocessingDocument())
- {
- AnnotateOlUl(wDoc, html);
- UpdateMainDocumentPart(wDoc, html, settings);
- NormalizeMainDocumentPart(wDoc);
- StylesUpdater.UpdateStylesPart(wDoc, html, settings, defaultCssDoc, authorCssDoc, userCssDoc);
- HtmlToWmlFontUpdater.UpdateFontsPart(wDoc, html, settings);
- ThemeUpdater.UpdateThemePart(wDoc, html, settings);
- NumberingUpdater.UpdateNumberingPart(wDoc, html, settings);
- }
- newWmlDocument = streamDoc.GetModifiedWmlDocument();
- }
- return newWmlDocument;
- }
- private static object TransformToLower(XNode node)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- XElement e = new XElement(element.Name.LocalName.ToLower(),
- element.Attributes().Select(a => new XAttribute(a.Name.LocalName.ToLower(), a.Value)),
- element.Nodes().Select(n => TransformToLower(n)));
- return e;
- }
- return node;
- }
- private static XElement AddPseudoCells(XElement html)
- {
- while (true)
- {
- var rowSpanCell = html
- .Descendants(XhtmlNoNamespace.td)
- .FirstOrDefault(td => td.Attribute(XhtmlNoNamespace.rowspan) != null && td.Attribute("HtmlToWmlVMergeRestart") == null);
- if (rowSpanCell == null)
- break;
- rowSpanCell.Add(
- new XAttribute("HtmlToWmlVMergeRestart", "true"));
- int colNumber = rowSpanCell.ElementsBeforeSelf(XhtmlNoNamespace.td).Count();
- int numberPseudoToAdd = (int)rowSpanCell.Attribute(XhtmlNoNamespace.rowspan) - 1;
- var tr = rowSpanCell.Ancestors(XhtmlNoNamespace.tr).FirstOrDefault();
- if (tr == null)
- throw new OpenXmlPowerToolsException("Invalid HTML - td does not have parent tr");
- var rowsToAddTo = tr
- .ElementsAfterSelf(XhtmlNoNamespace.tr)
- .Take(numberPseudoToAdd)
- .ToList();
- foreach (var rowToAddTo in rowsToAddTo)
- {
- if (colNumber > 0)
- {
- var tdToAddAfter = rowToAddTo
- .Elements(XhtmlNoNamespace.td)
- .Skip(colNumber - 1)
- .FirstOrDefault();
- var td = new XElement(XhtmlNoNamespace.td,
- rowSpanCell.Attributes(),
- new XAttribute("HtmlToWmlVMergeNoRestart", "true"));
- tdToAddAfter.AddAfterSelf(td);
- }
- else
- {
- var tdToAddBefore = rowToAddTo
- .Elements(XhtmlNoNamespace.td)
- .Skip(colNumber)
- .FirstOrDefault();
- var td = new XElement(XhtmlNoNamespace.td,
- rowSpanCell.Attributes(),
- new XAttribute("HtmlToWmlVMergeNoRestart", "true"));
- tdToAddBefore.AddBeforeSelf(td);
- }
- }
- }
- return html;
- }
- public class NumberedItemAnnotation
- {
- public int numId;
- public int ilvl;
- public string listStyleType;
- }
- private static void AnnotateOlUl(WordprocessingDocument wDoc, XElement html)
- {
- int numId;
- NumberingUpdater.GetNextNumId(wDoc, out numId);
- foreach (var item in html.DescendantsAndSelf().Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul))
- {
- XElement parentOlUl = item.Ancestors().Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul).LastOrDefault();
- int numIdToUse;
- if (parentOlUl != null)
- numIdToUse = parentOlUl.Annotation<NumberedItemAnnotation>().numId;
- else
- numIdToUse = numId++;
- string lst = CssApplier.GetComputedPropertyValue(null, item, "list-style-type", null).ToString();
- item.AddAnnotation(new NumberedItemAnnotation
- {
- numId = numIdToUse,
- ilvl = item.Ancestors().Where(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul).Count(),
- listStyleType = lst,
- });
- }
- }
- private static void UpdateMainDocumentPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings)
- {
- XDocument xDoc = XDocument.Parse(
- @"<w:document xmlns:wpc='http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas'
- xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006'
- xmlns:o='urn:schemas-microsoft-com:office:office'
- xmlns:r='http://schemas.openxmlformats.org/officeDocument/2006/relationships'
- xmlns:m='http://schemas.openxmlformats.org/officeDocument/2006/math'
- xmlns:v='urn:schemas-microsoft-com:vml'
- xmlns:wp14='http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing'
- xmlns:wp='http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'
- xmlns:w10='urn:schemas-microsoft-com:office:word'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'
- xmlns:w14='http://schemas.microsoft.com/office/word/2010/wordml'
- xmlns:wpg='http://schemas.microsoft.com/office/word/2010/wordprocessingGroup'
- xmlns:wpi='http://schemas.microsoft.com/office/word/2010/wordprocessingInk'
- xmlns:wne='http://schemas.microsoft.com/office/word/2006/wordml'
- xmlns:wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape'
- mc:Ignorable='w14 wp14'/>");
- XElement body = new XElement(W.body,
- Transform(html, settings, wDoc, NextExpected.Paragraph, false),
- settings.SectPr);
- AddNonBreakingSpacesForSpansWithWidth(wDoc, body);
- body = (XElement)TransformAndOrderElements(body);
- foreach (var d in body.Descendants())
- d.Attributes().Where(a => a.Name.Namespace == PtOpenXml.pt).Remove();
- xDoc.Root.Add(body);
- wDoc.MainDocumentPart.PutXDocument(xDoc);
- }
- private static object TransformWhiteSpaceInPreCodeTtKbdSamp(XNode node, bool inPre, bool inOther)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- if (element.Name == XhtmlNoNamespace.pre)
- {
- return new XElement(element.Name,
- element.Attributes(),
- element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, true, false)));
- }
- if (element.Name == XhtmlNoNamespace.code ||
- element.Name == XhtmlNoNamespace.tt ||
- element.Name == XhtmlNoNamespace.kbd ||
- element.Name == XhtmlNoNamespace.samp)
- {
- return new XElement(element.Name,
- element.Attributes(),
- element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, true)));
- }
- return new XElement(element.Name,
- element.Attributes(),
- element.Nodes().Select(n => TransformWhiteSpaceInPreCodeTtKbdSamp(n, false, false)));
- }
- XText xt = node as XText;
- if (xt != null && inPre)
- {
- var val = xt.Value.TrimStart('\r', '\n').TrimEnd('\r', '\n');
- var groupedCharacters = val.GroupAdjacent(c => c == '\r' || c == '\n');
- var newNodes = groupedCharacters.Select(g =>
- {
- if (g.Key == true)
- return (object)(new XElement(XhtmlNoNamespace.br));
- string x = g.Select(c => c.ToString()).StringConcatenate();
- return new XText(x);
- });
- return newNodes;
- }
- if (xt != null && inOther)
- {
- var val = xt.Value.TrimStart('\r', '\n', '\t', ' ').TrimEnd('\r', '\n', '\t', ' ');
- return new XText(val);
- }
- return node;
- }
- private static Dictionary<XName, int> Order_pPr = new Dictionary<XName, int>
- {
- { W.pStyle, 10 },
- { W.keepNext, 20 },
- { W.keepLines, 30 },
- { W.pageBreakBefore, 40 },
- { W.framePr, 50 },
- { W.widowControl, 60 },
- { W.numPr, 70 },
- { W.suppressLineNumbers, 80 },
- { W.pBdr, 90 },
- { W.shd, 100 },
- { W.tabs, 120 },
- { W.suppressAutoHyphens, 130 },
- { W.kinsoku, 140 },
- { W.wordWrap, 150 },
- { W.overflowPunct, 160 },
- { W.topLinePunct, 170 },
- { W.autoSpaceDE, 180 },
- { W.autoSpaceDN, 190 },
- { W.bidi, 200 },
- { W.adjustRightInd, 210 },
- { W.snapToGrid, 220 },
- { W.spacing, 230 },
- { W.ind, 240 },
- { W.contextualSpacing, 250 },
- { W.mirrorIndents, 260 },
- { W.suppressOverlap, 270 },
- { W.jc, 280 },
- { W.textDirection, 290 },
- { W.textAlignment, 300 },
- { W.textboxTightWrap, 310 },
- { W.outlineLvl, 320 },
- { W.divId, 330 },
- { W.cnfStyle, 340 },
- { W.rPr, 350 },
- { W.sectPr, 360 },
- { W.pPrChange, 370 },
- };
- private static Dictionary<XName, int> Order_rPr = new Dictionary<XName, int>
- {
- { W.moveFrom, 5 },
- { W.moveTo, 7 },
- { W.ins, 10 },
- { W.del, 20 },
- { W.rStyle, 30 },
- { W.rFonts, 40 },
- { W.b, 50 },
- { W.bCs, 60 },
- { W.i, 70 },
- { W.iCs, 80 },
- { W.caps, 90 },
- { W.smallCaps, 100 },
- { W.strike, 110 },
- { W.dstrike, 120 },
- { W.outline, 130 },
- { W.shadow, 140 },
- { W.emboss, 150 },
- { W.imprint, 160 },
- { W.noProof, 170 },
- { W.snapToGrid, 180 },
- { W.vanish, 190 },
- { W.webHidden, 200 },
- { W.color, 210 },
- { W.spacing, 220 },
- { W._w, 230 },
- { W.kern, 240 },
- { W.position, 250 },
- { W.sz, 260 },
- { W14.wShadow, 270 },
- { W14.wTextOutline, 280 },
- { W14.wTextFill, 290 },
- { W14.wScene3d, 300 },
- { W14.wProps3d, 310 },
- { W.szCs, 320 },
- { W.highlight, 330 },
- { W.u, 340 },
- { W.effect, 350 },
- { W.bdr, 360 },
- { W.shd, 370 },
- { W.fitText, 380 },
- { W.vertAlign, 390 },
- { W.rtl, 400 },
- { W.cs, 410 },
- { W.em, 420 },
- { W.lang, 430 },
- { W.eastAsianLayout, 440 },
- { W.specVanish, 450 },
- { W.oMath, 460 },
- };
- private static Dictionary<XName, int> Order_tblPr = new Dictionary<XName, int>
- {
- { W.tblStyle, 10 },
- { W.tblpPr, 20 },
- { W.tblOverlap, 30 },
- { W.bidiVisual, 40 },
- { W.tblStyleRowBandSize, 50 },
- { W.tblStyleColBandSize, 60 },
- { W.tblW, 70 },
- { W.jc, 80 },
- { W.tblCellSpacing, 90 },
- { W.tblInd, 100 },
- { W.tblBorders, 110 },
- { W.shd, 120 },
- { W.tblLayout, 130 },
- { W.tblCellMar, 140 },
- { W.tblLook, 150 },
- { W.tblCaption, 160 },
- { W.tblDescription, 170 },
- };
- private static Dictionary<XName, int> Order_tblBorders = new Dictionary<XName, int>
- {
- { W.top, 10 },
- { W.left, 20 },
- { W.start, 30 },
- { W.bottom, 40 },
- { W.right, 50 },
- { W.end, 60 },
- { W.insideH, 70 },
- { W.insideV, 80 },
- };
- private static Dictionary<XName, int> Order_tcPr = new Dictionary<XName, int>
- {
- { W.cnfStyle, 10 },
- { W.tcW, 20 },
- { W.gridSpan, 30 },
- { W.hMerge, 40 },
- { W.vMerge, 50 },
- { W.tcBorders, 60 },
- { W.shd, 70 },
- { W.noWrap, 80 },
- { W.tcMar, 90 },
- { W.textDirection, 100 },
- { W.tcFitText, 110 },
- { W.vAlign, 120 },
- { W.hideMark, 130 },
- { W.headers, 140 },
- };
- private static Dictionary<XName, int> Order_tcBorders = new Dictionary<XName, int>
- {
- { W.top, 10 },
- { W.start, 20 },
- { W.left, 30 },
- { W.bottom, 40 },
- { W.right, 50 },
- { W.end, 60 },
- { W.insideH, 70 },
- { W.insideV, 80 },
- { W.tl2br, 90 },
- { W.tr2bl, 100 },
- };
- private static Dictionary<XName, int> Order_pBdr = new Dictionary<XName, int>
- {
- { W.top, 10 },
- { W.left, 20 },
- { W.bottom, 30 },
- { W.right, 40 },
- { W.between, 50 },
- { W.bar, 60 },
- };
- private static object TransformAndOrderElements(XNode node)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- if (element.Name == W.pPr)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_pPr.ContainsKey(e.Name))
- return Order_pPr[e.Name];
- return 999;
- }));
- if (element.Name == W.rPr)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_rPr.ContainsKey(e.Name))
- return Order_rPr[e.Name];
- return 999;
- }));
- if (element.Name == W.tblPr)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_tblPr.ContainsKey(e.Name))
- return Order_tblPr[e.Name];
- return 999;
- }));
- if (element.Name == W.tcPr)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_tcPr.ContainsKey(e.Name))
- return Order_tcPr[e.Name];
- return 999;
- }));
- if (element.Name == W.tcBorders)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_tcBorders.ContainsKey(e.Name))
- return Order_tcBorders[e.Name];
- return 999;
- }));
- if (element.Name == W.tblBorders)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_tblBorders.ContainsKey(e.Name))
- return Order_tblBorders[e.Name];
- return 999;
- }));
- if (element.Name == W.pBdr)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements().Select(e => (XElement)TransformAndOrderElements(e)).OrderBy(e =>
- {
- if (Order_pBdr.ContainsKey(e.Name))
- return Order_pBdr[e.Name];
- return 999;
- }));
- if (element.Name == W.p)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements(W.pPr).Select(e => (XElement)TransformAndOrderElements(e)),
- element.Elements().Where(e => e.Name != W.pPr).Select(e => (XElement)TransformAndOrderElements(e)));
- if (element.Name == W.r)
- return new XElement(element.Name,
- element.Attributes(),
- element.Elements(W.rPr).Select(e => (XElement)TransformAndOrderElements(e)),
- element.Elements().Where(e => e.Name != W.rPr).Select(e => (XElement)TransformAndOrderElements(e)));
- return new XElement(element.Name,
- element.Attributes(),
- element.Nodes().Select(n => TransformAndOrderElements(n)));
- }
- return node;
- }
- private static void AddNonBreakingSpacesForSpansWithWidth(WordprocessingDocument wDoc, XElement body)
- {
- List<XElement> runsWithWidth = body
- .Descendants(W.r)
- .Where(r => r.Attribute(PtOpenXml.HtmlToWmlCssWidth) != null)
- .ToList();
- foreach (XElement run in runsWithWidth)
- {
- XElement p = run.Ancestors(W.p).FirstOrDefault();
- XElement pPr = p != null ? p.Element(W.pPr) : null;
- XElement rPr = run.Element(W.rPr);
- XElement rFonts = rPr != null ? rPr.Element(W.rFonts) : null;
- string str = run.Descendants(W.t).Select(t => (string) t).StringConcatenate();
- if ((pPr == null) || (rPr == null) || (rFonts == null) || (str == "")) continue;
- AdjustFontAttributes(wDoc, run, pPr, rPr);
- var csa = new CharStyleAttributes(pPr, rPr);
- char charToExamine = str.FirstOrDefault(c => !WeakAndNeutralDirectionalCharacters.Contains(c));
- if (charToExamine == '\0')
- charToExamine = str[0];
- FontType ft = DetermineFontTypeFromCharacter(charToExamine, csa);
- string fontType = null;
- string languageType = null;
- switch (ft)
- {
- case FontType.Ascii:
- fontType = (string) rFonts.Attribute(W.ascii);
- languageType = "western";
- break;
- case FontType.HAnsi:
- fontType = (string) rFonts.Attribute(W.hAnsi);
- languageType = "western";
- break;
- case FontType.EastAsia:
- fontType = (string) rFonts.Attribute(W.eastAsia);
- languageType = "eastAsia";
- break;
- case FontType.CS:
- fontType = (string) rFonts.Attribute(W.cs);
- languageType = "bidi";
- break;
- }
- if (fontType != null)
- {
- XAttribute fontNameAttribute = run.Attribute(PtOpenXml.FontName);
- if (fontNameAttribute == null)
- run.Add(new XAttribute(PtOpenXml.FontName, fontType));
- else
- fontNameAttribute.SetValue(fontType);
- }
- if (languageType != null)
- {
- XAttribute languageTypeAttribute = run.Attribute(PtOpenXml.LanguageType);
- if (languageTypeAttribute == null)
- {
- run.Add(new XAttribute(PtOpenXml.LanguageType, languageType));
- }
- else
- {
- languageTypeAttribute.SetValue(languageType);
- }
- }
- int pixWidth = CalcWidthOfRunInPixels(run) ?? 0;
- // calc width of non breaking spaces
- var npSpRun = new XElement(W.r,
- run.Attributes(),
- run.Elements(W.rPr),
- new XElement(W.t, "\u00a0"));
- int nbSpWidth = CalcWidthOfRunInPixels(npSpRun) ?? 0;
- if (nbSpWidth == 0)
- continue;
- // get HtmlToWmlCssWidth attribute
- var cssWidth = (string) run.Attribute(PtOpenXml.HtmlToWmlCssWidth);
- if (!cssWidth.EndsWith("pt")) continue;
- cssWidth = cssWidth.Substring(0, cssWidth.Length - 2);
- decimal cssWidthInDecimal;
- if (!decimal.TryParse(cssWidth, out cssWidthInDecimal)) continue;
- // calculate the number of non-breaking spaces to add
- decimal cssWidthInPixels = cssWidthInDecimal/72*96;
- var numberOfNpSpToAdd = (int) ((cssWidthInPixels - pixWidth)/nbSpWidth);
- if (numberOfNpSpToAdd > 0)
- run.Add(new XElement(W.t, "".PadRight(numberOfNpSpToAdd, '\u00a0')));
- }
- }
- private static void NormalizeMainDocumentPart(WordprocessingDocument wDoc)
- {
- XDocument mainXDoc = wDoc.MainDocumentPart.GetXDocument();
- XElement newRoot = (XElement)NormalizeTransform(mainXDoc.Root);
- mainXDoc.Root.ReplaceWith(newRoot);
- wDoc.MainDocumentPart.PutXDocument();
- }
- private static object NormalizeTransform(XNode node)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- if (element.Name == W.p && element.Elements().Any(c => c.Name == W.p || c.Name == W.tbl))
- {
- var groupedChildren = element.Elements()
- .GroupAdjacent(e => e.Name == W.p || e.Name == W.tbl);
- var newContent = groupedChildren
- .Select(g =>
- {
- if (g.Key == false)
- {
- XElement paragraph = new XElement(W.p,
- element.Elements(W.pPr),
- g.Where(gc => gc.Name != W.pPr));
- return (object)paragraph;
- }
- return g.Select(n => NormalizeTransform(n));
- });
- return newContent;
- }
- return new XElement(element.Name,
- element.Attributes(),
- element.Nodes().Select(n => NormalizeTransform(n)));
- }
- return node;
- }
- private enum NextExpected
- {
- Paragraph,
- Run,
- SubRun,
- }
- private static object Transform(XNode node, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, NextExpected nextExpected, bool preserveWhiteSpace)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- if (element.Name == XhtmlNoNamespace.a)
- {
- string rId = "R" + Guid.NewGuid().ToString().Replace("-", "");
- string href = (string)element.Attribute(NoNamespace.href);
- if (href != null)
- {
- Uri uri = null;
- try
- {
- uri = new Uri(href);
- }
- catch (UriFormatException)
- {
- XElement rPr = GetRunProperties(element, settings);
- XElement run = new XElement(W.r,
- rPr,
- new XElement(W.t, element.Value));
- return new[] { run };
- }
- if (uri != null)
- {
- wDoc.MainDocumentPart.AddHyperlinkRelationship(uri, true, rId);
- if (element.Element(XhtmlNoNamespace.img) != null)
- {
- var imageTransformed = element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)).OfType<XElement>();
- var newImageTransformed = imageTransformed
- .Select(i =>
- {
- if (i.Elements(W.drawing).Any())
- {
- var newRun = new XElement(i);
- var docPr = newRun.Elements(W.drawing).Elements(WP.inline).Elements(WP.docPr).FirstOrDefault();
- if (docPr != null)
- {
- var hlinkClick = new XElement(A.hlinkClick,
- new XAttribute(R.id, rId),
- new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName));
- docPr.Add(hlinkClick);
- }
- return newRun;
- }
- return i;
- })
- .ToList();
- return newImageTransformed;
- }
- XElement rPr = GetRunProperties(element, settings);
- XElement hyperlink = new XElement(W.hyperlink,
- new XAttribute(R.id, rId),
- new XElement(W.r,
- rPr,
- new XElement(W.t, element.Value)));
- return new[] { hyperlink };
- }
- }
- return null;
- }
- if (element.Name == XhtmlNoNamespace.b)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.body)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.caption)
- {
- return new XElement(W.tr,
- GetTableRowProperties(element),
- new XElement(W.tc,
- GetCellPropertiesForCaption(element),
- element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace))));
- }
- if (element.Name == XhtmlNoNamespace.div)
- {
- if (nextExpected == NextExpected.Paragraph)
- {
- if (element.Descendants().Any(d => d.Name == XhtmlNoNamespace.h1 ||
- d.Name == XhtmlNoNamespace.li ||
- d.Name == XhtmlNoNamespace.p ||
- d.Name == XhtmlNoNamespace.table))
- {
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- }
- else
- {
- return GenerateNextExpected(element, settings, wDoc, null, nextExpected, false);
- }
- }
- else
- {
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- }
- }
- if (element.Name == XhtmlNoNamespace.em)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace));
- HeadingInfo hi = HeadingTagMap.FirstOrDefault(htm => htm.Name == element.Name);
- if (hi != null)
- {
- return GenerateNextExpected(element, settings, wDoc, hi.StyleName, NextExpected.Paragraph, false);
- }
- if (element.Name == XhtmlNoNamespace.hr)
- {
- int i = GetNextRectId();
- XElement hr = XElement.Parse(
- @"<w:p xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'
- xmlns:o='urn:schemas-microsoft-com:office:office'
- xmlns:w14='http://schemas.microsoft.com/office/word/2010/wordml'
- xmlns:v='urn:schemas-microsoft-com:vml'>
- <w:r>
- <w:pict w14:anchorId='0DBC9ADE'>
- <v:rect id='_x0000_i" + i + @"'
- style='width:0;height:1.5pt'
- o:hralign='center'
- o:hrstd='t'
- o:hr='t'
- fillcolor='#a0a0a0'
- stroked='f'/>
- </w:pict>
- </w:r>
- </w:p>");
- hr.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
- return hr;
- }
- if (element.Name == XhtmlNoNamespace.html)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.i)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.blockquote)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.img)
- {
- if (element.Parent.Name == XhtmlNoNamespace.body)
- {
- XElement para = new XElement(W.p,
- GetParagraphPropertiesForImage(),
- TransformImageToWml(element, settings, wDoc));
- return para;
- }
- else
- {
- XElement content = TransformImageToWml(element, settings, wDoc);
- return content;
- }
- }
- if (element.Name == XhtmlNoNamespace.li)
- {
- return GenerateNextExpected(element, settings, wDoc, null, NextExpected.Paragraph, false);
- }
- if (element.Name == XhtmlNoNamespace.ol)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.p)
- {
- return GenerateNextExpected(element, settings, wDoc, null, NextExpected.Paragraph, false);
- }
- if (element.Name == XhtmlNoNamespace.s)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- /****************************************** SharePoint Specific ********************************************/
- // todo sharepoint specific
- //if (element.Name == Xhtml.div && (string)element.Attribute(Xhtml._class) == "ms-rteElement-Callout1")
- //{
- // return new XElement(W.p,
- // // todo need a style for class
- // new XElement(W.pPr,
- // new XElement(W.pStyle,
- // new XAttribute(W.val, "ms-rteElement-Callout1"))),
- // new XElement(W.r,
- // new XElement(W.t, element.Value)));
- //}
- if (element.Name == XhtmlNoNamespace.span && (string)element.Attribute(XhtmlNoNamespace.id) == "layoutsData")
- return null;
- /****************************************** End SharePoint Specific ********************************************/
- if (element.Name == XhtmlNoNamespace.span)
- {
- var spanReplacement = element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- var dummyElement = new XElement("dummy", spanReplacement);
- var firstChild = dummyElement.Elements().FirstOrDefault();
- XElement run = null;
- if (firstChild != null && firstChild.Name == W.r)
- run = firstChild;
- if (run != null)
- {
- Dictionary<string, CssExpression> computedProperties = element.Annotation<Dictionary<string, CssExpression>>();
- if (computedProperties != null && computedProperties.ContainsKey("width"))
- {
- string width = computedProperties["width"];
- if (width != "auto")
- run.Add(new XAttribute(PtOpenXml.HtmlToWmlCssWidth, width));
- var rFontsLocal = run.Element(W.rFonts);
- XElement rFontsGlobal = null;
- var styleDefPart = wDoc.MainDocumentPart.StyleDefinitionsPart;
- if (styleDefPart != null)
- {
- rFontsGlobal = styleDefPart.GetXDocument().Root.Elements(W.docDefaults).Elements(W.rPrDefault).Elements(W.rPr).Elements(W.rFonts).FirstOrDefault();
- }
- var rFontsNew = FontMerge(rFontsLocal, rFontsGlobal);
- var rPr = run.Element(W.rPr);
- if (rPr != null)
- {
- var rFontsExisting = rPr.Element(W.rFonts);
- if (rFontsExisting == null)
- rPr.AddFirst(rFontsGlobal);
- else
- rFontsExisting.ReplaceWith(rFontsGlobal);
- }
- }
- return dummyElement.Elements();
- }
- return spanReplacement;
- }
- if (element.Name == XhtmlNoNamespace.strong)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.style)
- return null;
- if (element.Name == XhtmlNoNamespace.sub)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.sup)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.table)
- {
- XElement wmlTable = new XElement(W.tbl,
- GetTableProperties(element),
- GetTableGrid(element, settings),
- element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)));
- return wmlTable;
- }
- if (element.Name == XhtmlNoNamespace.tbody)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.td)
- {
- var tdText = element.DescendantNodes().OfType<XText>().Select(t => t.Value).StringConcatenate().Trim();
- var hasOtherThanSpansAndParas = element.Descendants().Any(d => d.Name != XhtmlNoNamespace.span && d.Name != XhtmlNoNamespace.p);
- if (tdText != "" || hasOtherThanSpansAndParas)
- {
- var newElementRaw = new XElement("dummy", element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Paragraph, preserveWhiteSpace)));
- var newElements = new XElement("dummy",
- newElementRaw
- .Elements()
- .Select(e =>
- {
- if (e.Name == W.hyperlink || e.Name == W.r)
- return new XElement(W.p, e);
- return e;
- }));
- return new XElement(W.tc,
- GetCellProperties(element),
- newElements.Elements());
- }
- else
- {
- XElement p;
- p = new XElement(W.p,
- GetParagraphProperties(element, null, settings),
- new XElement(W.r,
- GetRunProperties(element, settings),
- new XElement(W.t, "")));
- return new XElement(W.tc,
- GetCellProperties(element), p);
- }
- }
- if (element.Name == XhtmlNoNamespace.th)
- {
- return new XElement(W.tc,
- GetCellHeaderProperties(element),
- element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)));
- }
- if (element.Name == XhtmlNoNamespace.tr)
- {
- return new XElement(W.tr,
- GetTableRowProperties(element),
- element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace)));
- }
- if (element.Name == XhtmlNoNamespace.u)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.ul)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.br)
- if (nextExpected == NextExpected.Paragraph)
- {
- return new XElement(W.p,
- new XElement(W.r,
- new XElement(W.t)));
- }
- else
- {
- return new XElement(W.r, new XElement(W.br));
- }
- if (element.Name == XhtmlNoNamespace.tt || element.Name == XhtmlNoNamespace.code || element.Name == XhtmlNoNamespace.kbd || element.Name == XhtmlNoNamespace.samp)
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- if (element.Name == XhtmlNoNamespace.pre)
- return GenerateNextExpected(element, settings, wDoc, null, NextExpected.Paragraph, true);
- // if no match up to this point, then just recursively process descendants
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- }
- if (node.Parent.Name != XhtmlNoNamespace.title)
- return GenerateNextExpected(node, settings, wDoc, null, nextExpected, preserveWhiteSpace);
- return null;
- }
- private static XElement FontMerge(XElement higherPriorityFont, XElement lowerPriorityFont)
- {
- XElement rFonts;
- if (higherPriorityFont == null)
- return lowerPriorityFont;
- if (lowerPriorityFont == null)
- return higherPriorityFont;
- if (higherPriorityFont == null && lowerPriorityFont == null)
- return null;
- rFonts = new XElement(W.rFonts,
- (higherPriorityFont.Attribute(W.ascii) != null || higherPriorityFont.Attribute(W.asciiTheme) != null) ?
- new[] { higherPriorityFont.Attribute(W.ascii), higherPriorityFont.Attribute(W.asciiTheme) } :
- new[] { lowerPriorityFont.Attribute(W.ascii), lowerPriorityFont.Attribute(W.asciiTheme) },
- (higherPriorityFont.Attribute(W.hAnsi) != null || higherPriorityFont.Attribute(W.hAnsiTheme) != null) ?
- new[] { higherPriorityFont.Attribute(W.hAnsi), higherPriorityFont.Attribute(W.hAnsiTheme) } :
- new[] { lowerPriorityFont.Attribute(W.hAnsi), lowerPriorityFont.Attribute(W.hAnsiTheme) },
- (higherPriorityFont.Attribute(W.eastAsia) != null || higherPriorityFont.Attribute(W.eastAsiaTheme) != null) ?
- new[] { higherPriorityFont.Attribute(W.eastAsia), higherPriorityFont.Attribute(W.eastAsiaTheme) } :
- new[] { lowerPriorityFont.Attribute(W.eastAsia), lowerPriorityFont.Attribute(W.eastAsiaTheme) },
- (higherPriorityFont.Attribute(W.cs) != null || higherPriorityFont.Attribute(W.cstheme) != null) ?
- new[] { higherPriorityFont.Attribute(W.cs), higherPriorityFont.Attribute(W.cstheme) } :
- new[] { lowerPriorityFont.Attribute(W.cs), lowerPriorityFont.Attribute(W.cstheme) },
- (higherPriorityFont.Attribute(W.hint) != null ? higherPriorityFont.Attribute(W.hint) :
- lowerPriorityFont.Attribute(W.hint))
- );
- return rFonts;
- }
- private static int? CalcWidthOfRunInPixels(XElement r)
- {
- var fontName = (string)r.Attribute(PtOpenXml.FontName) ??
- (string)r.Ancestors(W.p).First().Attribute(PtOpenXml.FontName);
- if (fontName == null)
- throw new OpenXmlPowerToolsException("Internal Error, should have FontName attribute");
- if (UnknownFonts.Contains(fontName))
- return 0;
- if (UnknownFonts.Contains(fontName))
- return null;
- var rPr = r.Element(W.rPr);
- if (rPr == null)
- return null;
- var sz = GetFontSize(r) ?? 22m;
- // unknown font families will throw ArgumentException, in which case just return 0
- if (!KnownFamilies.Contains(fontName))
- return 0;
- // in theory, all unknown fonts are found by the above test, but if not...
- FontFamily ff;
- try
- {
- ff = new FontFamily(fontName);
- }
- catch (ArgumentException)
- {
- UnknownFonts.Add(fontName);
- return 0;
- }
- var fs = FontStyle.Regular;
- if (Util.GetBoolProp(rPr, W.b) == true || Util.GetBoolProp(rPr, W.bCs) == true)
- fs |= FontStyle.Bold;
- if (Util.GetBoolProp(rPr, W.i) == true || Util.GetBoolProp(rPr, W.iCs) == true)
- fs |= FontStyle.Italic;
- // Appended blank as a quick fix to accommodate that will get
- // appended to some layout-critical runs such as list item numbers.
- // In some cases, this might not be required or even wrong, so this
- // must be revisited.
- // TODO: Revisit.
- var runText = r.DescendantsTrimmed(W.txbxContent)
- .Where(e => e.Name == W.t)
- .Select(t => (string)t)
- .StringConcatenate() + " ";
- var tabLength = r.DescendantsTrimmed(W.txbxContent)
- .Where(e => e.Name == W.tab)
- .Select(t => (decimal)t.Attribute(PtOpenXml.TabWidth))
- .Sum();
- if (runText.Length == 0 && tabLength == 0)
- return 0;
- int multiplier = 1;
- if (runText.Length <= 2)
- multiplier = 100;
- else if (runText.Length <= 4)
- multiplier = 50;
- else if (runText.Length <= 8)
- multiplier = 25;
- else if (runText.Length <= 16)
- multiplier = 12;
- else if (runText.Length <= 32)
- multiplier = 6;
- if (multiplier != 1)
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < multiplier; i++)
- sb.Append(runText);
- runText = sb.ToString();
- }
- return MetricsGetter.GetTextWidth(ff, fs, sz, runText) / multiplier;
- }
- // The algorithm for this method comes from the implementer notes in [MS-OI29500].pdf
- // section 2.1.87
- // The implementer notes are at:
- // http://msdn.microsoft.com/en-us/library/ee908652.aspx
- public enum FontType
- {
- Ascii,
- HAnsi,
- EastAsia,
- CS
- };
- public class CharStyleAttributes
- {
- public string AsciiFont;
- public string HAnsiFont;
- public string EastAsiaFont;
- public string CsFont;
- public string Hint;
- public bool Rtl;
- public string LatinLang;
- public string BidiLang;
- public string EastAsiaLang;
- public Dictionary<XName, bool?> ToggleProperties;
- public Dictionary<XName, XElement> Properties;
- public CharStyleAttributes(XElement pPr, XElement rPr)
- {
- ToggleProperties = new Dictionary<XName, bool?>();
- Properties = new Dictionary<XName, XElement>();
- if (rPr == null)
- return;
- foreach (XName xn in TogglePropertyNames)
- {
- ToggleProperties[xn] = Util.GetBoolProp(rPr, xn);
- }
- foreach (XName xn in PropertyNames)
- {
- Properties[xn] = GetXmlProperty(rPr, xn);
- }
- var rFonts = rPr.Element(W.rFonts);
- if (rFonts == null)
- {
- this.AsciiFont = null;
- this.HAnsiFont = null;
- this.EastAsiaFont = null;
- this.CsFont = null;
- this.Hint = null;
- }
- else
- {
- this.AsciiFont = (string)(rFonts.Attribute(W.ascii));
- this.HAnsiFont = (string)(rFonts.Attribute(W.hAnsi));
- this.EastAsiaFont = (string)(rFonts.Attribute(W.eastAsia));
- this.CsFont = (string)(rFonts.Attribute(W.cs));
- this.Hint = (string)(rFonts.Attribute(W.hint));
- }
- XElement csel = this.Properties[W.cs];
- bool cs = csel != null && (csel.Attribute(W.val) == null || csel.Attribute(W.val).ToBoolean() == true);
- XElement rtlel = this.Properties[W.rtl];
- bool rtl = rtlel != null && (rtlel.Attribute(W.val) == null || rtlel.Attribute(W.val).ToBoolean() == true);
- var bidi = false;
- if (pPr != null)
- {
- XElement bidiel = pPr.Element(W.bidi);
- bidi = bidiel != null && (bidiel.Attribute(W.val) == null || bidiel.Attribute(W.val).ToBoolean() == true);
- }
- Rtl = cs || rtl || bidi;
- var lang = rPr.Element(W.lang);
- if (lang != null)
- {
- LatinLang = (string)lang.Attribute(W.val);
- BidiLang = (string)lang.Attribute(W.bidi);
- EastAsiaLang = (string)lang.Attribute(W.eastAsia);
- }
- }
- private static XElement GetXmlProperty(XElement rPr, XName propertyName)
- {
- return rPr.Element(propertyName);
- }
- private static XName[] TogglePropertyNames = new[] {
- W.b,
- W.bCs,
- W.caps,
- W.emboss,
- W.i,
- W.iCs,
- W.imprint,
- W.outline,
- W.shadow,
- W.smallCaps,
- W.strike,
- W.vanish
- };
- private static XName[] PropertyNames = new[] {
- W.cs,
- W.rtl,
- W.u,
- W.color,
- W.highlight,
- W.shd
- };
- }
- public static FontType DetermineFontTypeFromCharacter(char ch, CharStyleAttributes csa)
- {
- // If the run has the cs element ("[ISO/IEC-29500-1] §17.3.2.7; cs") or the rtl element ("[ISO/IEC-29500-1] §17.3.2.30; rtl"),
- // then the cs (or cstheme if defined) font is used, regardless of the Unicode character values of the run’s content.
- if (csa.Rtl)
- {
- return FontType.CS;
- }
- // A large percentage of characters will fall in the following rule.
- // Unicode Block: Basic Latin
- if (ch >= 0x00 && ch <= 0x7f)
- {
- return FontType.Ascii;
- }
- // If the eastAsia (or eastAsiaTheme if defined) attribute’s value is “Times New Roman” and the ascii (or asciiTheme if defined)
- // and hAnsi (or hAnsiTheme if defined) attributes are equal, then the ascii (or asciiTheme if defined) font is used.
- if (csa.EastAsiaFont == "Times New Roman" &&
- csa.AsciiFont == csa.HAnsiFont)
- {
- return FontType.Ascii;
- }
- // Unicode BLock: Latin-1 Supplement
- if (ch >= 0xA0 && ch <= 0xFF)
- {
- if (csa.Hint == "eastAsia")
- {
- if (ch == 0xA1 ||
- ch == 0xA4 ||
- ch == 0xA7 ||
- ch == 0xA8 ||
- ch == 0xAA ||
- ch == 0xAD ||
- ch == 0xAF ||
- (ch >= 0xB0 && ch <= 0xB4) ||
- (ch >= 0xB6 && ch <= 0xBA) ||
- (ch >= 0xBC && ch <= 0xBF) ||
- ch == 0xD7 ||
- ch == 0xF7)
- {
- return FontType.EastAsia;
- }
- if (csa.EastAsiaLang == "zh-hant" ||
- csa.EastAsiaLang == "zh-hans")
- {
- if (ch == 0xE0 ||
- ch == 0xE1 ||
- (ch >= 0xE8 && ch <= 0xEA) ||
- (ch >= 0xEC && ch <= 0xED) ||
- (ch >= 0xF2 && ch <= 0xF3) ||
- (ch >= 0xF9 && ch <= 0xFA) ||
- ch == 0xFC)
- {
- return FontType.EastAsia;
- }
- }
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Latin Extended-A
- if (ch >= 0x0100 && ch <= 0x017F)
- {
- if (csa.Hint == "eastAsia")
- {
- if (csa.EastAsiaLang == "zh-hant" ||
- csa.EastAsiaLang == "zh-hans"
- /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */)
- {
- return FontType.EastAsia;
- }
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Latin Extended-B
- if (ch >= 0x0180 && ch <= 0x024F)
- {
- if (csa.Hint == "eastAsia")
- {
- if (csa.EastAsiaLang == "zh-hant" ||
- csa.EastAsiaLang == "zh-hans"
- /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */)
- {
- return FontType.EastAsia;
- }
- }
- return FontType.HAnsi;
- }
- // Unicode Block: IPA Extensions
- if (ch >= 0x0250 && ch <= 0x02AF)
- {
- if (csa.Hint == "eastAsia")
- {
- if (csa.EastAsiaLang == "zh-hant" ||
- csa.EastAsiaLang == "zh-hans"
- /* || the character set of the east Asia (or east Asia theme) font is Chinese5 || GB2312 todo */)
- {
- return FontType.EastAsia;
- }
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Spacing Modifier Letters
- if (ch >= 0x02B0 && ch <= 0x02FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Combining Diacritic Marks
- if (ch >= 0x0300 && ch <= 0x036F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Greek
- if (ch >= 0x0370 && ch <= 0x03CF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Cyrillic
- if (ch >= 0x0400 && ch <= 0x04FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Hebrew
- if (ch >= 0x0590 && ch <= 0x05FF)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Arabic
- if (ch >= 0x0600 && ch <= 0x06FF)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Syriac
- if (ch >= 0x0700 && ch <= 0x074F)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Arabic Supplement
- if (ch >= 0x0750 && ch <= 0x077F)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Thanna
- if (ch >= 0x0780 && ch <= 0x07BF)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Hangul Jamo
- if (ch >= 0x1100 && ch <= 0x11FF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Latin Extended Additional
- if (ch >= 0x1E00 && ch <= 0x1EFF)
- {
- if (csa.Hint == "eastAsia" &&
- (csa.EastAsiaLang == "zh-hant" ||
- csa.EastAsiaLang == "zh-hans"))
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: General Punctuation
- if (ch >= 0x2000 && ch <= 0x206F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Superscripts and Subscripts
- if (ch >= 0x2070 && ch <= 0x209F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Currency Symbols
- if (ch >= 0x20A0 && ch <= 0x20CF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Combining Diacritical Marks for Symbols
- if (ch >= 0x20D0 && ch <= 0x20FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Letter-like Symbols
- if (ch >= 0x2100 && ch <= 0x214F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Number Forms
- if (ch >= 0x2150 && ch <= 0x218F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Arrows
- if (ch >= 0x2190 && ch <= 0x21FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Mathematical Operators
- if (ch >= 0x2200 && ch <= 0x22FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Miscellaneous Technical
- if (ch >= 0x2300 && ch <= 0x23FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Control Pictures
- if (ch >= 0x2400 && ch <= 0x243F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Optical Character Recognition
- if (ch >= 0x2440 && ch <= 0x245F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Enclosed Alphanumerics
- if (ch >= 0x2460 && ch <= 0x24FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Box Drawing
- if (ch >= 0x2500 && ch <= 0x257F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Block Elements
- if (ch >= 0x2580 && ch <= 0x259F)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Geometric Shapes
- if (ch >= 0x25A0 && ch <= 0x25FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Miscellaneous Symbols
- if (ch >= 0x2600 && ch <= 0x26FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Dingbats
- if (ch >= 0x2700 && ch <= 0x27BF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: CJK Radicals Supplement
- if (ch >= 0x2E80 && ch <= 0x2EFF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Kangxi Radicals
- if (ch >= 0x2F00 && ch <= 0x2FDF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Ideographic Description Characters
- if (ch >= 0x2FF0 && ch <= 0x2FFF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: CJK Symbols and Punctuation
- if (ch >= 0x3000 && ch <= 0x303F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Hiragana
- if (ch >= 0x3040 && ch <= 0x309F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Katakana
- if (ch >= 0x30A0 && ch <= 0x30FF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Bopomofo
- if (ch >= 0x3100 && ch <= 0x312F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Hangul Compatibility Jamo
- if (ch >= 0x3130 && ch <= 0x318F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Kanbun
- if (ch >= 0x3190 && ch <= 0x319F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Enclosed CJK Letters and Months
- if (ch >= 0x3200 && ch <= 0x32FF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: CJK Compatibility
- if (ch >= 0x3300 && ch <= 0x33FF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: CJK Unified Ideographs Extension A
- if (ch >= 0x3400 && ch <= 0x4DBF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: CJK Unified Ideographs
- if (ch >= 0x4E00 && ch <= 0x9FAF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Yi Syllables
- if (ch >= 0xA000 && ch <= 0xA48F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Yi Radicals
- if (ch >= 0xA490 && ch <= 0xA4CF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Hangul Syllables
- if (ch >= 0xAC00 && ch <= 0xD7AF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: High Surrogates
- if (ch >= 0xD800 && ch <= 0xDB7F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: High Private Use Surrogates
- if (ch >= 0xDB80 && ch <= 0xDBFF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Low Surrogates
- if (ch >= 0xDC00 && ch <= 0xDFFF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Private Use Area
- if (ch >= 0xE000 && ch <= 0xF8FF)
- {
- if (csa.Hint == "eastAsia")
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: CJK Compatibility Ideographs
- if (ch >= 0xF900 && ch <= 0xFAFF)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Alphabetic Presentation Forms
- if (ch >= 0xFB00 && ch <= 0xFB4F)
- {
- if (csa.Hint == "eastAsia")
- {
- if (ch >= 0xFB00 && ch <= 0xFB1C)
- return FontType.EastAsia;
- if (ch >= 0xFB1D && ch <= 0xFB4F)
- return FontType.Ascii;
- }
- return FontType.HAnsi;
- }
- // Unicode Block: Arabic Presentation Forms-A
- if (ch >= 0xFB50 && ch <= 0xFDFF)
- {
- return FontType.Ascii;
- }
- // Unicode Block: CJK Compatibility Forms
- if (ch >= 0xFE30 && ch <= 0xFE4F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Small Form Variants
- if (ch >= 0xFE50 && ch <= 0xFE6F)
- {
- return FontType.EastAsia;
- }
- // Unicode Block: Arabic Presentation Forms-B
- if (ch >= 0xFE70 && ch <= 0xFEFE)
- {
- return FontType.Ascii;
- }
- // Unicode Block: Halfwidth and Fullwidth Forms
- if (ch >= 0xFF00 && ch <= 0xFFEF)
- {
- return FontType.EastAsia;
- }
- return FontType.HAnsi;
- }
- private static readonly HashSet<string> UnknownFonts = new HashSet<string>();
- private static HashSet<string> _knownFamilies;
- private static HashSet<string> KnownFamilies
- {
- get
- {
- if (_knownFamilies == null)
- {
- _knownFamilies = new HashSet<string>();
- var families = FontFamily.Families;
- foreach (var fam in families)
- _knownFamilies.Add(fam.Name);
- }
- return _knownFamilies;
- }
- }
- private static HashSet<char> WeakAndNeutralDirectionalCharacters = new HashSet<char>() {
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- '+',
- '-',
- ':',
- ',',
- '.',
- '|',
- '\t',
- '\r',
- '\n',
- ' ',
- '\x00A0', // non breaking space
- '\x00B0', // degree sign
- '\x066B', // arabic decimal separator
- '\x066C', // arabic thousands separator
- '\x0627', // arabic pipe
- '\x20A0', // start currency symbols
- '\x20A1',
- '\x20A2',
- '\x20A3',
- '\x20A4',
- '\x20A5',
- '\x20A6',
- '\x20A7',
- '\x20A8',
- '\x20A9',
- '\x20AA',
- '\x20AB',
- '\x20AC',
- '\x20AD',
- '\x20AE',
- '\x20AF',
- '\x20B0',
- '\x20B1',
- '\x20B2',
- '\x20B3',
- '\x20B4',
- '\x20B5',
- '\x20B6',
- '\x20B7',
- '\x20B8',
- '\x20B9',
- '\x20BA',
- '\x20BB',
- '\x20BC',
- '\x20BD',
- '\x20BE',
- '\x20BF',
- '\x20C0',
- '\x20C1',
- '\x20C2',
- '\x20C3',
- '\x20C4',
- '\x20C5',
- '\x20C6',
- '\x20C7',
- '\x20C8',
- '\x20C9',
- '\x20CA',
- '\x20CB',
- '\x20CC',
- '\x20CD',
- '\x20CE',
- '\x20CF', // end currency symbols
- '\x0660', // "Arabic" Indic Numeral Forms Iraq and West
- '\x0661',
- '\x0662',
- '\x0663',
- '\x0664',
- '\x0665',
- '\x0666',
- '\x0667',
- '\x0668',
- '\x0669',
- '\x06F0', // "Arabic" Indic Numberal Forms Iran and East
- '\x06F1',
- '\x06F2',
- '\x06F3',
- '\x06F4',
- '\x06F5',
- '\x06F6',
- '\x06F7',
- '\x06F8',
- '\x06F9',
- };
- private static void AdjustFontAttributes(WordprocessingDocument wDoc, XElement paraOrRun, XElement pPr, XElement rPr)
- {
- XDocument themeXDoc = null;
- if (wDoc.MainDocumentPart.ThemePart != null)
- themeXDoc = wDoc.MainDocumentPart.ThemePart.GetXDocument();
- XElement fontScheme = null;
- XElement majorFont = null;
- XElement minorFont = null;
- if (themeXDoc != null)
- {
- fontScheme = themeXDoc.Root.Element(A.themeElements).Element(A.fontScheme);
- majorFont = fontScheme.Element(A.majorFont);
- minorFont = fontScheme.Element(A.minorFont);
- }
- var rFonts = rPr.Element(W.rFonts);
- if (rFonts == null)
- {
- return;
- }
- var asciiTheme = (string)rFonts.Attribute(W.asciiTheme);
- var hAnsiTheme = (string)rFonts.Attribute(W.hAnsiTheme);
- var eastAsiaTheme = (string)rFonts.Attribute(W.eastAsiaTheme);
- var cstheme = (string)rFonts.Attribute(W.cstheme);
- string ascii = null;
- string hAnsi = null;
- string eastAsia = null;
- string cs = null;
- XElement minorLatin = null;
- string minorLatinTypeface = null;
- XElement majorLatin = null;
- string majorLatinTypeface = null;
- if (minorFont != null)
- {
- minorLatin = minorFont.Element(A.latin);
- minorLatinTypeface = (string)minorLatin.Attribute("typeface");
- }
- if (majorFont != null)
- {
- majorLatin = majorFont.Element(A.latin);
- majorLatinTypeface = (string)majorLatin.Attribute("typeface");
- }
- if (asciiTheme != null)
- {
- if (asciiTheme.StartsWith("minor") && minorLatinTypeface != null)
- {
- ascii = minorLatinTypeface;
- }
- else if (asciiTheme.StartsWith("major") && majorLatinTypeface != null)
- {
- ascii = majorLatinTypeface;
- }
- }
- if (hAnsiTheme != null)
- {
- if (hAnsiTheme.StartsWith("minor") && minorLatinTypeface != null)
- {
- hAnsi = minorLatinTypeface;
- }
- else if (hAnsiTheme.StartsWith("major") && majorLatinTypeface != null)
- {
- hAnsi = majorLatinTypeface;
- }
- }
- if (eastAsiaTheme != null)
- {
- if (eastAsiaTheme.StartsWith("minor") && minorLatinTypeface != null)
- {
- eastAsia = minorLatinTypeface;
- }
- else if (eastAsiaTheme.StartsWith("major") && majorLatinTypeface != null)
- {
- eastAsia = majorLatinTypeface;
- }
- }
- if (cstheme != null)
- {
- if (cstheme.StartsWith("minor") && minorFont != null)
- {
- cs = (string)minorFont.Element(A.cs).Attribute("typeface");
- }
- else if (cstheme.StartsWith("major") && majorFont != null)
- {
- cs = (string)majorFont.Element(A.cs).Attribute("typeface");
- }
- }
- if (ascii != null)
- {
- rFonts.SetAttributeValue(W.ascii, ascii);
- }
- if (hAnsi != null)
- {
- rFonts.SetAttributeValue(W.hAnsi, hAnsi);
- }
- if (eastAsia != null)
- {
- rFonts.SetAttributeValue(W.eastAsia, eastAsia);
- }
- if (cs != null)
- {
- rFonts.SetAttributeValue(W.cs, cs);
- }
- var firstTextNode = paraOrRun.Descendants(W.t).FirstOrDefault(t => t.Value.Length > 0);
- string str = " ";
- // if there is a run with no text in it, then no need to do any of the rest of this method.
- if (firstTextNode == null && paraOrRun.Name == W.r)
- return;
- if (firstTextNode != null)
- str = firstTextNode.Value;
- var csa = new CharStyleAttributes(pPr, rPr);
- // This module determines the font based on just the first character.
- // Technically, a run can contain characters from different Unicode code blocks, and hence should be rendered with different fonts.
- // However, Word breaks up runs that use more than one font into multiple runs. Other producers of WordprocessingML may not, so in
- // that case, this routine may need to be augmented to look at all characters in a run.
- /*
- old code
- var fontFamilies = str.select(function (c) {
- var ft = Pav.DetermineFontTypeFromCharacter(c, csa);
- switch (ft) {
- case Pav.FontType.Ascii:
- return cast(rFonts.attribute(W.ascii));
- case Pav.FontType.HAnsi:
- return cast(rFonts.attribute(W.hAnsi));
- case Pav.FontType.EastAsia:
- return cast(rFonts.attribute(W.eastAsia));
- case Pav.FontType.CS:
- return cast(rFonts.attribute(W.cs));
- default:
- return null;
- }
- })
- .where(function (f) { return f != null && f != ""; })
- .distinct()
- .select(function (f) { return new Pav.FontFamily(f); })
- .toArray();
- */
- var charToExamine = str.FirstOrDefault(c => !WeakAndNeutralDirectionalCharacters.Contains(c));
- if (charToExamine == '\0')
- charToExamine = str[0];
- var ft = DetermineFontTypeFromCharacter(charToExamine, csa);
- string fontType = null;
- string languageType = null;
- switch (ft)
- {
- case FontType.Ascii:
- fontType = (string)rFonts.Attribute(W.ascii);
- languageType = "western";
- break;
- case FontType.HAnsi:
- fontType = (string)rFonts.Attribute(W.hAnsi);
- languageType = "western";
- break;
- case FontType.EastAsia:
- fontType = (string)rFonts.Attribute(W.eastAsia);
- languageType = "eastAsia";
- break;
- case FontType.CS:
- fontType = (string)rFonts.Attribute(W.cs);
- languageType = "bidi";
- break;
- }
- if (fontType != null)
- {
- if (paraOrRun.Attribute(PtOpenXml.FontName) == null)
- {
- XAttribute fta = new XAttribute(PtOpenXml.FontName, fontType.ToString());
- paraOrRun.Add(fta);
- }
- else
- {
- paraOrRun.Attribute(PtOpenXml.FontName).Value = fontType.ToString();
- }
- }
- if (languageType != null)
- {
- if (paraOrRun.Attribute(PtOpenXml.LanguageType) == null)
- {
- XAttribute lta = new XAttribute(PtOpenXml.LanguageType, languageType);
- paraOrRun.Add(lta);
- }
- else
- {
- paraOrRun.Attribute(PtOpenXml.LanguageType).Value = languageType;
- }
- }
- }
- private static decimal? GetFontSize(XElement e)
- {
- var languageType = (string)e.Attribute(PtOpenXml.LanguageType);
- if (e.Name == W.p)
- {
- return GetFontSize(languageType, e.Elements(W.pPr).Elements(W.rPr).FirstOrDefault());
- }
- if (e.Name == W.r)
- {
- return GetFontSize(languageType, e.Element(W.rPr));
- }
- return null;
- }
- private static decimal? GetFontSize(string languageType, XElement rPr)
- {
- if (rPr == null) return null;
- return languageType == "bidi"
- ? (decimal?)rPr.Elements(W.szCs).Attributes(W.val).FirstOrDefault()
- : (decimal?)rPr.Elements(W.sz).Attributes(W.val).FirstOrDefault();
- }
- private static int NextRectId = 1025;
- private static int GetNextRectId()
- {
- return NextRectId++;
- }
- private static object GenerateNextExpected(XNode node, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc,
- string styleName, NextExpected nextExpected, bool preserveWhiteSpace)
- {
- if (nextExpected == NextExpected.Paragraph)
- {
- XElement element = node as XElement;
- if (element != null)
- {
- return new XElement(W.p,
- GetParagraphProperties(element, styleName, settings),
- element.Nodes().Select(n => Transform(n, settings, wDoc, NextExpected.Run, preserveWhiteSpace)));
- }
- else
- {
- XText xTextNode = node as XText;
- if (xTextNode != null)
- {
- string textNodeString = GetDisplayText(xTextNode, preserveWhiteSpace);
- XElement p;
- p = new XElement(W.p,
- GetParagraphProperties(node.Parent, null, settings),
- new XElement(W.r,
- GetRunProperties((XText)node, settings),
- new XElement(W.t,
- GetXmlSpaceAttribute(textNodeString),
- textNodeString)));
- return p;
- }
- return null;
- }
- }
- else
- {
- XElement element = node as XElement;
- if (element != null)
- {
- return element.Nodes().Select(n => Transform(n, settings, wDoc, nextExpected, preserveWhiteSpace));
- }
- else
- {
- string textNodeString = GetDisplayText((XText)node, preserveWhiteSpace);
- XElement rPr = GetRunProperties((XText)node, settings);
- XElement r = new XElement(W.r,
- rPr,
- new XElement(W.t,
- GetXmlSpaceAttribute(textNodeString),
- textNodeString));
- return r;
- }
- }
- }
- private static XElement TransformImageToWml(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc)
- {
- string srcAttribute = (string)element.Attribute(XhtmlNoNamespace.src);
- byte[] ba = null;
- Bitmap bmp = null;
- if (srcAttribute.StartsWith("data:"))
- {
- var semiIndex = srcAttribute.IndexOf(';');
- var commaIndex = srcAttribute.IndexOf(',', semiIndex);
- var base64 = srcAttribute.Substring(commaIndex + 1);
- ba = Convert.FromBase64String(base64);
- using (MemoryStream ms = new MemoryStream(ba))
- {
- bmp = new Bitmap(ms);
- }
- }
- else
- {
- try
- {
- bmp = new Bitmap(settings.BaseUriForImages + "/" + srcAttribute);
- }
- catch (ArgumentException)
- {
- return null;
- }
- catch (NotSupportedException)
- {
- return null;
- }
- MemoryStream ms = new MemoryStream();
- bmp.Save(ms, bmp.RawFormat);
- ba = ms.ToArray();
- }
- MainDocumentPart mdp = wDoc.MainDocumentPart;
- string rId = "R" + Guid.NewGuid().ToString().Replace("-", "");
- ImagePartType ipt = ImagePartType.Png;
- ImagePart newPart = mdp.AddImagePart(ipt, rId);
- using (Stream s = newPart.GetStream(FileMode.Create, FileAccess.ReadWrite))
- s.Write(ba, 0, ba.GetUpperBound(0) + 1);
- PictureId pid = wDoc.Annotation<PictureId>();
- if (pid == null)
- {
- pid = new PictureId
- {
- Id = 1,
- };
- wDoc.AddAnnotation(pid);
- }
- int pictureId = pid.Id;
- ++pid.Id;
- string pictureDescription = "Picture " + pictureId.ToString();
- string floatValue = element.GetProp("float").ToString();
- if (floatValue == "none")
- {
- XElement run = new XElement(W.r,
- GetRunPropertiesForImage(),
- new XElement(W.drawing,
- GetImageAsInline(element, settings, wDoc, bmp, rId, pictureId, pictureDescription)));
- return run;
- }
- if (floatValue == "left" || floatValue == "right")
- {
- XElement run = new XElement(W.r,
- GetRunPropertiesForImage(),
- new XElement(W.drawing,
- GetImageAsAnchor(element, settings, wDoc, bmp, rId, floatValue, pictureId, pictureDescription)));
- return run;
- }
- return null;
- }
- private static XElement GetImageAsInline(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, Bitmap bmp,
- string rId, int pictureId, string pictureDescription)
- {
- XElement inline = new XElement(WP.inline, // 20.4.2.8
- new XAttribute(XNamespace.Xmlns + "wp", WP.wp.NamespaceName),
- new XAttribute(NoNamespace.distT, 0), // distance from top of image to text, in EMUs, no effect if the parent is inline
- new XAttribute(NoNamespace.distB, 0), // bottom
- new XAttribute(NoNamespace.distL, 0), // left
- new XAttribute(NoNamespace.distR, 0), // right
- GetImageExtent(element, bmp),
- GetEffectExtent(),
- GetDocPr(element, pictureId, pictureDescription),
- GetCNvGraphicFramePr(),
- GetGraphicForImage(element, rId, bmp, pictureId, pictureDescription));
- return inline;
- }
- private static XElement GetImageAsAnchor(XElement element, HtmlToWmlConverterSettings settings, WordprocessingDocument wDoc, Bitmap bmp,
- string rId, string floatValue, int pictureId, string pictureDescription)
- {
- Emu minDistFromEdge = (long)(0.125 * Emu.s_EmusPerInch);
- long relHeight = 251658240; // z-order
- CssExpression marginTopProp = element.GetProp("margin-top");
- CssExpression marginLeftProp = element.GetProp("margin-left");
- CssExpression marginBottomProp = element.GetProp("margin-bottom");
- CssExpression marginRightProp = element.GetProp("margin-right");
- Emu marginTopInEmus = 0;
- Emu marginBottomInEmus = 0;
- Emu marginLeftInEmus = 0;
- Emu marginRightInEmus = 0;
- if (marginTopProp.IsNotAuto)
- marginTopInEmus = (Emu)marginTopProp;
- if (marginBottomProp.IsNotAuto)
- marginBottomInEmus = (Emu)marginBottomProp;
- if (marginLeftProp.IsNotAuto)
- marginLeftInEmus = (Emu)marginLeftProp;
- if (marginRightProp.IsNotAuto)
- marginRightInEmus = (Emu)marginRightProp;
- Emu relativeFromColumn = 0;
- if (floatValue == "left")
- {
- relativeFromColumn = marginLeftInEmus;
- CssExpression parentMarginLeft = element.Parent.GetProp("margin-left");
- if (parentMarginLeft.IsNotAuto)
- relativeFromColumn += (long)(Emu)parentMarginLeft;
- marginRightInEmus = Math.Max(marginRightInEmus, minDistFromEdge);
- }
- else if (floatValue == "right")
- {
- Emu printWidth = (long)settings.PageWidthEmus - (long)settings.PageMarginLeftEmus - (long)settings.PageMarginRightEmus;
- SizeEmu sl = GetImageSizeInEmus(element, bmp);
- relativeFromColumn = printWidth - sl.m_Width;
- if (marginRightProp.IsNotAuto)
- relativeFromColumn -= (long)(Emu)marginRightInEmus;
- CssExpression parentMarginRight = element.Parent.GetProp("margin-right");
- if (parentMarginRight.IsNotAuto)
- relativeFromColumn -= (long)(Emu)parentMarginRight;
- marginLeftInEmus = Math.Max(marginLeftInEmus, minDistFromEdge);
- }
- Emu relativeFromParagraph = marginTopInEmus;
- CssExpression parentMarginTop = element.Parent.GetProp("margin-top");
- if (parentMarginTop.IsNotAuto)
- relativeFromParagraph += (long)(Emu)parentMarginTop;
- XElement anchor = new XElement(WP.anchor,
- new XAttribute(XNamespace.Xmlns + "wp", WP.wp.NamespaceName),
- new XAttribute(NoNamespace.distT, (long)marginTopInEmus), // distance from top of image to text, in EMUs, no effect if the parent is inline
- new XAttribute(NoNamespace.distB, (long)marginBottomInEmus), // bottom
- new XAttribute(NoNamespace.distL, (long)marginLeftInEmus), // left
- new XAttribute(NoNamespace.distR, (long)marginRightInEmus), // right
- new XAttribute(NoNamespace.simplePos, 0),
- new XAttribute(NoNamespace.relativeHeight, relHeight),
- new XAttribute(NoNamespace.behindDoc, 0),
- new XAttribute(NoNamespace.locked, 0),
- new XAttribute(NoNamespace.layoutInCell, 1),
- new XAttribute(NoNamespace.allowOverlap, 1),
- new XElement(WP.simplePos, new XAttribute(NoNamespace.x, 0), new XAttribute(NoNamespace.y, 0)),
- new XElement(WP.positionH, new XAttribute(NoNamespace.relativeFrom, "column"),
- new XElement(WP.posOffset, (long)relativeFromColumn)),
- new XElement(WP.positionV, new XAttribute(NoNamespace.relativeFrom, "paragraph"),
- new XElement(WP.posOffset, (long)relativeFromParagraph)),
- GetImageExtent(element, bmp),
- GetEffectExtent(),
- new XElement(WP.wrapSquare, new XAttribute(NoNamespace.wrapText, "bothSides")),
- GetDocPr(element, pictureId, pictureDescription),
- GetCNvGraphicFramePr(),
- GetGraphicForImage(element, rId, bmp, pictureId, pictureDescription),
- new XElement(WP14.sizeRelH, new XAttribute(NoNamespace.relativeFrom, "page"),
- new XElement(WP14.pctWidth, 0)),
- new XElement(WP14.sizeRelV, new XAttribute(NoNamespace.relativeFrom, "page"),
- new XElement(WP14.pctHeight, 0))
- );
- return anchor;
- }
- #if false
- <wp:anchor distT="0"
- distB="0"
- distL="114300"
- distR="114300"
- simplePos="0"
- relativeHeight="251658240"
- behindDoc="0"
- locked="0"
- layoutInCell="1"
- allowOverlap="1">
- <wp:simplePos x="0"
- y="0"/>
- <wp:positionH relativeFrom="column">
- <wp:posOffset>0</wp:posOffset>
- </wp:positionH>
- <wp:positionV relativeFrom="paragraph">
- <wp:posOffset>0</wp:posOffset>
- </wp:positionV>
- <wp:extent cx="1713865"
- cy="1656715"/>
- <wp:effectExtent l="0"
- t="0"
- r="635"
- b="635"/>
- <wp:wrapSquare wrapText="bothSides"/>
- <wp:docPr id="1"
- name="Picture 1"
- descr="img.png"/>
- <wp:cNvGraphicFramePr>
- <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
- noChangeAspect="1"/>
- </wp:cNvGraphicFramePr>
- <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
- <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
- <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
- <pic:nvPicPr>
- <pic:cNvPr id="0"
- name="Picture 1"
- descr="img.png"/>
- <pic:cNvPicPr>
- <a:picLocks noChangeAspect="1"
- noChangeArrowheads="1"/>
- </pic:cNvPicPr>
- </pic:nvPicPr>
- <pic:blipFill>
- <a:blip r:embed="rId5">
- <a:extLst>
- <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
- <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"
- val="0"/>
- </a:ext>
- </a:extLst>
- </a:blip>
- <a:stretch>
- <a:fillRect/>
- </a:stretch>
- </pic:blipFill>
- <pic:spPr bwMode="auto">
- <a:xfrm>
- <a:off x="0"
- y="0"/>
- <a:ext cx="1713865"
- cy="1656715"/>
- </a:xfrm>
- <a:prstGeom prst="rect">
- <a:avLst/>
- </a:prstGeom>
- <a:noFill/>
- <a:ln>
- <a:noFill/>
- </a:ln>
- </pic:spPr>
- </pic:pic>
- </a:graphicData>
- </a:graphic>
- <wp14:sizeRelH relativeFrom="page">
- <wp14:pctWidth>0</wp14:pctWidth>
- </wp14:sizeRelH>
- <wp14:sizeRelV relativeFrom="page">
- <wp14:pctHeight>0</wp14:pctHeight>
- </wp14:sizeRelV>
- </wp:anchor>
- #endif
- private static XElement GetParagraphPropertiesForImage()
- {
- return null;
- }
- private static XElement GetRunPropertiesForImage()
- {
- return new XElement(W.rPr,
- new XElement(W.noProof));
- }
- private static SizeEmu GetImageSizeInEmus(XElement img, Bitmap bmp)
- {
- double hres = bmp.HorizontalResolution;
- double vres = bmp.VerticalResolution;
- Size s = bmp.Size;
- Emu cx = (long)((double)(s.Width / hres) * (double)Emu.s_EmusPerInch);
- Emu cy = (long)((double)(s.Height / vres) * (double)Emu.s_EmusPerInch);
- CssExpression width = img.GetProp("width");
- CssExpression height = img.GetProp("height");
- if (width.IsNotAuto && height.IsAuto)
- {
- Emu widthInEmus = (Emu)width;
- double percentChange = (float)widthInEmus / (float)cx;
- cx = widthInEmus;
- cy = (long)(cy * percentChange);
- return new SizeEmu(cx, cy);
- }
- if (width.IsAuto && height.IsNotAuto)
- {
- Emu heightInEmus = (Emu)height;
- double percentChange = (float)heightInEmus / (float)cy;
- cy = heightInEmus;
- cx = (long)(cx * percentChange);
- return new SizeEmu(cx, cy);
- }
- if (width.IsNotAuto && height.IsNotAuto)
- {
- return new SizeEmu((Emu)width, (Emu)height);
- }
- return new SizeEmu(cx, cy);
- }
- private static XElement GetImageExtent(XElement img, Bitmap bmp)
- {
- SizeEmu szEmu = GetImageSizeInEmus(img, bmp);
- return new XElement(WP.extent,
- new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), // in EMUs
- new XAttribute(NoNamespace.cy, (long)szEmu.m_Height)); // in EMUs
- }
- private static XElement GetEffectExtent()
- {
- return new XElement(WP.effectExtent,
- new XAttribute(NoNamespace.l, 0),
- new XAttribute(NoNamespace.t, 0),
- new XAttribute(NoNamespace.r, 0),
- new XAttribute(NoNamespace.b, 0));
- }
- private static XElement GetDocPr(XElement element, int pictureId, string pictureDescription)
- {
- return new XElement(WP.docPr,
- new XAttribute(NoNamespace.id, pictureId),
- new XAttribute(NoNamespace.name, pictureDescription),
- new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src)));
- }
- private static XElement GetCNvGraphicFramePr()
- {
- return new XElement(WP.cNvGraphicFramePr,
- new XElement(A.graphicFrameLocks,
- new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName),
- new XAttribute(NoNamespace.noChangeAspect, 1)));
- }
- private static XElement GetGraphicForImage(XElement element, string rId, Bitmap bmp, int pictureId, string pictureDescription)
- {
- SizeEmu szEmu = GetImageSizeInEmus(element, bmp);
- XElement graphic = new XElement(A.graphic,
- new XAttribute(XNamespace.Xmlns + "a", A.a.NamespaceName),
- new XElement(A.graphicData,
- new XAttribute(NoNamespace.uri, Pic.pic.NamespaceName),
- new XElement(Pic._pic,
- new XAttribute(XNamespace.Xmlns + "pic", Pic.pic.NamespaceName),
- new XElement(Pic.nvPicPr,
- new XElement(Pic.cNvPr,
- new XAttribute(NoNamespace.id, pictureId),
- new XAttribute(NoNamespace.name, pictureDescription),
- new XAttribute(NoNamespace.descr, (string)element.Attribute(NoNamespace.src))),
- new XElement(Pic.cNvPicPr,
- new XElement(A.picLocks,
- new XAttribute(NoNamespace.noChangeAspect, 1),
- new XAttribute(NoNamespace.noChangeArrowheads, 1)))),
- new XElement(Pic.blipFill,
- new XElement(A.blip,
- new XAttribute(R.embed, rId),
- new XElement(A.extLst,
- new XElement(A.ext,
- new XAttribute(NoNamespace.uri, "{28A0092B-C50C-407E-A947-70E740481C1C}"),
- new XElement(A14.useLocalDpi,
- new XAttribute(NoNamespace.val, "0"))))),
- new XElement(A.stretch,
- new XElement(A.fillRect))),
- new XElement(Pic.spPr,
- new XAttribute(NoNamespace.bwMode, "auto"),
- new XElement(A.xfrm,
- new XElement(A.off, new XAttribute(NoNamespace.x, 0), new XAttribute(NoNamespace.y, 0)),
- new XElement(A.ext, new XAttribute(NoNamespace.cx, (long)szEmu.m_Width), new XAttribute(NoNamespace.cy, (long)szEmu.m_Height))),
- new XElement(A.prstGeom, new XAttribute(NoNamespace.prst, "rect"),
- new XElement(A.avLst)),
- new XElement(A.noFill),
- new XElement(A.ln,
- new XElement(A.noFill))))));
- return graphic;
- }
- #if false
- <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
- <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
- <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
- <pic:nvPicPr>
- <pic:cNvPr id="0" name="Picture 1" descr="img.png"/>
- <pic:cNvPicPr>
- <a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
- </pic:cNvPicPr>
- </pic:nvPicPr>
- <pic:blipFill>
- <a:blip r:link="rId5">
- <a:extLst>
- <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
- <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
- </a:ext>
- </a:extLst>
- </a:blip>
- <a:srcRect/>
- <a:stretch>
- <a:fillRect/>
- </a:stretch>
- </pic:blipFill>
- <pic:spPr bwMode="auto">
- <a:xfrm>
- <a:off x="0" y="0"/>
- <a:ext cx="1781175" cy="1781175"/>
- </a:xfrm>
- <a:prstGeom prst="rect">
- <a:avLst/>
- </a:prstGeom>
- <a:noFill/>
- <a:ln>
- <a:noFill/>
- </a:ln>
- </pic:spPr>
- </pic:pic>
- </a:graphicData>
- </a:graphic>
- #endif
- private static XElement GetParagraphProperties(XElement blockLevelElement, string styleName, HtmlToWmlConverterSettings settings)
- {
- XElement paragraphMarkRunProperties = GetRunProperties(blockLevelElement, settings);
- XElement backgroundProperty = GetBackgroundProperty(blockLevelElement);
- XElement[] spacingProperty = GetSpacingProperties(blockLevelElement, settings); // spacing, ind, contextualSpacing
- XElement jc = GetJustification(blockLevelElement, settings);
- XElement pStyle = styleName != null ? new XElement(W.pStyle, new XAttribute(W.val, styleName)) : null;
- XElement numPr = GetNumberingProperties(blockLevelElement, settings);
- XElement pBdr = GetBlockContentBorders(blockLevelElement, W.pBdr, true);
- XElement bidi = null;
- string direction = GetDirection(blockLevelElement);
- if (direction == "rtl")
- bidi = new XElement(W.bidi);
- XElement pPr = new XElement(W.pPr,
- pStyle,
- numPr,
- pBdr,
- backgroundProperty,
- bidi,
- spacingProperty,
- jc,
- paragraphMarkRunProperties
- );
- return pPr;
- }
- // vertical-align doesn't really work in the Word rendering - puts space above, but not below. There really are no
- // options in WordprocessingML to specify vertical alignment. I think that the only possible way that this could be
- // implemented would be to specifically calculate the space before and space after. I'm not completely sure that
- // this could be possible. I am pretty sure that this is not worth the effort.
- // Returns the spacing, ind, and contextualSpacing elements
- private static XElement[] GetSpacingProperties(XElement paragraph, HtmlToWmlConverterSettings settings)
- {
- CssExpression marginLeftProperty = paragraph.GetProp("margin-left");
- CssExpression marginRightProperty = paragraph.GetProp("margin-right");
- CssExpression marginTopProperty = paragraph.GetProp("margin-top");
- CssExpression marginBottomProperty = paragraph.GetProp("margin-bottom");
- CssExpression lineHeightProperty = paragraph.GetProp("line-height");
- CssExpression leftPaddingProperty = paragraph.GetProp("padding-left");
- CssExpression rightPaddingProperty = paragraph.GetProp("padding-right");
- /*****************************************************************************************/
- // leftIndent, rightIndent, firstLine
- Twip leftIndent = 0;
- Twip rightIndent = 0;
- Twip firstLine = 0;
- #if false
- // this code is here for some reason. What is it?
- double leftBorderSize = GetBorderSize(paragraph, "left"); // in 1/8 point
- double rightBorderSize = GetBorderSize(paragraph, "right"); // in 1/8 point
- leftIndent += (long)((leftBorderSize / 8d) * 20d);
- rightIndent += (long)((rightBorderSize / 8d) * 20d);
- #endif
- if (leftPaddingProperty != null)
- leftIndent += (Twip)leftPaddingProperty;
- if (rightPaddingProperty != null)
- rightIndent += (Twip)rightPaddingProperty;
- if (paragraph.Name == XhtmlNoNamespace.li)
- {
- leftIndent += 180;
- rightIndent += 180;
- }
- XElement listElement = null;
- NumberedItemAnnotation numberedItemAnnotation = null;
- listElement = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul);
- if (listElement != null)
- {
- numberedItemAnnotation = listElement.Annotation<NumberedItemAnnotation>();
- leftIndent += 600 * (numberedItemAnnotation.ilvl + 1);
- }
- int blockQuoteCount = paragraph.Ancestors(XhtmlNoNamespace.blockquote).Count();
- leftIndent += blockQuoteCount * 720;
- if (blockQuoteCount == 0)
- {
- if (marginLeftProperty != null && marginLeftProperty.IsNotAuto && marginLeftProperty.IsNotNormal)
- leftIndent += (Twip)marginLeftProperty;
- if (marginRightProperty != null && marginRightProperty.IsNotAuto && marginRightProperty.IsNotNormal)
- rightIndent += (Twip)marginRightProperty;
- }
- CssExpression textIndentProperty = paragraph.GetProp("text-indent");
- if (textIndentProperty != null)
- {
- Twip twips = (Twip)textIndentProperty;
- firstLine = twips;
- }
- XElement ind = null;
- if (leftIndent > 0 || rightIndent > 0 || firstLine != 0)
- {
- if (firstLine < 0)
- ind = new XElement(W.ind,
- leftIndent != 0 ? new XAttribute(W.left, (long)leftIndent) : null,
- rightIndent != 0 ? new XAttribute(W.right, (long)rightIndent) : null,
- firstLine != 0 ? new XAttribute(W.hanging, -(long)firstLine) : null);
- else
- ind = new XElement(W.ind,
- leftIndent != 0 ? new XAttribute(W.left, (long)leftIndent) : null,
- rightIndent != 0 ? new XAttribute(W.right, (long)rightIndent) : null,
- firstLine != 0 ? new XAttribute(W.firstLine, (long)firstLine) : null);
- }
- /*****************************************************************************************/
- // spacing
- long line = 240;
- string lineRule = "auto";
- string beforeAutospacing = null;
- string afterAutospacing = null;
- long? before = null;
- long? after = null;
- if (paragraph.Name == XhtmlNoNamespace.td || paragraph.Name == XhtmlNoNamespace.th || paragraph.Name == XhtmlNoNamespace.caption)
- {
- line = (long)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.line);
- lineRule = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.lineRule);
- before = (long?)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.before);
- beforeAutospacing = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.beforeAutospacing);
- after = (long?)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.after);
- afterAutospacing = (string)settings.DefaultSpacingElementForParagraphsInTables.Attribute(W.afterAutospacing);
- }
- // todo should check based on display property
- bool numItem = paragraph.Name == XhtmlNoNamespace.li;
- if (numItem && marginTopProperty.IsAuto)
- beforeAutospacing = "1";
- if (numItem && marginBottomProperty.IsAuto)
- afterAutospacing = "1";
- if (marginTopProperty != null && marginTopProperty.IsNotAuto)
- {
- before = (long)(Twip)marginTopProperty;
- beforeAutospacing = "0";
- }
- if (marginBottomProperty != null && marginBottomProperty.IsNotAuto)
- {
- after = (long)(Twip)marginBottomProperty;
- afterAutospacing = "0";
- }
- if (lineHeightProperty != null && lineHeightProperty.IsNotAuto && lineHeightProperty.IsNotNormal)
- {
- // line is in twips if lineRule == "atLeast"
- line = (long)(Twip)lineHeightProperty;
- lineRule = "atLeast";
- }
- XElement spacing = new XElement(W.spacing,
- before != null ? new XAttribute(W.before, before) : null,
- beforeAutospacing != null ? new XAttribute(W.beforeAutospacing, beforeAutospacing) : null,
- after != null ? new XAttribute(W.after, after) : null,
- afterAutospacing != null ? new XAttribute(W.afterAutospacing, afterAutospacing) : null,
- new XAttribute(W.line, line),
- new XAttribute(W.lineRule, lineRule));
- /*****************************************************************************************/
- // contextualSpacing
- XElement contextualSpacing = null;
- if (paragraph.Name == XhtmlNoNamespace.li)
- {
- NumberedItemAnnotation thisNumberedItemAnnotation = null;
- XElement listElement2 = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul);
- if (listElement2 != null)
- {
- thisNumberedItemAnnotation = listElement2.Annotation<NumberedItemAnnotation>();
- XElement next = paragraph.ElementsAfterSelf().FirstOrDefault();
- if (next != null && next.Name == XhtmlNoNamespace.li)
- {
- XElement nextListElement = next.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul);
- NumberedItemAnnotation nextNumberedItemAnnotation = nextListElement.Annotation<NumberedItemAnnotation>();
- if (nextNumberedItemAnnotation != null && thisNumberedItemAnnotation.numId == nextNumberedItemAnnotation.numId)
- contextualSpacing = new XElement(W.contextualSpacing);
- }
- }
- }
- return new XElement[] { spacing, ind, contextualSpacing };
- }
- private static XElement GetRunProperties(XText textNode, HtmlToWmlConverterSettings settings)
- {
- XElement parent = textNode.Parent;
- XElement rPr = GetRunProperties(parent, settings);
- return rPr;
- }
- private static XElement GetRunProperties(XElement element, HtmlToWmlConverterSettings settings)
- {
- CssExpression colorProperty = element.GetProp("color");
- CssExpression fontFamilyProperty = element.GetProp("font-family");
- CssExpression fontSizeProperty = element.GetProp("font-size");
- CssExpression textDecorationProperty = element.GetProp("text-decoration");
- CssExpression fontStyleProperty = element.GetProp("font-style");
- CssExpression fontWeightProperty = element.GetProp("font-weight");
- CssExpression backgroundColorProperty = element.GetProp("background-color");
- CssExpression letterSpacingProperty = element.GetProp("letter-spacing");
- CssExpression directionProp = element.GetProp("direction");
- string colorPropertyString = colorProperty.ToString();
- string fontFamilyString = GetUsedFontFromFontFamilyProperty(fontFamilyProperty);
- TPoint? fontSizeTPoint = GetUsedSizeFromFontSizeProperty(fontSizeProperty);
- string textDecorationString = textDecorationProperty.ToString();
- string fontStyleString = fontStyleProperty.ToString();
- string fontWeightString = fontWeightProperty.ToString().ToLower();
- string backgroundColorString = backgroundColorProperty.ToString().ToLower();
- string letterSpacingString = letterSpacingProperty.ToString().ToLower();
- string directionString = directionProp.ToString().ToLower();
- bool subAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.sub).Any();
- bool supAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.sup).Any();
- bool bAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.b).Any();
- bool iAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.i).Any();
- bool strongAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.strong).Any();
- bool emAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.em).Any();
- bool uAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.u).Any();
- bool sAncestor = element.AncestorsAndSelf(XhtmlNoNamespace.s).Any();
- XAttribute dirAttribute = element.Attribute(XhtmlNoNamespace.dir);
- string dirAttributeString = "";
- if (dirAttribute != null)
- dirAttributeString = dirAttribute.Value.ToLower();
- XElement shd = null;
- if (backgroundColorString != "transparent")
- shd = new XElement(W.shd, new XAttribute(W.val, "clear"),
- new XAttribute(W.color, "auto"),
- new XAttribute(W.fill, backgroundColorString));
- XElement subSuper = null;
- if (subAncestor)
- subSuper = new XElement(W.vertAlign, new XAttribute(W.val, "subscript"));
- else
- if (supAncestor)
- subSuper = new XElement(W.vertAlign, new XAttribute(W.val, "superscript"));
- XElement rFonts = null;
- if (fontFamilyString != null)
- {
- rFonts = new XElement(W.rFonts,
- fontFamilyString != settings.MinorLatinFont ? new XAttribute(W.ascii, fontFamilyString) : null,
- fontFamilyString != settings.MajorLatinFont ? new XAttribute(W.hAnsi, fontFamilyString) : null,
- new XAttribute(W.cs, fontFamilyString));
- }
- // todo I think this puts a color on every element.
- XElement color = colorPropertyString != null ?
- new XElement(W.color, new XAttribute(W.val, colorPropertyString)) : null;
- XElement sz = null;
- XElement szCs = null;
- if (fontSizeTPoint != null)
- {
- sz = new XElement(W.sz, new XAttribute(W.val, (int)((double)fontSizeTPoint * 2)));
- szCs = new XElement(W.szCs, new XAttribute(W.val, (int)((double)fontSizeTPoint * 2)));
- }
- XElement strike = null;
- if (textDecorationString == "line-through" || sAncestor)
- strike = new XElement(W.strike);
- XElement bold = null;
- XElement boldCs = null;
- if (bAncestor || strongAncestor || fontWeightString == "bold" || fontWeightString == "bolder" || fontWeightString == "600" || fontWeightString == "700" || fontWeightString == "800" || fontWeightString == "900")
- {
- bold = new XElement(W.b);
- boldCs = new XElement(W.bCs);
- }
- XElement italic = null;
- XElement italicCs = null;
- if (iAncestor || emAncestor || fontStyleString == "italic")
- {
- italic = new XElement(W.i);
- italicCs = new XElement(W.iCs);
- }
- XElement underline = null;
- if (uAncestor || textDecorationString == "underline")
- underline = new XElement(W.u, new XAttribute(W.val, "single"));
- XElement rStyle = null;
- if (element.Name == XhtmlNoNamespace.a)
- rStyle = new XElement(W.rStyle,
- new XAttribute(W.val, "Hyperlink"));
- XElement spacing = null;
- if (letterSpacingProperty.IsNotNormal)
- spacing = new XElement(W.spacing,
- new XAttribute(W.val, (long)(Twip)letterSpacingProperty));
- XElement rtl = null;
- if (dirAttributeString == "rtl" || directionString == "rtl")
- rtl = new XElement(W.rtl);
- XElement runProps = new XElement(W.rPr,
- rStyle,
- rFonts,
- bold,
- boldCs,
- italic,
- italicCs,
- strike,
- color,
- spacing,
- sz,
- szCs,
- underline,
- shd,
- subSuper,
- rtl);
- if (runProps.Elements().Any())
- return runProps;
- return null;
- }
- // todo can make this faster
- // todo this is not right - needs to be rationalized for all characters in an entire paragraph.
- // if there is text like <p>abc <em> def </em> ghi</p> then there needs to be just one space between abc and def, and between
- // def and ghi.
- private static string GetDisplayText(XText node, bool preserveWhiteSpace)
- {
- string textTransform = node.Parent.GetProp("text-transform").ToString();
- bool isFirst = node.Parent.Name == XhtmlNoNamespace.p && node == node.Parent.FirstNode;
- bool isLast = node.Parent.Name == XhtmlNoNamespace.p && node == node.Parent.LastNode;
- IEnumerable<IGrouping<bool, char>> groupedCharacters = null;
- if (preserveWhiteSpace)
- groupedCharacters = node.Value.GroupAdjacent(c => c == '\r' || c == '\n');
- else
- groupedCharacters = node.Value.GroupAdjacent(c => c == ' ' || c == '\r' || c == '\n');
- string newString = groupedCharacters.Select(g =>
- {
- if (g.Key == true)
- return " ";
- string x = g.Select(c => c.ToString()).StringConcatenate();
- return x;
- })
- .StringConcatenate();
- if (!preserveWhiteSpace)
- {
- if (isFirst)
- newString = newString.TrimStart();
- if (isLast)
- newString = newString.TrimEnd();
- }
- if (textTransform == "uppercase")
- newString = newString.ToUpper();
- else if (textTransform == "lowercase")
- newString = newString.ToLower();
- else if (textTransform == "capitalize")
- newString = newString.Substring(0, 1).ToUpper() + newString.Substring(1).ToLower();
- return newString;
- }
- private static XElement GetNumberingProperties(XElement paragraph, HtmlToWmlConverterSettings settings)
- {
- // Numbering properties ******************************************************
- NumberedItemAnnotation numberedItemAnnotation = null;
- XElement listElement = paragraph.Ancestors().FirstOrDefault(a => a.Name == XhtmlNoNamespace.ol || a.Name == XhtmlNoNamespace.ul);
- if (listElement != null)
- {
- numberedItemAnnotation = listElement.Annotation<NumberedItemAnnotation>();
- }
- XElement numPr = null;
- if (paragraph.Name == XhtmlNoNamespace.li)
- numPr = new XElement(W.numPr,
- new XElement(W.ilvl, new XAttribute(W.val, numberedItemAnnotation.ilvl)),
- new XElement(W.numId, new XAttribute(W.val, numberedItemAnnotation.numId)));
- return numPr;
- }
- private static XElement GetJustification(XElement blockLevelElement, HtmlToWmlConverterSettings settings)
- {
- // Justify ******************************************************
- CssExpression textAlignProperty = blockLevelElement.GetProp("text-align");
- string textAlign;
- if (blockLevelElement.Name == XhtmlNoNamespace.caption || blockLevelElement.Name == XhtmlNoNamespace.th)
- textAlign = "center";
- else
- textAlign = "left";
- if (textAlignProperty != null)
- textAlign = textAlignProperty.ToString();
- string jc = null;
- if (textAlign == "center")
- jc = "center";
- else
- {
- if (textAlign == "right")
- jc = "right";
- else
- {
- if (textAlign == "justify")
- jc = "both";
- }
- }
- string direction = GetDirection(blockLevelElement);
- if (direction == "rtl")
- {
- if (jc == "left")
- jc = "right";
- else if (jc == "right")
- jc = "left";
- }
- XElement jcElement = null;
- if (jc != null)
- jcElement = new XElement(W.jc, new XAttribute(W.val, jc));
- return jcElement;
- }
- private class HeadingInfo
- {
- public XName Name;
- public string StyleName;
- };
- private static HeadingInfo[] HeadingTagMap = new[]
- {
- new HeadingInfo { Name = XhtmlNoNamespace.h1, StyleName = "Heading1" },
- new HeadingInfo { Name = XhtmlNoNamespace.h2, StyleName = "Heading2" },
- new HeadingInfo { Name = XhtmlNoNamespace.h3, StyleName = "Heading3" },
- new HeadingInfo { Name = XhtmlNoNamespace.h4, StyleName = "Heading4" },
- new HeadingInfo { Name = XhtmlNoNamespace.h5, StyleName = "Heading5" },
- new HeadingInfo { Name = XhtmlNoNamespace.h6, StyleName = "Heading6" },
- new HeadingInfo { Name = XhtmlNoNamespace.h7, StyleName = "Heading7" },
- new HeadingInfo { Name = XhtmlNoNamespace.h8, StyleName = "Heading8" },
- };
- private static string GetDirection(XElement element)
- {
- string retValue = "ltr";
- string dirString = (string)element.Attribute(XhtmlNoNamespace.dir);
- if (dirString != null && dirString.ToLower() == "rtl")
- retValue = "rtl";
- CssExpression directionProp = element.GetProp("direction");
- if (directionProp != null)
- {
- string directionValue = directionProp.ToString();
- if (directionValue.ToLower() == "rtl")
- retValue = "rtl";
- }
- return retValue;
- }
- private static XElement GetTableProperties(XElement element)
- {
- XElement bidiVisual = null;
- string direction = GetDirection(element);
- if (direction == "rtl")
- bidiVisual = new XElement(W.bidiVisual);
- XElement tblPr = new XElement(W.tblPr,
- bidiVisual,
- GetTableWidth(element),
- GetTableCellSpacing(element),
- GetBlockContentBorders(element, W.tblBorders, false),
- GetTableShading(element),
- GetTableCellMargins(element),
- GetTableLook(element));
- return tblPr;
- }
- private static XElement GetTableShading(XElement element)
- {
- // todo this is not done.
- // needs to work for W.tbl and W.tc
- //XElement shd = new XElement(W.shd,
- // new XAttribute(W.val, "clear"),
- // new XAttribute(W.color, "auto"),
- // new XAttribute(W.fill, "ffffff"));
- //return shd;
- return null;
- }
- private static XElement GetTableWidth(XElement element)
- {
- CssExpression width = element.GetProp("width");
- if (width.IsAuto)
- {
- return new XElement(W.tblW,
- new XAttribute(W._w, "0"),
- new XAttribute(W.type, "auto"));
- }
- XElement widthElement = new XElement(W.tblW,
- new XAttribute(W._w, (long)(Twip)width),
- new XAttribute(W.type, "dxa"));
- return widthElement;
- }
- private static XElement GetCellWidth(XElement element)
- {
- CssExpression width = element.GetProp("width");
- if (width.IsAuto)
- {
- return new XElement(W.tcW,
- new XAttribute(W._w, "0"),
- new XAttribute(W.type, "auto"));
- }
- XElement widthElement = new XElement(W.tcW,
- new XAttribute(W._w, (long)(Twip)width),
- new XAttribute(W.type, "dxa"));
- return widthElement;
- }
- private static XElement GetBlockContentBorders(XElement element, XName borderXName, bool forParagraph)
- {
- if ((element.Name == XhtmlNoNamespace.td || element.Name == XhtmlNoNamespace.th || element.Name == XhtmlNoNamespace.caption) && forParagraph)
- return null;
- XElement borders = new XElement(borderXName,
- new XElement(W.top, GetBorderAttributes(element, "top")),
- new XElement(W.left, GetBorderAttributes(element, "left")),
- new XElement(W.bottom, GetBorderAttributes(element, "bottom")),
- new XElement(W.right, GetBorderAttributes(element, "right")));
- if (borders.Elements().Attributes(W.val).Where(v => (string)v == "none").Count() == 4)
- return null;
- return borders;
- }
- private static Dictionary<string, string> BorderStyleMap = new Dictionary<string, string>()
- {
- { "none", "none" },
- { "hidden", "none" },
- { "dotted", "dotted" },
- { "dashed", "dashed" },
- { "solid", "single" },
- { "double", "double" },
- { "groove", "inset" },
- { "ridge", "outset" },
- { "inset", "inset" },
- { "outset", "outset" },
- };
- private static List<XAttribute> GetBorderAttributes(XElement element, string whichBorder)
- {
- //if (whichBorder == "right")
- // Console.WriteLine(1);
- CssExpression styleProp = element.GetProp(string.Format("border-{0}-style", whichBorder));
- CssExpression colorProp = element.GetProp(string.Format("border-{0}-color", whichBorder));
- CssExpression paddingProp = element.GetProp(string.Format("padding-{0}", whichBorder));
- CssExpression marginProp = element.GetProp(string.Format("margin-{0}", whichBorder));
- // The space attribute is equivalent to the margin properties of CSS
- // the ind element of the parent is more or less equivalent to the padding properties of CSS, except that ind takes space
- // AWAY from the space attribute, therefore ind needs to be increased by the amount of padding.
- // if there is no border, and yet there is padding, then need to create a thin border so that word will display the background
- // color of the paragraph properly (including padding).
- XAttribute val = null;
- XAttribute sz = null;
- XAttribute space = null;
- XAttribute color = null;
- if (styleProp != null)
- {
- if (BorderStyleMap.ContainsKey(styleProp.ToString()))
- val = new XAttribute(W.val, BorderStyleMap[styleProp.ToString()]);
- else
- val = new XAttribute(W.val, "none");
- }
- double borderSizeInTwips = GetBorderSize(element, whichBorder);
- double borderSizeInOneEighthPoint = borderSizeInTwips / 20 * 8;
- sz = new XAttribute(W.sz, (int)borderSizeInOneEighthPoint);
- if (element.Name == XhtmlNoNamespace.td || element.Name == XhtmlNoNamespace.th)
- {
- space = new XAttribute(W.space, "0");
- #if false
- // 2012-05-14 todo alternative algorithm for margin for cells
- if (marginProp != null)
- {
- // space is specified in points, not twips
- TPoint points = 0;
- if (marginProp.IsNotAuto)
- points = (TPoint)marginProp;
- space = new XAttribute(W.space, Math.Min(31, (double)points));
- }
- #endif
- }
- else
- {
- space = new XAttribute(W.space, "0");
- if (paddingProp != null)
- {
- // space is specified in points, not twips
- TPoint points = (TPoint)paddingProp;
- space = new XAttribute(W.space, (int)(Math.Min(31, (double)points)));
- }
- }
- if (colorProp != null)
- color = new XAttribute(W.color, colorProp.ToString());
- // no default yet
- if ((string)val == "none" && (double)space != 0d)
- {
- val.Value = "single";
- sz.Value = "0";
- //color.Value = "FF0000";
- }
- // sz is in 1/8 of a point
- // space is in 1/20 of a point
- List<XAttribute> attList = new List<XAttribute>()
- {
- val,
- sz,
- space,
- color,
- };
- return attList;
- }
- private static Twip GetBorderSize(XElement element, string whichBorder)
- {
- CssExpression widthProp = element.GetProp(string.Format("border-{0}-width", whichBorder));
- if (widthProp != null && widthProp.Terms.Count() == 1)
- {
- CssTerm term = widthProp.Terms.First();
- Twip twips = (Twip)widthProp;
- return twips;
- }
- return 12;
- }
- private static XElement GetTableLook(XElement element)
- {
- XElement tblLook = XElement.Parse(
- //@"<w:tblLook w:val='0600'
- // w:firstRow='0'
- // w:lastRow='0'
- // w:firstColumn='0'
- // w:lastColumn='0'
- // w:noHBand='1'
- // w:noVBand='1'
- // xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'/>"
- @"<w:tblLook w:val='0600' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'/>"
- );
- tblLook.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
- return tblLook;
- }
- private static XElement GetTableGrid(XElement element, HtmlToWmlConverterSettings settings)
- {
- Twip? pageWidthInTwips = (int?)settings.SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault();
- Twip? marginLeft = (int?)settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault();
- Twip? marginRight = (int?)settings.SectPr.Elements(W.pgMar).Attributes(W.right).FirstOrDefault();
- Twip printable = (long)pageWidthInTwips - (long)marginLeft - (long)marginRight;
- XElement[][] tableArray = GetTableArray(element);
- int numberColumns = tableArray[0].Length;
- CssExpression[] columnWidths = new CssExpression[numberColumns];
- for (int c = 0; c < numberColumns; c++)
- {
- CssExpression columnWidth = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto" } } };
- for (int r = 0; r < tableArray.Length; ++r)
- {
- if (tableArray[r][c] != null)
- {
- XElement cell = tableArray[r][c];
- CssExpression width = cell.GetProp("width");
- XAttribute colSpan = cell.Attribute(XhtmlNoNamespace.colspan);
- if (colSpan == null && columnWidth.ToString() == "auto" && width.ToString() != "auto")
- {
- columnWidth = width;
- break;
- }
- }
- }
- columnWidths[c] = columnWidth;
- }
- XElement tblGrid = new XElement(W.tblGrid,
- columnWidths.Select(cw => new XElement(W.gridCol,
- new XAttribute(W._w, (long)GetTwipWidth(cw, (int)printable)))));
- return tblGrid;
- }
- private static Twip GetTwipWidth(CssExpression columnWidth, int printable)
- {
- Twip defaultTwipWidth = 1440;
- if (columnWidth.Terms.Count() == 1)
- {
- CssTerm term = columnWidth.Terms.First();
- if (term.Unit == CssUnit.PT)
- {
- Double ptValue;
- if (Double.TryParse(term.Value, out ptValue))
- {
- Twip twips = (long)(ptValue * 20);
- return twips;
- }
- return defaultTwipWidth;
- }
- }
- return defaultTwipWidth;
- }
- private static XElement[][] GetTableArray(XElement table)
- {
- List<XElement> rowList = table.DescendantsTrimmed(XhtmlNoNamespace.table).Where(e => e.Name == XhtmlNoNamespace.tr).ToList();
- int numberColumns = rowList.Select(r => r.Elements().Where(e => e.Name == XhtmlNoNamespace.td || e.Name == XhtmlNoNamespace.th).Count()).Max();
- XElement[][] tableArray = new XElement[rowList.Count()][];
- int rowNumber = 0;
- foreach (var row in rowList)
- {
- tableArray[rowNumber] = new XElement[numberColumns];
- int columnNumber = 0;
- foreach (var cell in row.Elements(XhtmlNoNamespace.td))
- {
- tableArray[rowNumber][columnNumber] = cell;
- columnNumber++;
- }
- rowNumber++;
- }
- return tableArray;
- }
- private static XElement GetCellPropertiesForCaption(XElement element)
- {
- XElement gridSpan = new XElement(W.gridSpan,
- new XAttribute(W.val, 3));
- XElement tcBorders = GetBlockContentBorders(element, W.tcBorders, false);
- if (tcBorders == null)
- tcBorders = new XElement(W.tcBorders,
- new XElement(W.top, new XAttribute(W.val, "nil")),
- new XElement(W.left, new XAttribute(W.val, "nil")),
- new XElement(W.bottom, new XAttribute(W.val, "nil")),
- new XElement(W.right, new XAttribute(W.val, "nil")));
- XElement shd = GetCellShading(element);
- //XElement hideMark = new XElement(W.hideMark);
- XElement hideMark = null;
- XElement tcMar = GetCellMargins(element);
- XElement vAlign = new XElement(W.vAlign, new XAttribute(W.val, "center"));
- return new XElement(W.tcPr,
- gridSpan,
- tcBorders,
- shd,
- tcMar,
- vAlign,
- hideMark);
- }
- private static XElement GetCellProperties(XElement element)
- {
- int? colspan = (int?)element.Attribute(XhtmlNoNamespace.colspan);
- XElement gridSpan = null;
- if (colspan != null)
- gridSpan = new XElement(W.gridSpan,
- new XAttribute(W.val, colspan));
- XElement tblW = GetCellWidth(element);
- XElement tcBorders = GetBlockContentBorders(element, W.tcBorders, false);
- XElement shd = GetCellShading(element);
- //XElement hideMark = new XElement(W.hideMark);
- XElement hideMark = null;
- XElement tcMar = GetCellMargins(element);
- XElement vAlign = new XElement(W.vAlign, new XAttribute(W.val, "center"));
- XElement vMerge = null;
- if (element.Attribute("HtmlToWmlVMergeNoRestart") != null)
- vMerge = new XElement(W.vMerge);
- else
- if (element.Attribute("HtmlToWmlVMergeRestart") != null)
- vMerge = new XElement(W.vMerge,
- new XAttribute(W.val, "restart"));
- string vAlignValue = (string)element.Attribute(XhtmlNoNamespace.valign);
- CssExpression verticalAlignmentProp = element.GetProp("vertical-align");
- if (verticalAlignmentProp != null && verticalAlignmentProp.ToString() != "inherit")
- vAlignValue = verticalAlignmentProp.ToString();
- if (vAlignValue != null)
- {
- if (vAlignValue == "middle" || (vAlignValue != "top" && vAlignValue != "bottom"))
- vAlignValue = "center";
- vAlign = new XElement(W.vAlign, new XAttribute(W.val, vAlignValue));
- }
- return new XElement(W.tcPr,
- tblW,
- gridSpan,
- vMerge,
- tcBorders,
- shd,
- tcMar,
- vAlign,
- hideMark);
- }
- private static XElement GetCellHeaderProperties(XElement element)
- {
- //int? colspan = (int?)element.Attribute(Xhtml.colspan);
- //XElement gridSpan = null;
- //if (colspan != null)
- // gridSpan = new XElement(W.gridSpan,
- // new XAttribute(W.val, colspan));
- XElement tblW = GetCellWidth(element);
- XElement tcBorders = GetBlockContentBorders(element, W.tcBorders, false);
- XElement shd = GetCellShading(element);
- //XElement hideMark = new XElement(W.hideMark);
- XElement hideMark = null;
- XElement tcMar = GetCellMargins(element);
- XElement vAlign = new XElement(W.vAlign, new XAttribute(W.val, "center"));
- return new XElement(W.tcPr,
- tblW,
- tcBorders,
- shd,
- tcMar,
- vAlign,
- hideMark);
- }
- private static XElement GetCellShading(XElement element)
- {
- CssExpression backgroundColorProp = element.GetProp("background-color");
- if (backgroundColorProp != null && (string)backgroundColorProp != "transparent")
- {
- XElement shd = new XElement(W.shd,
- new XAttribute(W.val, "clear"),
- new XAttribute(W.color, "auto"),
- new XAttribute(W.fill, backgroundColorProp));
- return shd;
- }
- return null;
- }
- private static XElement GetCellMargins(XElement element)
- {
- CssExpression topProp = element.GetProp("padding-top");
- CssExpression leftProp = element.GetProp("padding-left");
- CssExpression bottomProp = element.GetProp("padding-bottom");
- CssExpression rightProp = element.GetProp("padding-right");
- if ((long)topProp == 0 &&
- (long)leftProp == 0 &&
- (long)bottomProp == 0 &&
- (long)rightProp == 0)
- return null;
- XElement top = null;
- if (topProp != null)
- top = new XElement(W.top,
- new XAttribute(W._w, (long)(Twip)topProp),
- new XAttribute(W.type, "dxa"));
- XElement left = null;
- if (leftProp != null)
- left = new XElement(W.left,
- new XAttribute(W._w, (long)(Twip)leftProp),
- new XAttribute(W.type, "dxa"));
- XElement bottom = null;
- if (bottomProp != null)
- bottom = new XElement(W.bottom,
- new XAttribute(W._w, (long)(Twip)bottomProp),
- new XAttribute(W.type, "dxa"));
- XElement right = null;
- if (rightProp != null)
- right = new XElement(W.right,
- new XAttribute(W._w, (long)(Twip)rightProp),
- new XAttribute(W.type, "dxa"));
- XElement tcMar = new XElement(W.tcMar,
- top, left, bottom, right);
- if (tcMar.Elements().Any())
- return tcMar;
- return null;
- }
- #if false
- <w:tcMar>
- <w:top w:w="720"
- w:type="dxa" />
- <w:left w:w="720"
- w:type="dxa" />
- <w:bottom w:w="720"
- w:type="dxa" />
- <w:right w:w="720"
- w:type="dxa" />
- </w:tcMar>
- #endif
- private static XElement GetTableCellSpacing(XElement element)
- {
- XElement table = element.AncestorsAndSelf(XhtmlNoNamespace.table).FirstOrDefault();
- XElement tblCellSpacing = null;
- if (table != null)
- {
- CssExpression borderCollapse = table.GetProp("border-collapse");
- if (borderCollapse == null || (string)borderCollapse != "collapse")
- {
- // todo very incomplete
- CssExpression borderSpacing = table.GetProp("border-spacing");
- CssExpression marginTopProperty = element.GetProp("margin-top");
- if (marginTopProperty == null)
- marginTopProperty = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT } } };
- CssExpression marginBottomProperty = element.GetProp("margin-bottom");
- if (marginBottomProperty == null)
- marginBottomProperty = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = CssTermType.Number, Unit = CssUnit.PT } } };
- Twip twips1 = (Twip)marginTopProperty;
- Twip twips2 = (Twip)marginBottomProperty;
- Twip minTwips = 15;
- if (borderSpacing != null)
- minTwips = (Twip)borderSpacing;
- long twipToUse = Math.Max((long)twips1, (long)twips2);
- twipToUse = Math.Max(twipToUse, (long)minTwips);
- // have to divide twipToUse by 2 because border-spacing specifies the space between the border of once cell and its adjacent.
- // tblCellSpacing specifies the distance between the border and the half way point between two cells.
- long twipToUseOverTwo = (long)twipToUse / 2;
- tblCellSpacing = new XElement(W.tblCellSpacing, new XAttribute(W._w, twipToUseOverTwo),
- new XAttribute(W.type, "dxa"));
- }
- }
- return tblCellSpacing;
- }
- private static XElement GetTableCellMargins(XElement element)
- {
- // todo very incomplete
- XElement tblCellMar = XElement.Parse(
- @"<w:tblCellMar xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:top w:w='15'
- w:type='dxa'/>
- <w:left w:w='15'
- w:type='dxa'/>
- <w:bottom w:w='15'
- w:type='dxa'/>
- <w:right w:w='15'
- w:type='dxa'/>
- </w:tblCellMar>");
- tblCellMar.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
- return tblCellMar;
- }
- private static XElement GetTableRowProperties(XElement element)
- {
- XElement trPr = null;
- XElement table = element.AncestorsAndSelf(XhtmlNoNamespace.table).FirstOrDefault();
- if (table != null)
- {
- CssExpression heightProperty = element.GetProp("height");
- //long? maxCellHeight = element.Elements(Xhtml.td).Aggregate((long?)null,
- // (XElement td, long? last) =>
- // {
- // Expression heightProp2 = td.GetProp("height");
- // if (heightProp2 == null)
- // return last;
- // if (last == null)
- // return (long)(Twip)heightProp2;
- // return last + (long?)(long)(Twip)heightProp2;
- // });
- var cellHeights = element
- .Elements(XhtmlNoNamespace.td)
- .Select(td => td.GetProp("height"))
- .Concat(new[] { heightProperty })
- .Where(d => d != null)
- .Select(e => (long)(Twip)e)
- .ToList();
- XElement trHeight = null;
- if (cellHeights.Any())
- {
- long max = cellHeights.Max();
- trHeight = new XElement(W.trHeight,
- new XAttribute(W.val, max));
- }
- CssExpression borderCollapseProperty = table.GetProp("border-collapse");
- XElement borderCollapse = null;
- if (borderCollapseProperty != null && (string)borderCollapseProperty != "collapse")
- borderCollapse = GetTableCellSpacing(element);
- trPr = new XElement(W.trPr,
- GetTableCellSpacing(element),
- trHeight);
- if (trPr.Elements().Any())
- return trPr;
- }
- return trPr;
- }
- private static XAttribute GetXmlSpaceAttribute(string value)
- {
- if (value.StartsWith(" ") || value.EndsWith(" "))
- return new XAttribute(XNamespace.Xml + "space", "preserve");
- return null;
- }
- private static Dictionary<string, string> InstalledFonts = new Dictionary<string, string>
- {
- {"serif", "Times New Roman"},
- {"sans-serif", "Arial"},
- {"cursive", "Kunstler Script"},
- {"fantasy", "Curlz MT"},
- {"monospace", "Courier New"},
- {"agency fb", "Agency FB"},
- {"agencyfb", "Agency FB"},
- {"aharoni", "Aharoni"},
- {"algerian", "Algerian"},
- {"andalus", "Andalus"},
- {"angsana new", "Angsana New"},
- {"angsananew", "Angsana New"},
- {"angsanaupc", "AngsanaUPC"},
- {"aparajita", "Aparajita"},
- {"arabic typesetting", "Arabic Typesetting"},
- {"arabictypesetting", "Arabic Typesetting"},
- {"arial", "Arial"},
- {"arial black", "Arial Black"},
- {"arial narrow", "Arial Narrow"},
- {"arial rounded mt bold", "Arial Rounded MT Bold"},
- {"arial unicode ms", "Arial Unicode MS"},
- {"arialblack", "Arial Black"},
- {"arialnarrow", "Arial Narrow"},
- {"arialroundedmtbold", "Arial Rounded MT Bold"},
- {"arialunicodems", "Arial Unicode MS"},
- {"baskerville old face", "Baskerville Old Face"},
- {"baskervilleoldface", "Baskerville Old Face"},
- {"batang", "Batang"},
- {"batangche", "BatangChe"},
- {"bauhaus 93", "Bauhaus 93"},
- {"bauhaus93", "Bauhaus 93"},
- {"bell mt", "Bell MT"},
- {"bellmt", "Bell MT"},
- {"berlin sans fb", "Berlin Sans FB"},
- {"berlin sans fb demi", "Berlin Sans FB Demi"},
- {"berlinsansfb", "Berlin Sans FB"},
- {"berlinsansfbdemi", "Berlin Sans FB Demi"},
- {"bernard mt condensed", "Bernard MT Condensed"},
- {"bernardmtcondensed", "Bernard MT Condensed"},
- {"blackadder itc", "Blackadder ITC"},
- {"blackadderitc", "Blackadder ITC"},
- {"bodoni mt", "Bodoni MT"},
- {"bodoni mt black", "Bodoni MT Black"},
- {"bodoni mt condensed", "Bodoni MT Condensed"},
- {"bodoni mt poster compressed", "Bodoni MT Poster Compressed"},
- {"bodonimt", "Bodoni MT"},
- {"bodonimtblack", "Bodoni MT Black"},
- {"bodonimtcondensed", "Bodoni MT Condensed"},
- {"bodonimtpostercompressed", "Bodoni MT Poster Compressed"},
- {"book antiqua", "Book Antiqua"},
- {"bookantiqua", "Book Antiqua"},
- {"bookman old style", "Bookman Old Style"},
- {"bookmanoldstyle", "Bookman Old Style"},
- {"bookshelf symbol 7", "Bookshelf Symbol 7"},
- {"bookshelfsymbol7", "Bookshelf Symbol 7"},
- {"bradley hand itc", "Bradley Hand ITC"},
- {"bradleyhanditc", "Bradley Hand ITC"},
- {"britannic bold", "Britannic Bold"},
- {"britannicbold", "Britannic Bold"},
- {"broadway", "Broadway"},
- {"browallia new", "Browallia New"},
- {"browallianew", "Browallia New"},
- {"browalliaupc", "BrowalliaUPC"},
- {"brush script mt", "Brush Script MT"},
- {"brushscriptmt", "Brush Script MT"},
- {"calibri", "Calibri"},
- {"californian fb", "Californian FB"},
- {"californianfb", "Californian FB"},
- {"calisto mt", "Calisto MT"},
- {"calistomt", "Calisto MT"},
- {"cambria", "Cambria"},
- {"cambria math", "Cambria Math"},
- {"cambriamath", "Cambria Math"},
- {"candara", "Candara"},
- {"castellar", "Castellar"},
- {"centaur", "Centaur"},
- {"century", "Century"},
- {"century gothic", "Century Gothic"},
- {"century schoolbook", "Century Schoolbook"},
- {"centurygothic", "Century Gothic"},
- {"centuryschoolbook", "Century Schoolbook"},
- {"chiller", "Chiller"},
- {"colonna mt", "Colonna MT"},
- {"colonnamt", "Colonna MT"},
- {"comic sans ms", "Comic Sans MS"},
- {"comicsansms", "Comic Sans MS"},
- {"consolas", "Consolas"},
- {"constantia", "Constantia"},
- {"cooper black", "Cooper Black"},
- {"cooperblack", "Cooper Black"},
- {"copperplate gothic bold", "Copperplate Gothic Bold"},
- {"copperplate gothic light", "Copperplate Gothic Light"},
- {"copperplategothicbold", "Copperplate Gothic Bold"},
- {"copperplategothiclight", "Copperplate Gothic Light"},
- {"corbel", "Corbel"},
- {"cordia new", "Cordia New"},
- {"cordianew", "Cordia New"},
- {"cordiaupc", "CordiaUPC"},
- {"courier new", "Courier New"},
- {"couriernew", "Courier New"},
- {"curlz mt", "Curlz MT"},
- {"curlzmt", "Curlz MT"},
- {"daunpenh", "DaunPenh"},
- {"david", "David"},
- {"dfkai-sb", "DFKai-SB"},
- {"dilleniaupc", "DilleniaUPC"},
- {"dokchampa", "DokChampa"},
- {"dotum", "Dotum"},
- {"dotumche", "DotumChe"},
- {"ebrima", "Ebrima"},
- {"edwardian script itc", "Edwardian Script ITC"},
- {"edwardianscriptitc", "Edwardian Script ITC"},
- {"elephant", "Elephant"},
- {"engravers mt", "Engravers MT"},
- {"engraversmt", "Engravers MT"},
- {"eras bold itc", "Eras Bold ITC"},
- {"eras demi itc", "Eras Demi ITC"},
- {"eras light itc", "Eras Light ITC"},
- {"eras medium itc", "Eras Medium ITC"},
- {"erasbolditc", "Eras Bold ITC"},
- {"erasdemiitc", "Eras Demi ITC"},
- {"eraslightitc", "Eras Light ITC"},
- {"erasmediumitc", "Eras Medium ITC"},
- {"estrangelo edessa", "Estrangelo Edessa"},
- {"estrangeloedessa", "Estrangelo Edessa"},
- {"eucrosiaupc", "EucrosiaUPC"},
- {"euphemia", "Euphemia"},
- {"fangsong", "FangSong"},
- {"felix titling", "Felix Titling"},
- {"felixtitling", "Felix Titling"},
- {"footlight mt light", "Footlight MT Light"},
- {"footlightmtlight", "Footlight MT Light"},
- {"forte", "Forte"},
- {"franklin gothic book", "Franklin Gothic Book"},
- {"franklin gothic demi", "Franklin Gothic Demi"},
- {"franklin gothic demi cond", "Franklin Gothic Demi Cond"},
- {"franklin gothic heavy", "Franklin Gothic Heavy"},
- {"franklin gothic medium", "Franklin Gothic Medium"},
- {"franklin gothic medium cond", "Franklin Gothic Medium Cond"},
- {"franklingothicbook", "Franklin Gothic Book"},
- {"franklingothicdemi", "Franklin Gothic Demi"},
- {"franklingothicdemicond", "Franklin Gothic Demi Cond"},
- {"franklingothicheavy", "Franklin Gothic Heavy"},
- {"franklingothicmedium", "Franklin Gothic Medium"},
- {"franklingothicmediumcond", "Franklin Gothic Medium Cond"},
- {"frankruehl", "FrankRuehl"},
- {"freesiaupc", "FreesiaUPC"},
- {"freestyle script", "Freestyle Script"},
- {"freestylescript", "Freestyle Script"},
- {"french script mt", "French Script MT"},
- {"frenchscriptmt", "French Script MT"},
- {"gabriola", "Gabriola"},
- {"garamond", "Garamond"},
- {"gautami", "Gautami"},
- {"georgia", "Georgia"},
- {"gigi", "Gigi"},
- {"gill sans mt", "Gill Sans MT"},
- {"gill sans mt condensed", "Gill Sans MT Condensed"},
- {"gill sans mt ext condensed bold", "Gill Sans MT Ext Condensed Bold"},
- {"gill sans ultra bold", "Gill Sans Ultra Bold"},
- {"gill sans ultra bold condensed", "Gill Sans Ultra Bold Condensed"},
- {"gillsansmt", "Gill Sans MT"},
- {"gillsansmtcondensed", "Gill Sans MT Condensed"},
- {"gillsansmtextcondensedbold", "Gill Sans MT Ext Condensed Bold"},
- {"gillsansultrabold", "Gill Sans Ultra Bold"},
- {"gillsansultraboldcondensed", "Gill Sans Ultra Bold Condensed"},
- {"gisha", "Gisha"},
- {"gloucester mt extra condensed", "Gloucester MT Extra Condensed"},
- {"gloucestermtextracondensed", "Gloucester MT Extra Condensed"},
- {"goudy old style", "Goudy Old Style"},
- {"goudy stout", "Goudy Stout"},
- {"goudyoldstyle", "Goudy Old Style"},
- {"goudystout", "Goudy Stout"},
- {"gulim", "Gulim"},
- {"gulimche", "GulimChe"},
- {"gungsuh", "Gungsuh"},
- {"gungsuhche", "GungsuhChe"},
- {"haettenschweiler", "Haettenschweiler"},
- {"harlow solid italic", "Harlow Solid Italic"},
- {"harlowsoliditalic", "Harlow Solid Italic"},
- {"harrington", "Harrington"},
- {"high tower text", "High Tower Text"},
- {"hightowertext", "High Tower Text"},
- {"impact", "Impact"},
- {"imprint mt shadow", "Imprint MT Shadow"},
- {"imprintmtshadow", "Imprint MT Shadow"},
- {"informal roman", "Informal Roman"},
- {"informalroman", "Informal Roman"},
- {"irisupc", "IrisUPC"},
- {"iskoola pota", "Iskoola Pota"},
- {"iskoolapota", "Iskoola Pota"},
- {"jasmineupc", "JasmineUPC"},
- {"jokerman", "Jokerman"},
- {"juice itc", "Juice ITC"},
- {"juiceitc", "Juice ITC"},
- {"kaiti", "KaiTi"},
- {"kalinga", "Kalinga"},
- {"kartika", "Kartika"},
- {"khmer ui", "Khmer UI"},
- {"khmerui", "Khmer UI"},
- {"kodchiangupc", "KodchiangUPC"},
- {"kokila", "Kokila"},
- {"kristen itc", "Kristen ITC"},
- {"kristenitc", "Kristen ITC"},
- {"kunstler script", "Kunstler Script"},
- {"kunstlerscript", "Kunstler Script"},
- {"lao ui", "Lao UI"},
- {"laoui", "Lao UI"},
- {"latha", "Latha"},
- {"leelawadee", "Leelawadee"},
- {"levenim mt", "Levenim MT"},
- {"levenimmt", "Levenim MT"},
- {"lilyupc", "LilyUPC"},
- {"lucida bright", "Lucida Bright"},
- {"lucida calligraphy", "Lucida Calligraphy"},
- {"lucida console", "Lucida Console"},
- {"lucida fax", "Lucida Fax"},
- {"lucida handwriting", "Lucida Handwriting"},
- {"lucida sans", "Lucida Sans"},
- {"lucida sans typewriter", "Lucida Sans Typewriter"},
- {"lucida sans unicode", "Lucida Sans Unicode"},
- {"lucidabright", "Lucida Bright"},
- {"lucidacalligraphy", "Lucida Calligraphy"},
- {"lucidaconsole", "Lucida Console"},
- {"lucidafax", "Lucida Fax"},
- {"lucidahandwriting", "Lucida Handwriting"},
- {"lucidasans", "Lucida Sans"},
- {"lucidasanstypewriter", "Lucida Sans Typewriter"},
- {"lucidasansunicode", "Lucida Sans Unicode"},
- {"magneto", "Magneto"},
- {"maiandra gd", "Maiandra GD"},
- {"maiandragd", "Maiandra GD"},
- {"malgun gothic", "Malgun Gothic"},
- {"malgungothic", "Malgun Gothic"},
- {"mangal", "Mangal"},
- {"marlett", "Marlett"},
- {"matura mt script capitals", "Matura MT Script Capitals"},
- {"maturamtscriptcapitals", "Matura MT Script Capitals"},
- {"meiryo", "Meiryo"},
- {"meiryo ui", "Meiryo UI"},
- {"meiryoui", "Meiryo UI"},
- {"microsoft himalaya", "Microsoft Himalaya"},
- {"microsoft jhenghei", "Microsoft JhengHei"},
- {"microsoft new tai lue", "Microsoft New Tai Lue"},
- {"microsoft phagspa", "Microsoft PhagsPa"},
- {"microsoft sans serif", "Microsoft Sans Serif"},
- {"microsoft tai le", "Microsoft Tai Le"},
- {"microsoft uighur", "Microsoft Uighur"},
- {"microsoft yahei", "Microsoft YaHei"},
- {"microsoft yi baiti", "Microsoft Yi Baiti"},
- {"microsofthimalaya", "Microsoft Himalaya"},
- {"microsoftjhenghei", "Microsoft JhengHei"},
- {"microsoftnewtailue", "Microsoft New Tai Lue"},
- {"microsoftphagspa", "Microsoft PhagsPa"},
- {"microsoftsansserif", "Microsoft Sans Serif"},
- {"microsofttaile", "Microsoft Tai Le"},
- {"microsoftuighur", "Microsoft Uighur"},
- {"microsoftyahei", "Microsoft YaHei"},
- {"microsoftyibaiti", "Microsoft Yi Baiti"},
- {"mingliu", "MingLiU"},
- {"mingliu_hkscs", "MingLiU_HKSCS"},
- {"mingliu_hkscs-extb", "MingLiU_HKSCS-ExtB"},
- {"mingliu-extb", "MingLiU-ExtB"},
- {"miriam", "Miriam"},
- {"miriam fixed", "Miriam Fixed"},
- {"miriamfixed", "Miriam Fixed"},
- {"mistral", "Mistral"},
- {"modern no. 20", "Modern No. 20"},
- {"modernno.20", "Modern No. 20"},
- {"mongolian baiti", "Mongolian Baiti"},
- {"mongolianbaiti", "Mongolian Baiti"},
- {"monotype corsiva", "Monotype Corsiva"},
- {"monotypecorsiva", "Monotype Corsiva"},
- {"moolboran", "MoolBoran"},
- {"ms gothic", "MS Gothic"},
- {"ms mincho", "MS Mincho"},
- {"ms pgothic", "MS PGothic"},
- {"ms pmincho", "MS PMincho"},
- {"ms reference sans serif", "MS Reference Sans Serif"},
- {"ms reference specialty", "MS Reference Specialty"},
- {"ms ui gothic", "MS UI Gothic"},
- {"msgothic", "MS Gothic"},
- {"msmincho", "MS Mincho"},
- {"mspgothic", "MS PGothic"},
- {"mspmincho", "MS PMincho"},
- {"msreferencesansserif", "MS Reference Sans Serif"},
- {"msreferencespecialty", "MS Reference Specialty"},
- {"msuigothic", "MS UI Gothic"},
- {"mt extra", "MT Extra"},
- {"mtextra", "MT Extra"},
- {"mv boli", "MV Boli"},
- {"mvboli", "MV Boli"},
- {"narkisim", "Narkisim"},
- {"niagara engraved", "Niagara Engraved"},
- {"niagara solid", "Niagara Solid"},
- {"niagaraengraved", "Niagara Engraved"},
- {"niagarasolid", "Niagara Solid"},
- {"nsimsun", "NSimSun"},
- {"nyala", "Nyala"},
- {"ocr a extended", "OCR A Extended"},
- {"ocraextended", "OCR A Extended"},
- {"old english text mt", "Old English Text MT"},
- {"oldenglishtextmt", "Old English Text MT"},
- {"onyx", "Onyx"},
- {"palace script mt", "Palace Script MT"},
- {"palacescriptmt", "Palace Script MT"},
- {"palatino linotype", "Palatino Linotype"},
- {"palatinolinotype", "Palatino Linotype"},
- {"papyrus", "Papyrus"},
- {"parchment", "Parchment"},
- {"perpetua", "Perpetua"},
- {"perpetua titling mt", "Perpetua Titling MT"},
- {"perpetuatitlingmt", "Perpetua Titling MT"},
- {"plantagenet cherokee", "Plantagenet Cherokee"},
- {"plantagenetcherokee", "Plantagenet Cherokee"},
- {"playbill", "Playbill"},
- {"pmingliu", "PMingLiU"},
- {"pmingliu-extb", "PMingLiU-ExtB"},
- {"poor richard", "Poor Richard"},
- {"poorrichard", "Poor Richard"},
- {"pristina", "Pristina"},
- {"raavi", "Raavi"},
- {"rage italic", "Rage Italic"},
- {"rageitalic", "Rage Italic"},
- {"ravie", "Ravie"},
- {"rockwell", "Rockwell"},
- {"rockwell condensed", "Rockwell Condensed"},
- {"rockwell extra bold", "Rockwell Extra Bold"},
- {"rockwellcondensed", "Rockwell Condensed"},
- {"rockwellextrabold", "Rockwell Extra Bold"},
- {"rod", "Rod"},
- {"sakkal majalla", "Sakkal Majalla"},
- {"sakkalmajalla", "Sakkal Majalla"},
- {"script mt bold", "Script MT Bold"},
- {"scriptmtbold", "Script MT Bold"},
- {"segoe print", "Segoe Print"},
- {"segoe script", "Segoe Script"},
- {"segoe ui", "Segoe UI"},
- {"segoe ui light", "Segoe UI Light"},
- {"segoe ui semibold", "Segoe UI Semibold"},
- {"segoe ui symbol", "Segoe UI Symbol"},
- {"segoeprint", "Segoe Print"},
- {"segoescript", "Segoe Script"},
- {"segoeui", "Segoe UI"},
- {"segoeuilight", "Segoe UI Light"},
- {"segoeuisemibold", "Segoe UI Semibold"},
- {"segoeuisymbol", "Segoe UI Symbol"},
- {"shonar bangla", "Shonar Bangla"},
- {"shonarbangla", "Shonar Bangla"},
- {"showcard gothic", "Showcard Gothic"},
- {"showcardgothic", "Showcard Gothic"},
- {"shruti", "Shruti"},
- {"simhei", "SimHei"},
- {"simplified arabic", "Simplified Arabic"},
- {"simplified arabic fixed", "Simplified Arabic Fixed"},
- {"simplifiedarabic", "Simplified Arabic"},
- {"simplifiedarabicfixed", "Simplified Arabic Fixed"},
- {"simsun", "SimSun"},
- {"simsun-extb", "SimSun-ExtB"},
- {"snap itc", "Snap ITC"},
- {"snapitc", "Snap ITC"},
- {"stencil", "Stencil"},
- {"swgamekeys mt", "SWGamekeys MT"},
- {"swgamekeysmt", "SWGamekeys MT"},
- {"swmacro", "SWMacro"},
- {"sylfaen", "Sylfaen"},
- {"symbol", "Symbol"},
- {"tahoma", "Tahoma"},
- {"tempus sans itc", "Tempus Sans ITC"},
- {"tempussansitc", "Tempus Sans ITC"},
- {"times new roman", "Times New Roman"},
- {"timesnewroman", "Times New Roman"},
- {"traditional arabic", "Traditional Arabic"},
- {"traditionalarabic", "Traditional Arabic"},
- {"trebuchet ms", "Trebuchet MS"},
- {"trebuchetms", "Trebuchet MS"},
- {"tunga", "Tunga"},
- {"tw cen mt", "Tw Cen MT"},
- {"tw cen mt condensed", "Tw Cen MT Condensed"},
- {"tw cen mt condensed extra bold", "Tw Cen MT Condensed Extra Bold"},
- {"twcenmt", "Tw Cen MT"},
- {"twcenmtcondensed", "Tw Cen MT Condensed"},
- {"twcenmtcondensedextrabold", "Tw Cen MT Condensed Extra Bold"},
- {"utsaah", "Utsaah"},
- {"vani", "Vani"},
- {"verdana", "Verdana"},
- {"vijaya", "Vijaya"},
- {"viner hand itc", "Viner Hand ITC"},
- {"vinerhanditc", "Viner Hand ITC"},
- {"vivaldi", "Vivaldi"},
- {"vladimir script", "Vladimir Script"},
- {"vladimirscript", "Vladimir Script"},
- {"vrinda", "Vrinda"},
- {"webdings", "Webdings"},
- {"wide latin", "Wide Latin"},
- {"widelatin", "Wide Latin"},
- {"wingdings", "Wingdings"},
- {"wingdings 2", "Wingdings 2"},
- {"wingdings 3", "Wingdings 3"},
- {"wingdings2", "Wingdings 2"},
- {"wingdings3", "Wingdings 3"},
- };
- private static TPoint? GetUsedSizeFromFontSizeProperty(CssExpression fontSize)
- {
- if (fontSize == null)
- return null;
- if (fontSize.Terms.Count() == 1)
- {
- CssTerm term = fontSize.Terms.First();
- double size = 0;
- if (term.Unit == CssUnit.PT)
- {
- if (double.TryParse(term.Value, out size))
- return new TPoint(size);
- return null;
- }
- return null;
- }
- return null;
- }
- private static string GetUsedFontFromFontFamilyProperty(CssExpression fontFamily)
- {
- if (fontFamily == null)
- return null;
- string fullFontFamily = fontFamily.Terms.Select(t => t + " ").StringConcatenate().Trim();
- string lcfont = fullFontFamily.ToLower();
- if (InstalledFonts.ContainsKey(lcfont))
- return InstalledFonts[lcfont];
- return null;
- }
- private static XElement GetBackgroundProperty(XElement element)
- {
- CssExpression color = element.GetProp("background-color");
- // todo this really should test against default background color
- if (color.ToString() != "transparent")
- {
- string hexString = color.ToString();
- XElement shd = new XElement(W.shd,
- new XAttribute(W.val, "clear"),
- new XAttribute(W.color, "auto"),
- new XAttribute(W.fill, hexString));
- return shd;
- }
- return null;
- }
- }
- public class PictureId
- {
- public int Id;
- }
- class HtmlToWmlFontUpdater
- {
- public static void UpdateFontsPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings)
- {
- XDocument fontXDoc = wDoc.MainDocumentPart.FontTablePart.GetXDocument();
- PtUtils.AddElementIfMissing(fontXDoc,
- fontXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1")
- .FirstOrDefault(),
- @"<w:font w:name='Verdana' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:panose1 w:val='020B0604030504040204'/>
- <w:charset w:val='00'/>
- <w:family w:val='swiss'/>
- <w:pitch w:val='variable'/>
- <w:sig w:usb0='A10006FF'
- w:usb1='4000205B'
- w:usb2='00000010'
- w:usb3='00000000'
- w:csb0='0000019F'
- w:csb1='00000000'/>
- </w:font>");
- wDoc.MainDocumentPart.FontTablePart.PutXDocument();
- }
- }
- class NumberingUpdater
- {
- public static void InitializeNumberingPart(WordprocessingDocument wDoc)
- {
- NumberingDefinitionsPart numberingPart = wDoc.MainDocumentPart.NumberingDefinitionsPart;
- if (numberingPart == null)
- {
- wDoc.MainDocumentPart.AddNewPart<NumberingDefinitionsPart>();
- XDocument npXDoc = new XDocument(
- new XElement(W.numbering,
- new XAttribute(XNamespace.Xmlns + "w", W.w)));
- wDoc.MainDocumentPart.NumberingDefinitionsPart.PutXDocument(npXDoc);
- }
- }
- public static void GetNextNumId(WordprocessingDocument wDoc, out int nextNumId)
- {
- InitializeNumberingPart(wDoc);
- NumberingDefinitionsPart numberingPart = wDoc.MainDocumentPart.NumberingDefinitionsPart;
- XDocument numberingXDoc = numberingPart.GetXDocument();
- nextNumId = numberingXDoc.Root.Elements(W.num).Attributes(W.numId).Select(ni => (int)ni).Concat(new[] { 1 }).Max();
- }
- // decimal, lowerLetter
- private static string OrderedListAbstractXml =
- @"<w:abstractNum w:abstractNumId='{0}' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:multiLevelType w:val='multilevel'/>
- <w:tmpl w:val='7D26959A'/>
- <w:lvl w:ilvl='0'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{1}'/>
- <w:lvlText w:val='%1.'/>
- <w:lvlJc w:val='{2}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='720'/>
- </w:tabs>
- <w:ind w:left='720'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='1'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{3}'/>
- <w:lvlText w:val='%2.'/>
- <w:lvlJc w:val='{4}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='1440'/>
- </w:tabs>
- <w:ind w:left='1440'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='2'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{5}'/>
- <w:lvlText w:val='%3.'/>
- <w:lvlJc w:val='{6}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='2160'/>
- </w:tabs>
- <w:ind w:left='2160'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='3'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{7}'/>
- <w:lvlText w:val='%4.'/>
- <w:lvlJc w:val='{8}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='2880'/>
- </w:tabs>
- <w:ind w:left='2880'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='4'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{9}'/>
- <w:lvlText w:val='%5.'/>
- <w:lvlJc w:val='{10}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='3600'/>
- </w:tabs>
- <w:ind w:left='3600'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='5'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{11}'/>
- <w:lvlText w:val='%6.'/>
- <w:lvlJc w:val='{12}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='4320'/>
- </w:tabs>
- <w:ind w:left='4320'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='6'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{13}'/>
- <w:lvlText w:val='%7.'/>
- <w:lvlJc w:val='{14}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='5040'/>
- </w:tabs>
- <w:ind w:left='5040'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='7'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{15}'/>
- <w:lvlText w:val='%8.'/>
- <w:lvlJc w:val='{16}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='5760'/>
- </w:tabs>
- <w:ind w:left='5760'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- <w:lvl w:ilvl='8'
- w:tentative='1'>
- <w:start w:val='1'/>
- <w:numFmt w:val='{17}'/>
- <w:lvlText w:val='%9.'/>
- <w:lvlJc w:val='{18}'/>
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num'
- w:pos='6480'/>
- </w:tabs>
- <w:ind w:left='6480'
- w:hanging='360'/>
- </w:pPr>
- </w:lvl>
- </w:abstractNum>";
- private static string BulletAbstractXml =
- @"<w:abstractNum w:abstractNumId='{0}' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:multiLevelType w:val='multilevel' />
- <w:tmpl w:val='02BEA0DA' />
- <w:lvl w:ilvl='0'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='720' />
- </w:tabs>
- <w:ind w:left='720' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Symbol' w:hAnsi='Symbol' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='o' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='1440' />
- </w:tabs>
- <w:ind w:left='1440' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Courier New' w:hAnsi='Courier New' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='2' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='2160' />
- </w:tabs>
- <w:ind w:left='2160' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='3' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='2880' />
- </w:tabs>
- <w:ind w:left='2880' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='4' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='3600' />
- </w:tabs>
- <w:ind w:left='3600' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='5' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='4320' />
- </w:tabs>
- <w:ind w:left='4320' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='6' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='5040' />
- </w:tabs>
- <w:ind w:left='5040' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='7' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='5760' />
- </w:tabs>
- <w:ind w:left='5760' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- <w:lvl w:ilvl='8' w:tentative='1'>
- <w:start w:val='1' />
- <w:numFmt w:val='bullet' />
- <w:lvlText w:val='' />
- <w:lvlJc w:val='left' />
- <w:pPr>
- <w:tabs>
- <w:tab w:val='num' w:pos='6480' />
- </w:tabs>
- <w:ind w:left='6480' w:hanging='360' />
- </w:pPr>
- <w:rPr>
- <w:rFonts w:ascii='Wingdings' w:hAnsi='Wingdings' w:hint='default' />
- <w:sz w:val='20' />
- </w:rPr>
- </w:lvl>
- </w:abstractNum>";
- public static void UpdateNumberingPart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings)
- {
- InitializeNumberingPart(wDoc);
- NumberingDefinitionsPart numberingPart = wDoc.MainDocumentPart.NumberingDefinitionsPart;
- XDocument numberingXDoc = numberingPart.GetXDocument();
- int nextAbstractId, nextNumId;
- nextNumId = numberingXDoc.Root.Elements(W.num).Attributes(W.numId).Select(ni => (int)ni).Concat(new[] { 1 }).Max();
- nextAbstractId = numberingXDoc.Root.Elements(W.abstractNum).Attributes(W.abstractNumId).Select(ani => (int)ani).Concat(new[] { 0 }).Max();
- var numberingElements = html.DescendantsAndSelf().Where(d => d.Name == XhtmlNoNamespace.ol || d.Name == XhtmlNoNamespace.ul).ToList();
- Dictionary<int, int> numToAbstractNum = new Dictionary<int, int>();
- // add abstract numbering elements
- int currentNumId = nextNumId;
- int currentAbstractId = nextAbstractId;
- foreach (var list in numberingElements)
- {
- HtmlToWmlConverterCore.NumberedItemAnnotation nia = list.Annotation<HtmlToWmlConverterCore.NumberedItemAnnotation>();
- if (!numToAbstractNum.ContainsKey(nia.numId))
- {
- numToAbstractNum.Add(nia.numId, currentAbstractId);
- if (list.Name == XhtmlNoNamespace.ul)
- {
- XElement bulletAbstract = XElement.Parse(String.Format(BulletAbstractXml, currentAbstractId++));
- numberingXDoc.Root.Add(bulletAbstract);
- }
- if (list.Name == XhtmlNoNamespace.ol)
- {
- string[] numFmt = new string[9];
- string[] just = new string[9];
- for (int i = 0; i < numFmt.Length; ++i)
- {
- numFmt[i] = "decimal";
- just[i] = "left";
- XElement itemAtLevel = numberingElements
- .FirstOrDefault(nf =>
- {
- HtmlToWmlConverterCore.NumberedItemAnnotation n = nf.Annotation<HtmlToWmlConverterCore.NumberedItemAnnotation>();
- if (n != null && n.numId == nia.numId && n.ilvl == i)
- return true;
- return false;
- });
- if (itemAtLevel != null)
- {
- HtmlToWmlConverterCore.NumberedItemAnnotation thisLevelNia = itemAtLevel.Annotation<HtmlToWmlConverterCore.NumberedItemAnnotation>();
- string thisLevelNumFmt = thisLevelNia.listStyleType;
- if (thisLevelNumFmt == "lower-alpha" || thisLevelNumFmt == "lower-latin")
- {
- numFmt[i] = "lowerLetter";
- //just[i] = "left";
- }
- if (thisLevelNumFmt == "upper-alpha" || thisLevelNumFmt == "upper-latin")
- {
- numFmt[i] = "upperLetter";
- //just[i] = "left";
- }
- if (thisLevelNumFmt == "decimal-leading-zero")
- {
- numFmt[i] = "decimalZero";
- //just[i] = "left";
- }
- if (thisLevelNumFmt == "lower-roman")
- {
- numFmt[i] = "lowerRoman";
- just[i] = "right";
- }
- if (thisLevelNumFmt == "upper-roman")
- {
- numFmt[i] = "upperRoman";
- just[i] = "right";
- }
- }
- }
- XElement simpleNumAbstract = XElement.Parse(String.Format(OrderedListAbstractXml, currentAbstractId++,
- numFmt[0], just[0], numFmt[1], just[1], numFmt[2], just[2], numFmt[3], just[3], numFmt[4], just[4], numFmt[5], just[5], numFmt[6], just[6], numFmt[7], just[7], numFmt[8], just[8]));
- numberingXDoc.Root.Add(simpleNumAbstract);
- }
- }
- }
- foreach (var list in numToAbstractNum)
- {
- numberingXDoc.Root.Add(
- new XElement(W.num, new XAttribute(W.numId, list.Key),
- new XElement(W.abstractNumId, new XAttribute(W.val, list.Value))));
- }
- wDoc.MainDocumentPart.NumberingDefinitionsPart.PutXDocument();
- #if false
- <w:num w:numId='1'>
- <w:abstractNumId w:val='0'/>
- </w:num>
- #endif
- }
- }
- class StylesUpdater
- {
- public static void UpdateStylesPart(
- WordprocessingDocument wDoc,
- XElement html,
- HtmlToWmlConverterSettings settings,
- CssDocument defaultCssDoc,
- CssDocument authorCssDoc,
- CssDocument userCssDoc)
- {
- XDocument styleXDoc = wDoc.MainDocumentPart.StyleDefinitionsPart.GetXDocument();
- if (settings.DefaultSpacingElement != null)
- {
- XElement spacingElement = styleXDoc.Root.Elements(W.docDefaults).Elements(W.pPrDefault).Elements(W.pPr).Elements(W.spacing).FirstOrDefault();
- if (spacingElement != null)
- spacingElement.ReplaceWith(settings.DefaultSpacingElement);
- }
- var classes = html
- .DescendantsAndSelf()
- .Where(d => d.Attribute(XhtmlNoNamespace._class) != null && ((string)d.Attribute(XhtmlNoNamespace._class)).Split().Length == 1)
- .Select(d => (string)d.Attribute(XhtmlNoNamespace._class));
- foreach (var item in classes)
- {
- //string item = "ms-rteStyle-Byline";
- foreach (var ruleSet in authorCssDoc.RuleSets)
- {
- var selector = ruleSet.Selectors.Where(
- sel =>
- {
- bool found = sel.SimpleSelectors.Count() == 1 &&
- sel.SimpleSelectors.First().Class == item &&
- (sel.SimpleSelectors.First().ElementName == "" ||
- sel.SimpleSelectors.First().ElementName == null);
- return found;
- }).FirstOrDefault();
- var color = ruleSet.Declarations.FirstOrDefault(d => d.Name == "color");
- if (selector != null)
- {
- //Console.WriteLine("found ruleset and selector for {0}", item);
- string styleName = item.ToLower();
- XElement newStyle = new XElement(W.style,
- new XAttribute(W.type, "paragraph"),
- new XAttribute(W.customStyle, "1"),
- new XAttribute(W.styleId, styleName),
- new XElement(W.name, new XAttribute(W.val, styleName)),
- new XElement(W.basedOn, new XAttribute(W.val, "Normal")),
- new XElement(W.pPr,
- new XElement(W.spacing, new XAttribute(W.before, "100"),
- new XAttribute(W.beforeAutospacing, "1"),
- new XAttribute(W.after, "100"),
- new XAttribute(W.afterAutospacing, "1"),
- new XAttribute(W.line, "240"),
- new XAttribute(W.lineRule, "auto"))),
- new XElement(W.rPr,
- new XElement(W.rFonts, new XAttribute(W.ascii, "Times New Roman"),
- new XAttribute(W.eastAsiaTheme, "minorEastAsia"),
- new XAttribute(W.hAnsi, "Times New Roman"),
- new XAttribute(W.cs, "Times New Roman")),
- color != null ? new XElement(W.color, new XAttribute(W.val, "this should be a color")) : null,
- new XElement(W.sz, new XAttribute(W.val, "24")),
- new XElement(W.szCs, new XAttribute(W.val, "24"))));
- if (styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && ((string)e.Attribute(W.styleId)).ToLower() == styleName)
- .FirstOrDefault() == null)
- styleXDoc.Root.Add(newStyle);
- }
- }
- }
- if (html.Descendants(XhtmlNoNamespace.h1).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading1")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading1'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 1'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading1Char'/>
- <w:uiPriority w:val='9'/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='480'
- w:after='0'/>
- <w:outlineLvl w:val='0'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='365F91'
- w:themeColor='accent1'
- w:themeShade='BF'/>
- <w:sz w:val='28'/>
- <w:szCs w:val='28'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h2).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading2")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading2'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 2'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading2Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='1'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- <w:sz w:val='26'/>
- <w:szCs w:val='26'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h3).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading3")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading3'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 3'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading3Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='2'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h4).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading4")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading4'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 4'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading4Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='3'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h5).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading5")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading5'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 5'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading5Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='4'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:color w:val='243F60'
- w:themeColor='accent1'
- w:themeShade='7F'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h6).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading6")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading6'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 6'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading6Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='5'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='243F60'
- w:themeColor='accent1'
- w:themeShade='7F'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h7).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading7")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading7'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 7'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading7Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='6'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h8).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading8")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading8'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 8'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading8Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='7'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- <w:sz w:val='20'/>
- <w:szCs w:val='20'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h9).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "Heading9")
- .FirstOrDefault(),
- @"<w:style w:type='paragraph'
- w:styleId='Heading9'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='heading 9'/>
- <w:basedOn w:val='Normal'/>
- <w:next w:val='Normal'/>
- <w:link w:val='Heading9Char'/>
- <w:uiPriority w:val='9'/>
- <w:unhideWhenUsed/>
- <w:qFormat/>
- <w:pPr>
- <w:keepNext/>
- <w:keepLines/>
- <w:spacing w:before='200'
- w:after='0'/>
- <w:outlineLvl w:val='8'/>
- </w:pPr>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- <w:sz w:val='20'/>
- <w:szCs w:val='20'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h1).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading1Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading1Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 1 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading1'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='365F91'
- w:themeColor='accent1'
- w:themeShade='BF'/>
- <w:sz w:val='28'/>
- <w:szCs w:val='28'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h2).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading2Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading2Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 2 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading2'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- <w:sz w:val='26'/>
- <w:szCs w:val='26'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h3).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading3Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading3Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 3 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading3'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h4).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading4Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading4Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 4 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading4'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:b/>
- <w:bCs/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='4F81BD'
- w:themeColor='accent1'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h5).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading5Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading5Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 5 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading5'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:color w:val='243F60'
- w:themeColor='accent1'
- w:themeShade='7F'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h6).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading6Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading6Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 6 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading6'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='243F60'
- w:themeColor='accent1'
- w:themeShade='7F'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h7).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading7Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading7Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 7 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading7'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h8).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading8Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading8Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 8 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading8'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- <w:sz w:val='20'/>
- <w:szCs w:val='20'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.h9).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Heading9Char")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:customStyle='1'
- w:styleId='Heading9Char'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Heading 9 Char'/>
- <w:basedOn w:val='DefaultParagraphFont'/>
- <w:link w:val='Heading9'/>
- <w:uiPriority w:val='9'/>
- <w:rPr>
- <w:rFonts w:asciiTheme='majorHAnsi'
- w:eastAsiaTheme='majorEastAsia'
- w:hAnsiTheme='majorHAnsi'
- w:cstheme='majorBidi'/>
- <w:i/>
- <w:iCs/>
- <w:color w:val='404040'
- w:themeColor='text1'
- w:themeTint='BF'/>
- <w:sz w:val='20'/>
- <w:szCs w:val='20'/>
- </w:rPr>
- </w:style>");
- if (html.Descendants(XhtmlNoNamespace.a).Any())
- PtUtils.AddElementIfMissing(styleXDoc,
- styleXDoc
- .Root
- .Elements(W.style)
- .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Hyperlink")
- .FirstOrDefault(),
- @"<w:style w:type='character'
- w:styleId='Hyperlink'
- xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
- <w:name w:val='Hyperlink' />
- <w:basedOn w:val='DefaultParagraphFont' />
- <w:uiPriority w:val='99' />
- <w:semiHidden />
- <w:unhideWhenUsed />
- <w:rPr>
- <w:color w:val='0000FF' />
- <w:u w:val='single' />
- </w:rPr>
- </w:style>");
- wDoc.MainDocumentPart.StyleDefinitionsPart.PutXDocument();
- }
- }
- class ThemeUpdater
- {
- public static void UpdateThemePart(WordprocessingDocument wDoc, XElement html, HtmlToWmlConverterSettings settings)
- {
- XDocument themeXDoc = wDoc.MainDocumentPart.ThemePart.GetXDocument();
- CssExpression minorFont = html.Descendants(XhtmlNoNamespace.body).FirstOrDefault().GetProp("font-family");
- XElement majorFontElement = html.Descendants().Where(e =>
- e.Name == XhtmlNoNamespace.h1 ||
- e.Name == XhtmlNoNamespace.h2 ||
- e.Name == XhtmlNoNamespace.h3 ||
- e.Name == XhtmlNoNamespace.h4 ||
- e.Name == XhtmlNoNamespace.h5 ||
- e.Name == XhtmlNoNamespace.h6 ||
- e.Name == XhtmlNoNamespace.h7 ||
- e.Name == XhtmlNoNamespace.h8 ||
- e.Name == XhtmlNoNamespace.h9).FirstOrDefault();
- CssExpression majorFont = null;
- if (majorFontElement != null)
- majorFont = majorFontElement.GetProp("font-family");
- XAttribute majorTypeface = themeXDoc
- .Root
- .Elements(A.themeElements)
- .Elements(A.fontScheme)
- .Elements(A.majorFont)
- .Elements(A.latin)
- .Attributes(NoNamespace.typeface)
- .FirstOrDefault();
- if (majorTypeface != null && majorFont != null)
- {
- CssTerm term = majorFont.Terms.FirstOrDefault();
- if (term != null)
- majorTypeface.Value = term.Value;
- }
- XAttribute minorTypeface = themeXDoc
- .Root
- .Elements(A.themeElements)
- .Elements(A.fontScheme)
- .Elements(A.minorFont)
- .Elements(A.latin)
- .Attributes(NoNamespace.typeface)
- .FirstOrDefault();
- if (minorTypeface != null && minorFont != null)
- {
- CssTerm term = minorFont.Terms.FirstOrDefault();
- if (term != null)
- minorTypeface.Value = term.Value;
- }
- wDoc.MainDocumentPart.ThemePart.PutXDocument();
- }
- }
- }
|