1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- //
- // Purpose: Chart graphic class is used for drawing Chart
- // elements as Rectangles, Pie slices, lines, areas
- // etc. This class is used in all classes where
- // drawing is necessary. The GDI+ graphic class is
- // used throw this class. Encapsulates a GDI+ chart
- // drawing functionality
- //
- using System;
- using System.Windows.Forms;
- using System.Diagnostics.CodeAnalysis;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Drawing.Imaging;
- using FastReport.DataVisualization.Charting.Borders3D;
- using FastReport.DataVisualization.Charting.Utilities;
- namespace FastReport.DataVisualization.Charting
- {
- using Size = System.Drawing.Size;
- #region Enumerations
- /// <summary>
- /// Defines the style how the bars/columns are drawn.
- /// </summary>
- internal enum BarDrawingStyle
- {
- /// <summary>
- /// Default bar/column style.
- /// </summary>
- Default,
- /// <summary>
- /// Cylinder bar/column style.
- /// </summary>
- Cylinder,
- /// <summary>
- /// Emboss bar/column style.
- /// </summary>
- Emboss,
- /// <summary>
- /// LightToDark bar/column style.
- /// </summary>
- LightToDark,
-
- /// <summary>
- /// Wedge bar/column style.
- /// </summary>
- Wedge,
- }
- /// <summary>
- /// Defines the style how the pie and doughnut charts are drawn.
- /// </summary>
- internal enum PieDrawingStyle
- {
- /// <summary>
- /// Default pie/doughnut drawing style.
- /// </summary>
- Default,
- /// <summary>
- /// Soft edge shadow is drawn on the edges of the pie/doughnut slices.
- /// </summary>
- SoftEdge,
- /// <summary>
- /// A shadow is drawn from the top to the bottom of the pie/doughnut chart.
- /// </summary>
- Concave,
- }
- /// <summary>
- /// An enumeration of line styles.
- /// </summary>
- public enum ChartDashStyle
- {
- /// <summary>
- /// Line style not set
- /// </summary>
- NotSet,
- /// <summary>
- /// Specifies a line consisting of dashes.
- /// </summary>
- Dash,
- /// <summary>
- /// Specifies a line consisting of a repeating pattern of dash-dot.
- /// </summary>
- DashDot,
- /// <summary>
- /// Specifies a line consisting of a repeating pattern of dash-dot-dot.
- /// </summary>
- DashDotDot,
- /// <summary>
- /// Specifies a line consisting of dots.
- /// </summary>
- Dot,
- /// <summary>
- /// Specifies a solid line.
- /// </summary>
- Solid,
- }
- #endregion
- /// <summary>
- /// The ChartGraphics class provides all chart drawing capabilities.
- /// It contains methods for drawing 2D primitives and also exposes
- /// all ChartGraphics3D class methods for 3D shapes. Only this
- /// class should be used for any drawing in the chart.
- /// </summary>
- public partial class ChartGraphics : ChartElement
- {
- #region Fields
- // Common Elements
- private CommonElements _common;
- // Reusable objects
- private Pen _pen;
- private SolidBrush _solidBrush;
- private Matrix _myMatrix;
-
- // Private fields which represents picture size
- private int _width;
- private int _height;
-
- // Indicates that smoothing is applied while drawing shadows
- internal bool softShadows = true;
- // Anti aliasing flags
- private AntiAliasingStyles _antiAliasing = AntiAliasingStyles.All;
- // True if rendering into the metafile
- internal bool IsMetafile = false;
- #endregion
- #region Lines Methods
- /// <summary>
- /// Draws a line connecting the two specified points.
- /// </summary>
- /// <param name="color">Line color.</param>
- /// <param name="width">Line width.</param>
- /// <param name="style">Line style.</param>
- /// <param name="firstPointF">A Point that represents the first point to connect.</param>
- /// <param name="secondPointF">A Point that represents the second point to connect.</param>
- internal void DrawLineRel(
- Color color,
- int width,
- ChartDashStyle style,
- PointF firstPointF,
- PointF secondPointF
- )
- {
- DrawLineAbs(
- color,
- width,
- style,
- GetAbsolutePoint(firstPointF),
- GetAbsolutePoint(secondPointF) );
- }
- /// <summary>
- /// Draws a line connecting the two specified points using absolute coordinates.
- /// </summary>
- /// <param name="color">Line color.</param>
- /// <param name="width">Line width.</param>
- /// <param name="style">Line style.</param>
- /// <param name="firstPoint">A Point that represents the first point to connect.</param>
- /// <param name="secondPoint">A Point that represents the second point to connect.</param>
- internal void DrawLineAbs(
- Color color,
- int width,
- ChartDashStyle style,
- PointF firstPoint,
- PointF secondPoint
- )
- {
- // Do not draw line if width is 0 or style not set
- if( width == 0 || style == ChartDashStyle.NotSet )
- {
- return;
- }
- // Set a line color
- if(_pen.Color != color)
- {
- _pen.Color = color;
- }
- // Set a line width
- if(_pen.Width != width)
- {
- _pen.Width = width;
- }
- // Set a line style
- if(_pen.DashStyle != GetPenStyle( style ))
- {
- _pen.DashStyle = GetPenStyle( style );
- }
- // Remember SmoothingMode and turn off anti aliasing for
- // vertical or horizontal lines usinig 1 pixel dashed pen.
- // This prevents anialiasing from completly smoothing the
- // dashed line.
- SmoothingMode oldSmoothingMode = this.SmoothingMode;
- if(width <= 1 && style != ChartDashStyle.Solid)
- {
- if(firstPoint.X == secondPoint.X ||
- firstPoint.Y == secondPoint.Y)
- {
- this.SmoothingMode = SmoothingMode.Default;
- }
- }
- // Draw a line
- this.DrawLine(_pen,
- (float)Math.Round(firstPoint.X),
- (float)Math.Round(firstPoint.Y),
- (float)Math.Round(secondPoint.X),
- (float)Math.Round(secondPoint.Y) );
- // Return old smoothing mode
- this.SmoothingMode = oldSmoothingMode;
- }
- /// <summary>
- /// Draws a line with shadow connecting the two specified points.
- /// </summary>
- /// <param name="color">Line color.</param>
- /// <param name="width">Line width.</param>
- /// <param name="style">Line style.</param>
- /// <param name="firstPoint">A Point that represents the first point to connect.</param>
- /// <param name="secondPoint">A Point that represents the second point to connect.</param>
- /// <param name="shadowColor">Shadow Color.</param>
- /// <param name="shadowOffset">Shadow Offset.</param>
- internal void DrawLineRel(
- Color color,
- int width,
- ChartDashStyle style,
- PointF firstPoint,
- PointF secondPoint,
- Color shadowColor,
- int shadowOffset
- )
- {
- DrawLineAbs(
- color,
- width,
- style,
- GetAbsolutePoint(firstPoint),
- GetAbsolutePoint(secondPoint),
- shadowColor,
- shadowOffset );
- }
- /// <summary>
- /// Draws a line with shadow connecting the two specified points.
- /// </summary>
- /// <param name="color">Line color.</param>
- /// <param name="width">Line width.</param>
- /// <param name="style">Line style.</param>
- /// <param name="firstPoint">A Point that represents the first point to connect.</param>
- /// <param name="secondPoint">A Point that represents the second point to connect.</param>
- /// <param name="shadowColor">Shadow Color.</param>
- /// <param name="shadowOffset">Shadow Offset.</param>
- internal void DrawLineAbs(
- Color color,
- int width,
- ChartDashStyle style,
- PointF firstPoint,
- PointF secondPoint,
- Color shadowColor,
- int shadowOffset
- )
- {
- if(shadowOffset != 0)
- {
- // Shadow color
- Color shColor;
- // Make shadow semi transparent
- // if alpha value not used
- if( shadowColor.A != 255 )
- shColor = shadowColor;
- else
- shColor = Color.FromArgb(color.A/2, shadowColor);
- // Set shadow line position
- PointF firstShadow = new PointF( firstPoint.X + shadowOffset, firstPoint.Y + shadowOffset);
- PointF secondShadow = new PointF( secondPoint.X + shadowOffset, secondPoint.Y + shadowOffset );
- // Draw Shadow of Line
- DrawLineAbs( shColor, width, style, firstShadow, secondShadow );
- }
- // Draw Line
- DrawLineAbs( color, width, style, firstPoint, secondPoint );
- }
- #endregion
- #region Pen and Brush Methods
- /// <summary>
- /// Creates a Hatch Brush.
- /// </summary>
- /// <param name="hatchStyle">Chart Hatch style.</param>
- /// <param name="backColor">Back Color.</param>
- /// <param name="foreColor">Fore Color.</param>
- /// <returns>Brush</returns>
- internal Brush GetHatchBrush(
- ChartHatchStyle hatchStyle,
- Color backColor,
- Color foreColor
- )
- {
- // Convert Chart Hatch Style enum
- // to Hatch Style enum.
- HatchStyle hatch;
- hatch = (HatchStyle)Enum.Parse(typeof(HatchStyle),hatchStyle.ToString());
-
- // Create Hatch Brush
- return new HatchBrush( hatch, foreColor, backColor );
- }
- /// <summary>
- /// Creates a textured brush.
- /// </summary>
- /// <param name="name">Image file name or URL.</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="mode">Wrap mode.</param>
- /// <param name="backColor">Image background color.</param>
- /// <returns>Textured brush.</returns>
- internal Brush GetTextureBrush(
- string name,
- Color backImageTransparentColor,
- ChartImageWrapMode mode,
- Color backColor
- )
- {
- // Load a image
- System.Drawing.Image image = _common.ImageLoader.LoadImage( name );
- // Create a brush
- ImageAttributes attrib = new ImageAttributes();
- attrib.SetWrapMode((mode == ChartImageWrapMode.Unscaled) ? WrapMode.Clamp : ((WrapMode)mode));
- if(backImageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(backImageTransparentColor, backImageTransparentColor, ColorAdjustType.Default);
- }
- // If image is a metafile background must be filled first
- // Solves issue that background is not cleared correctly
- if(backImageTransparentColor == Color.Empty &&
- image is Metafile &&
- backColor != Color.Transparent)
- {
- TextureBrush backFilledBrush = null;
- Bitmap bitmap = new Bitmap(image.Width, image.Height);
- using(Graphics graphics = System.Drawing.Graphics.FromImage(bitmap))
- {
- using(SolidBrush backBrush = new SolidBrush(backColor))
- {
- graphics.FillRectangle(backBrush, 0, 0, image.Width, image.Height);
- graphics.DrawImageUnscaled(image, 0, 0);
- backFilledBrush= new TextureBrush( bitmap, new RectangleF(0,0,image.Width,image.Height), attrib);
- }
- }
- return backFilledBrush;
- }
-
-
- TextureBrush textureBrush;
- if (ImageLoader.DoDpisMatch(image, this.Graphics))
- textureBrush = new TextureBrush(image, new RectangleF(0, 0, image.Width, image.Height), attrib);
- else // if the image dpi does not match the graphics dpi we have to scale the image
- {
- Image scaledImage = ImageLoader.GetScaledImage(image, this.Graphics);
- textureBrush = new TextureBrush(scaledImage, new RectangleF(0, 0, scaledImage.Width, scaledImage.Height), attrib);
- scaledImage.Dispose();
- }
-
- return textureBrush;
- }
-
- /// <summary>
- /// This method creates a gradient brush.
- /// </summary>
- /// <param name="rectangle">A rectangle which has to be filled with a gradient color.</param>
- /// <param name="firstColor">First color.</param>
- /// <param name="secondColor">Second color.</param>
- /// <param name="type ">Gradient type .</param>
- /// <returns>Gradient Brush</returns>
- internal Brush GetGradientBrush(
- RectangleF rectangle,
- Color firstColor,
- Color secondColor,
- GradientStyle type
- )
- {
- // Increse the brush rectangle by 1 pixel to ensure the fit
- rectangle.Inflate(1f, 1f);
- Brush gradientBrush = null;
- float angle = 0;
- // Function which create gradient brush fires exception if
- // rectangle size is zero.
- if( rectangle.Height == 0 || rectangle.Width == 0 )
- {
- gradientBrush = new SolidBrush( Color.Black );
- return gradientBrush;
- }
- // *******************************************
- // Linear Gradient
- // *******************************************
- // Check linear type .
- if( type == GradientStyle.LeftRight || type == GradientStyle.VerticalCenter )
- {
- angle = 0;
- }
- else if( type == GradientStyle.TopBottom || type == GradientStyle.HorizontalCenter )
- {
- angle = 90;
- }
- else if( type == GradientStyle.DiagonalLeft )
- {
- angle = (float)(Math.Atan(rectangle.Width / rectangle.Height)* 180 / Math.PI);
- }
- else if( type == GradientStyle.DiagonalRight )
- {
- angle = (float)(180 - Math.Atan(rectangle.Width / rectangle.Height)* 180 / Math.PI);
- }
-
- // Create a linear gradient brush
- if( type == GradientStyle.TopBottom || type == GradientStyle.LeftRight
- || type == GradientStyle.DiagonalLeft || type == GradientStyle.DiagonalRight
- || type == GradientStyle.HorizontalCenter || type == GradientStyle.VerticalCenter )
- {
- RectangleF tempRect = new RectangleF(rectangle.X,rectangle.Y,rectangle.Width,rectangle.Height);
- // For Horizontal and vertical center gradient types
- if( type == GradientStyle.HorizontalCenter )
- {
- // Resize and wrap gradient
- tempRect.Height = tempRect.Height / 2F;
- LinearGradientBrush linearGradientBrush = new LinearGradientBrush(tempRect, firstColor, secondColor, angle);
- gradientBrush = linearGradientBrush;
- linearGradientBrush.WrapMode = WrapMode.TileFlipX;
- }
- else if( type == GradientStyle.VerticalCenter )
- {
- // Resize and wrap gradient
- tempRect.Width = tempRect.Width / 2F;
- LinearGradientBrush linearGradientBrush = new LinearGradientBrush(tempRect, firstColor, secondColor, angle);
- gradientBrush = linearGradientBrush;
- linearGradientBrush.WrapMode = WrapMode.TileFlipX;
- }
- else
- {
- gradientBrush = new LinearGradientBrush( rectangle, firstColor, secondColor, angle );
- }
- return gradientBrush;
- }
- // *******************************************
- // Gradient is not linear : From Center.
- // *******************************************
-
- // Create a path
- GraphicsPath path = new GraphicsPath();
- // Add a rectangle to the path
- path.AddRectangle( rectangle );
- // Create a gradient brush
- PathGradientBrush pathGradientBrush = new PathGradientBrush(path);
- gradientBrush = pathGradientBrush;
- // Set the center color
- pathGradientBrush.CenterColor = firstColor;
- // Set the Surround color
- Color[] colors = {secondColor};
- pathGradientBrush.SurroundColors = colors;
-
- if( path != null )
- {
- path.Dispose();
- }
- return gradientBrush;
- }
- /// <summary>
- /// This method creates a gradient brush for pie. This gradient is one
- /// of the types used only with pie and doughnut.
- /// </summary>
- /// <param name="rectangle">A rectangle which has to be filled with a gradient color</param>
- /// <param name="firstColor">First color</param>
- /// <param name="secondColor">Second color</param>
- /// <returns>Gradient Brush</returns>
- internal Brush GetPieGradientBrush(
- RectangleF rectangle,
- Color firstColor,
- Color secondColor
- )
- {
- // Create a path that consists of a single ellipse.
- GraphicsPath path = new GraphicsPath();
- path.AddEllipse( rectangle );
- // Use the path to construct a brush.
- PathGradientBrush gradientBrush = new PathGradientBrush(path);
- // Set the color at the center of the path.
- gradientBrush.CenterColor = firstColor;
- // Set the color along the entire boundary
- // of the path to aqua.
- Color[] colors = {secondColor};
- gradientBrush.SurroundColors = colors;
- if( path != null )
- {
- path.Dispose();
- }
- return gradientBrush;
- }
- /// <summary>
- /// Converts GDI+ line style to Chart Graph line style.
- /// </summary>
- /// <param name="style">Chart Line style.</param>
- /// <returns>GDI+ line style.</returns>
- internal DashStyle GetPenStyle( ChartDashStyle style )
- {
- // Convert to chart line styles. The custom style doesn’t exist.
- switch( style )
- {
- case ChartDashStyle.Dash:
- return DashStyle.Dash;
- case ChartDashStyle.DashDot:
- return DashStyle.DashDot;
- case ChartDashStyle.DashDotDot:
- return DashStyle.DashDotDot;
- case ChartDashStyle.Dot:
- return DashStyle.Dot;
- }
- return DashStyle.Solid;
- }
- #endregion
- #region Markers
- /// <summary>
- /// Creates polygon for multi-corner star marker.
- /// </summary>
- /// <param name="rect">Marker rectangle.</param>
- /// <param name="numberOfCorners">Number of corners (4 and up).</param>
- /// <returns>Array of points.</returns>
- internal PointF[] CreateStarPolygon(RectangleF rect, int numberOfCorners)
- {
- int numberOfCornersX2;
- checked
- {
- numberOfCornersX2 = numberOfCorners * 2;
- }
- bool outside = true;
- PointF[] points = new PointF[numberOfCornersX2];
- PointF[] tempPoints = new PointF[1];
- // overflow check
- for (int pointIndex = 0; pointIndex < numberOfCornersX2; pointIndex++)
- {
- tempPoints[0] = new PointF(rect.X + rect.Width/2f, (outside == true) ? rect.Y : rect.Y + rect.Height/4f);
- Matrix matrix = new Matrix();
- matrix.RotateAt(pointIndex*(360f/(numberOfCorners*2f)), new PointF(rect.X + rect.Width/2f, rect.Y + rect.Height/2f));
- matrix.TransformPoints(tempPoints);
- points[pointIndex] = tempPoints[0];
- outside = !outside;
- }
- return points;
- }
- /// <summary>
- /// Draw marker using relative coordinates of the center.
- /// </summary>
- /// <param name="point">Coordinates of the center.</param>
- /// <param name="markerStyle">Marker style.</param>
- /// <param name="markerSize">Marker size.</param>
- /// <param name="markerColor">Marker color.</param>
- /// <param name="markerBorderColor">Marker border color.</param>
- /// <param name="markerBorderSize">Marker border size.</param>
- /// <param name="markerImage">Marker image name.</param>
- /// <param name="markerImageTransparentColor">Marker image transparent color.</param>
- /// <param name="shadowSize">Marker shadow size.</param>
- /// <param name="shadowColor">Marker shadow color.</param>
- /// <param name="imageScaleRect">Rectangle to which marker image should be scaled.</param>
- internal void DrawMarkerRel(
- PointF point,
- MarkerStyle markerStyle,
- int markerSize,
- Color markerColor,
- Color markerBorderColor,
- int markerBorderSize,
- string markerImage,
- Color markerImageTransparentColor,
- int shadowSize,
- Color shadowColor,
- RectangleF imageScaleRect
- )
- {
- DrawMarkerAbs(this.GetAbsolutePoint(point), markerStyle, markerSize, markerColor, markerBorderColor, markerBorderSize, markerImage, markerImageTransparentColor, shadowSize, shadowColor, imageScaleRect, false);
- }
- /// <summary>
- /// Draw marker using absolute coordinates of the center.
- /// </summary>
- /// <param name="point">Coordinates of the center.</param>
- /// <param name="markerStyle">Marker style.</param>
- /// <param name="markerSize">Marker size.</param>
- /// <param name="markerColor">Marker color.</param>
- /// <param name="markerBorderColor">Marker border color.</param>
- /// <param name="markerBorderSize">Marker border size.</param>
- /// <param name="markerImage">Marker image name.</param>
- /// <param name="markerImageTransparentColor">Marker image transparent color.</param>
- /// <param name="shadowSize">Marker shadow size.</param>
- /// <param name="shadowColor">Marker shadow color.</param>
- /// <param name="imageScaleRect">Rectangle to which marker image should be scaled.</param>
- /// <param name="forceAntiAlias">Always use anti aliasing when drawing the marker.</param>
- internal void DrawMarkerAbs(
- PointF point,
- MarkerStyle markerStyle,
- int markerSize,
- Color markerColor,
- Color markerBorderColor,
- int markerBorderSize,
- string markerImage,
- Color markerImageTransparentColor,
- int shadowSize,
- Color shadowColor,
- RectangleF imageScaleRect,
- bool forceAntiAlias
- )
- {
- // Hide border when zero width specified
- if(markerBorderSize <= 0)
- {
- markerBorderColor = Color.Transparent;
- }
- // Draw image instead of standart markers
- if(markerImage.Length > 0)
- {
- // Get image
- System.Drawing.Image image = _common.ImageLoader.LoadImage( markerImage );
- if (image != null)
- {
- // Calculate image rectangle
- RectangleF rect = RectangleF.Empty;
- if (imageScaleRect == RectangleF.Empty)
- {
- SizeF size = new SizeF();
- ImageLoader.GetAdjustedImageSize(image, this.Graphics, ref size);
- imageScaleRect.Width = size.Width;
- imageScaleRect.Height = size.Height;
- }
- rect.X = point.X - imageScaleRect.Width / 2F;
- rect.Y = point.Y - imageScaleRect.Height / 2F;
- rect.Width = imageScaleRect.Width;
- rect.Height = imageScaleRect.Height;
- // Prepare image properties (transparent color)
- ImageAttributes attrib = new ImageAttributes();
- if (markerImageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(markerImageTransparentColor, markerImageTransparentColor, ColorAdjustType.Default);
- }
- // Draw image shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- ImageAttributes attribShadow = new ImageAttributes();
- attribShadow.SetColorKey(markerImageTransparentColor, markerImageTransparentColor, ColorAdjustType.Default);
- ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.Matrix00 = 0.25f; // Red
- colorMatrix.Matrix11 = 0.25f; // Green
- colorMatrix.Matrix22 = 0.25f; // Blue
- colorMatrix.Matrix33 = 0.5f; // alpha
- colorMatrix.Matrix44 = 1.0f; // w
- attribShadow.SetColorMatrix(colorMatrix);
- this.DrawImage(image,
- new Rectangle((int)rect.X + shadowSize, (int)rect.Y + shadowSize, (int)rect.Width, (int)rect.Height),
- 0, 0, image.Width, image.Height,
- GraphicsUnit.Pixel,
- attribShadow);
- }
- // Draw image
- this.DrawImage(image,
- new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height),
- 0, 0, image.Width, image.Height,
- GraphicsUnit.Pixel,
- attrib);
- }
- }
- // Draw standart marker using style, size and color
- else if(markerStyle != MarkerStyle.None && markerSize > 0 && markerColor != Color.Empty)
- {
- // Enable antialising
- SmoothingMode oldSmoothingMode = this.SmoothingMode;
- if(forceAntiAlias)
- {
- this.SmoothingMode = SmoothingMode.AntiAlias;
- }
-
- // Create solid color brush
- using (SolidBrush brush = new SolidBrush(markerColor))
- {
- // Calculate marker rectangle
- RectangleF rect = RectangleF.Empty;
- rect.X = point.X - ((float)markerSize) / 2F;
- rect.Y = point.Y - ((float)markerSize) / 2F;
- rect.Width = markerSize;
- rect.Height = markerSize;
- // Draw marker depending on style
- switch (markerStyle)
- {
- case (MarkerStyle.Star4):
- case (MarkerStyle.Star5):
- case (MarkerStyle.Star6):
- case (MarkerStyle.Star10):
- {
- // Set number of corners
- int cornerNumber = 4;
- if (markerStyle == MarkerStyle.Star5)
- {
- cornerNumber = 5;
- }
- else if (markerStyle == MarkerStyle.Star6)
- {
- cornerNumber = 6;
- }
- else if (markerStyle == MarkerStyle.Star10)
- {
- cornerNumber = 10;
- }
- // Get star polygon
- PointF[] points = CreateStarPolygon(rect, cornerNumber);
- // Draw shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- Matrix translateMatrix = this.Transform.Clone();
- translateMatrix.Translate(shadowSize, shadowSize);
- Matrix oldMatrix = this.Transform;
- this.Transform = translateMatrix;
- this.FillPolygon(new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(markerColor.A / 2, shadowColor)), points);
- this.Transform = oldMatrix;
- }
- // Draw star
- this.FillPolygon(brush, points);
- this.DrawPolygon(new Pen(markerBorderColor, markerBorderSize), points);
- break;
- }
- case (MarkerStyle.Circle):
- {
- // Draw marker shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- if (!softShadows)
- {
- using (SolidBrush shadowBrush = new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(markerColor.A / 2, shadowColor)))
- {
- RectangleF shadowRect = rect;
- shadowRect.X += shadowSize;
- shadowRect.Y += shadowSize;
- this.FillEllipse(shadowBrush, shadowRect);
- }
- }
- else
- {
- // Add circle to the graphics path
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddEllipse(rect.X + shadowSize - 1, rect.Y + shadowSize - 1, rect.Width + 2, rect.Height + 2);
- // Create path brush
- using (PathGradientBrush shadowBrush = new PathGradientBrush(path))
- {
- shadowBrush.CenterColor = shadowColor;
- // Set the color along the entire boundary of the path
- Color[] colors = { Color.Transparent };
- shadowBrush.SurroundColors = colors;
- shadowBrush.CenterPoint = new PointF(point.X, point.Y);
- // Define brush focus scale
- PointF focusScale = new PointF(1 - 2f * shadowSize / rect.Width, 1 - 2f * shadowSize / rect.Height);
- if (focusScale.X < 0)
- {
- focusScale.X = 0;
- }
- if (focusScale.Y < 0)
- {
- focusScale.Y = 0;
- }
- shadowBrush.FocusScales = focusScale;
- // Draw shadow
- this.FillPath(shadowBrush, path);
- }
- }
- }
- }
- this.FillEllipse(brush, rect);
- this.DrawEllipse(new Pen(markerBorderColor, markerBorderSize), rect);
- break;
- }
- case (MarkerStyle.Square):
- {
- // Draw marker shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- FillRectangleShadowAbs(rect, shadowColor, shadowSize, shadowColor);
- }
- this.FillRectangle(brush, rect);
- this.DrawRectangle(new Pen(markerBorderColor, markerBorderSize), (int)Math.Round(rect.X, 0), (int)Math.Round(rect.Y, 0), (int)Math.Round(rect.Width, 0), (int)Math.Round(rect.Height, 0));
- break;
- }
- case (MarkerStyle.Cross):
- {
- // Calculate cross line width and size
- float crossLineWidth = (float)Math.Ceiling(markerSize / 4F);
- float crossSize = markerSize;// * (float)Math.Sin(45f/180f*Math.PI);
- // Calculate cross coordinates
- PointF[] points = new PointF[12];
- points[0].X = point.X - crossSize / 2F;
- points[0].Y = point.Y + crossLineWidth / 2F;
- points[1].X = point.X - crossSize / 2F;
- points[1].Y = point.Y - crossLineWidth / 2F;
- points[2].X = point.X - crossLineWidth / 2F;
- points[2].Y = point.Y - crossLineWidth / 2F;
- points[3].X = point.X - crossLineWidth / 2F;
- points[3].Y = point.Y - crossSize / 2F;
- points[4].X = point.X + crossLineWidth / 2F;
- points[4].Y = point.Y - crossSize / 2F;
- points[5].X = point.X + crossLineWidth / 2F;
- points[5].Y = point.Y - crossLineWidth / 2F;
- points[6].X = point.X + crossSize / 2F;
- points[6].Y = point.Y - crossLineWidth / 2F;
- points[7].X = point.X + crossSize / 2F;
- points[7].Y = point.Y + crossLineWidth / 2F;
- points[8].X = point.X + crossLineWidth / 2F;
- points[8].Y = point.Y + crossLineWidth / 2F;
- points[9].X = point.X + crossLineWidth / 2F;
- points[9].Y = point.Y + crossSize / 2F;
- points[10].X = point.X - crossLineWidth / 2F;
- points[10].Y = point.Y + crossSize / 2F;
- points[11].X = point.X - crossLineWidth / 2F;
- points[11].Y = point.Y + crossLineWidth / 2F;
- // Rotate cross coordinates 45 degrees
- Matrix rotationMatrix = new Matrix();
- rotationMatrix.RotateAt(45, point);
- rotationMatrix.TransformPoints(points);
- // Draw shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- // Create translation matrix
- Matrix translateMatrix = this.Transform.Clone();
- translateMatrix.Translate(
- (softShadows) ? shadowSize + 1 : shadowSize,
- (softShadows) ? shadowSize + 1 : shadowSize);
- Matrix oldMatrix = this.Transform;
- this.Transform = translateMatrix;
- if (!softShadows)
- {
- using (Brush softShadowBrush = new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(markerColor.A / 2, shadowColor)))
- {
- this.FillPolygon(softShadowBrush, points);
- }
- }
- else
- {
- // Add polygon to the graphics path
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddPolygon(points);
- // Create path brush
- using (PathGradientBrush shadowBrush = new PathGradientBrush(path))
- {
- shadowBrush.CenterColor = shadowColor;
- // Set the color along the entire boundary of the path
- Color[] colors = { Color.Transparent };
- shadowBrush.SurroundColors = colors;
- shadowBrush.CenterPoint = new PointF(point.X, point.Y);
- // Define brush focus scale
- PointF focusScale = new PointF(1 - 2f * shadowSize / rect.Width, 1 - 2f * shadowSize / rect.Height);
- if (focusScale.X < 0)
- {
- focusScale.X = 0;
- }
- if (focusScale.Y < 0)
- {
- focusScale.Y = 0;
- }
- shadowBrush.FocusScales = focusScale;
- // Draw shadow
- this.FillPath(shadowBrush, path);
- }
- }
- }
- this.Transform = oldMatrix;
- }
- // Create translation matrix
- Matrix translateMatrixShape = this.Transform.Clone();
- Matrix oldMatrixShape = this.Transform;
- this.Transform = translateMatrixShape;
- this.FillPolygon(brush, points);
- this.DrawPolygon(new Pen(markerBorderColor, markerBorderSize), points);
- this.Transform = oldMatrixShape;
- break;
- }
- case (MarkerStyle.Diamond):
- {
- PointF[] points = new PointF[4];
- points[0].X = rect.X;
- points[0].Y = rect.Y + rect.Height / 2F;
- points[1].X = rect.X + rect.Width / 2F;
- points[1].Y = rect.Top;
- points[2].X = rect.Right;
- points[2].Y = rect.Y + rect.Height / 2F;
- points[3].X = rect.X + rect.Width / 2F;
- points[3].Y = rect.Bottom;
- // Draw shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- Matrix translateMatrix = this.Transform.Clone();
- translateMatrix.Translate((softShadows) ? 0 : shadowSize,
- (softShadows) ? 0 : shadowSize);
- Matrix oldMatrix = this.Transform;
- this.Transform = translateMatrix;
- if (!softShadows)
- {
- using (Brush softShadowBrush = new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(markerColor.A / 2, shadowColor)))
- {
- this.FillPolygon(softShadowBrush, points);
- }
- }
- else
- {
- // Calculate diamond size
- float diamondSize = markerSize * (float)Math.Sin(45f / 180f * Math.PI);
- // Calculate diamond rectangle position
- RectangleF diamondRect = RectangleF.Empty;
- diamondRect.X = point.X - ((float)diamondSize) / 2F;
- diamondRect.Y = point.Y - ((float)diamondSize) / 2F - shadowSize;
- diamondRect.Width = diamondSize;
- diamondRect.Height = diamondSize;
- // Set rotation matrix to 45
- translateMatrix.RotateAt(45, point);
- this.Transform = translateMatrix;
- FillRectangleShadowAbs(diamondRect, shadowColor, shadowSize, shadowColor);
- }
- this.Transform = oldMatrix;
- }
- this.FillPolygon(brush, points);
- this.DrawPolygon(new Pen(markerBorderColor, markerBorderSize), points);
- break;
- }
- case (MarkerStyle.Triangle):
- {
- PointF[] points = new PointF[3];
- points[0].X = rect.X;
- points[0].Y = rect.Bottom;
- points[1].X = rect.X + rect.Width / 2F;
- points[1].Y = rect.Top;
- points[2].X = rect.Right;
- points[2].Y = rect.Bottom;
- // Draw image shadow
- if (shadowSize != 0 && shadowColor != Color.Empty)
- {
- Matrix translateMatrix = this.Transform.Clone();
- translateMatrix.Translate((softShadows) ? shadowSize - 1 : shadowSize,
- (softShadows) ? shadowSize + 1 : shadowSize);
- Matrix oldMatrix = this.Transform;
- this.Transform = translateMatrix;
- if (!softShadows)
- {
- using (Brush softShadowBrush = new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(markerColor.A / 2, shadowColor)))
- {
- this.FillPolygon(softShadowBrush, points);
- }
- }
- else
- {
- // Add polygon to the graphics path
- GraphicsPath path = new GraphicsPath();
- path.AddPolygon(points);
- // Create path brush
- PathGradientBrush shadowBrush = new PathGradientBrush(path);
- shadowBrush.CenterColor = shadowColor;
- // Set the color along the entire boundary of the path
- Color[] colors = { Color.Transparent };
- shadowBrush.SurroundColors = colors;
- shadowBrush.CenterPoint = new PointF(point.X, point.Y);
- // Define brush focus scale
- PointF focusScale = new PointF(1 - 2f * shadowSize / rect.Width, 1 - 2f * shadowSize / rect.Height);
- if (focusScale.X < 0)
- {
- focusScale.X = 0;
- }
- if (focusScale.Y < 0)
- {
- focusScale.Y = 0;
- }
- shadowBrush.FocusScales = focusScale;
- // Draw shadow
- this.FillPath(shadowBrush, path);
- }
- this.Transform = oldMatrix;
- }
- this.FillPolygon(brush, points);
- this.DrawPolygon(new Pen(markerBorderColor, markerBorderSize), points);
- break;
- }
- default:
- {
- throw (new InvalidOperationException(SR.ExceptionGraphicsMarkerStyleUnknown));
- }
- }
- }
- // Restore SmoothingMode
- if(forceAntiAlias)
- {
- this.SmoothingMode = oldSmoothingMode;
- }
- }
- }
- #endregion
-
- #region String Methods
- /// <summary>
- /// Measures the specified string when drawn with the specified
- /// Font object and formatted with the specified StringFormat object.
- /// </summary>
- /// <param name="text">String to measure.</param>
- /// <param name="font">Font object defines the text format of the string.</param>
- /// <param name="layoutArea">SizeF structure that specifies the maximum layout area for the text.</param>
- /// <param name="stringFormat">StringFormat object that represents formatting information, such as line spacing, for the string.</param>
- /// <param name="textOrientation">Text orientation.</param>
- /// <returns>This method returns a SizeF structure that represents the size, in pixels, of the string specified in the text parameter as drawn with the font parameter and the stringFormat parameter.</returns>
- internal SizeF MeasureString(
- string text,
- Font font,
- SizeF layoutArea,
- StringFormat stringFormat,
- TextOrientation textOrientation
- )
- {
- // Current implementation of the stacked text will simply insert a new
- // line character between all characters in the original string. This
- // apporach will not allow to show multiple lines of stacked text or
- // correctly handle text wrapping.
- if (textOrientation == TextOrientation.Stacked)
- {
- text = GetStackedText(text);
- }
- return this.MeasureString(text, font, layoutArea, stringFormat);
- }
- /// <summary>
- /// Measures the specified text string when drawn with
- /// the specified Font object and formatted with the
- /// specified StringFormat object.
- /// </summary>
- /// <param name="text">The string to measure</param>
- /// <param name="font">The Font object used to determine the size of the text string. </param>
- /// <param name="layoutArea">A SizeF structure that specifies the layout rectangle for the text. </param>
- /// <param name="stringFormat">A StringFormat object that represents formatting information, such as line spacing, for the text string. </param>
- /// <param name="textOrientation">Text orientation.</param>
- /// <returns>A SizeF structure that represents the size of text as drawn with font.</returns>
- internal SizeF MeasureStringRel(
- string text,
- Font font,
- SizeF layoutArea,
- StringFormat stringFormat,
- TextOrientation textOrientation)
- {
- // Current implementation of the stacked text will simply insert a new
- // line character between all characters in the original string. This
- // apporach will not allow to show multiple lines of stacked text or
- // correctly handle text wrapping.
- if (textOrientation == TextOrientation.Stacked)
- {
- text = GetStackedText(text);
- }
- return this.MeasureStringRel(text, font, layoutArea, stringFormat);
- }
- /// <summary>
- /// Draws the specified text string at the specified location with the specified Brush and Font objects using the formatting properties of the specified StringFormat object.
- /// </summary>
- /// <param name="text">String to draw.</param>
- /// <param name="font">Font object that defines the text format of the string.</param>
- /// <param name="brush">Brush object that determines the color and texture of the drawn text.</param>
- /// <param name="rect">Position of the drawn text in pixels.</param>
- /// <param name="format">StringFormat object that specifies formatting properties, such as line spacing and alignment, that are applied to the drawn text.</param>
- /// <param name="textOrientation">Text orientation.</param>
- internal void DrawString(
- string text,
- Font font,
- Brush brush,
- RectangleF rect,
- StringFormat format,
- TextOrientation textOrientation
- )
- {
- // Current implementation of the stacked text will simply insert a new
- // line character between all characters in the original string. This
- // apporach will not allow to show multiple lines of stacked text or
- // correctly handle text wrapping.
- if (textOrientation == TextOrientation.Stacked)
- {
- text = GetStackedText(text);
- }
- this.DrawString(text, font, brush, rect, format);
- }
- /// <summary>
- /// Draw a string.
- /// </summary>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="position">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="angle">Text angle.</param>
- /// <param name="textOrientation">Text orientation.</param>
- internal void DrawStringRel(
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- PointF position,
- System.Drawing.StringFormat format,
- int angle,
- TextOrientation textOrientation
- )
- {
- // Current implementation of the stacked text will simply insert a new
- // line character between all characters in the original string. This
- // apporach will not allow to show multiple lines of stacked text or
- // correctly handle text wrapping.
- if (textOrientation == TextOrientation.Stacked)
- {
- text = GetStackedText(text);
- }
- this.DrawStringRel(text, font, brush, position, format, angle);
- }
- /// <summary>
- /// Draw a string.
- /// </summary>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="position">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="textOrientation">Text orientation.</param>
- internal void DrawStringRel(
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- RectangleF position,
- System.Drawing.StringFormat format,
- TextOrientation textOrientation
- )
- {
- // Current implementation of the stacked text will simply insert a new
- // line character between all characters in the original string. This
- // apporach will not allow to show multiple lines of stacked text or
- // correctly handle text wrapping.
- if (textOrientation == TextOrientation.Stacked)
- {
- text = GetStackedText(text);
- }
- this.DrawStringRel(text, font, brush, position, format);
- }
- /// <summary>
- /// Function returned stacked text by inserting new line characters between
- /// all characters in the original string.
- /// </summary>
- /// <param name="text">Original text.</param>
- /// <returns>Stacked text.</returns>
- internal static string GetStackedText(string text)
- {
- string result = string.Empty;
- foreach (char ch in text)
- {
- result += ch;
- if (ch != '\n')
- {
- result += '\n';
- }
- }
- return result;
- }
- /// <summary>
- /// Draw a string and fills it's background
- /// </summary>
- /// <param name="common">The Common elements object.</param>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="position">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="angle">Text angle.</param>
- /// <param name="backPosition">Text background position.</param>
- /// <param name="backColor">Back Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="series">Series</param>
- /// <param name="point">Point</param>
- /// <param name="pointIndex">Point index in series</param>
- internal void DrawPointLabelStringRel(
- CommonElements common,
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- RectangleF position,
- System.Drawing.StringFormat format,
- int angle,
- RectangleF backPosition,
- Color backColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Series series,
- DataPoint point,
- int pointIndex)
- {
- // Start Svg/Flash Selection mode
- this.StartHotRegion( point, true );
- // Draw background
- DrawPointLabelBackground(
- common,
- angle,
- PointF.Empty,
- backPosition,
- backColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- series,
- point,
- pointIndex);
- // End Svg/Flash Selection mode
- this.EndHotRegion( );
-
- point._lastLabelText = text;
- // Draw text
- if (IsRightToLeft)
- {
- // datapoint label alignments should appear as not RTL.
- using (StringFormat fmt = (StringFormat)format.Clone())
- {
- if (fmt.Alignment == StringAlignment.Far)
- {
- fmt.Alignment = StringAlignment.Near;
- }
- else if (fmt.Alignment == StringAlignment.Near)
- {
- fmt.Alignment = StringAlignment.Far;
- }
- DrawStringRel(text,font,brush,position,fmt,angle);
- }
- }
- else
- DrawStringRel(text, font, brush, position, format, angle);
- }
- /// <summary>
- /// Draw a string and fills it's background
- /// </summary>
- /// <param name="common">The Common elements object.</param>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="position">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="angle">Text angle.</param>
- /// <param name="backPosition">Text background position.</param>
- /// <param name="backColor">Back Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="series">Series</param>
- /// <param name="point">Point</param>
- /// <param name="pointIndex">Point index in series</param>
- internal void DrawPointLabelStringRel(
- CommonElements common,
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- PointF position,
- System.Drawing.StringFormat format,
- int angle,
- RectangleF backPosition,
- Color backColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Series series,
- DataPoint point,
- int pointIndex)
- {
- // Start Svg/Flash Selection mode
- this.StartHotRegion( point, true );
- // Draw background
- DrawPointLabelBackground(
- common,
- angle,
- position,
- backPosition,
- backColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- series,
- point,
- pointIndex);
- // End Svg/Flash Selection mode
- this.EndHotRegion( );
- point._lastLabelText = text;
- // Draw text
- if (IsRightToLeft)
- {
- // datapoint label alignments should appear as not RTL
- using (StringFormat fmt = (StringFormat)format.Clone())
- {
- if (fmt.Alignment == StringAlignment.Far)
- {
- fmt.Alignment = StringAlignment.Near;
- }
- else if (fmt.Alignment == StringAlignment.Near)
- {
- fmt.Alignment = StringAlignment.Far;
- }
- DrawStringRel(text,font,brush,position,fmt,angle);
- }
- }
- else
- DrawStringRel(text,font,brush,position,format,angle);
- }
- /// <summary>
- /// Draw a string and fills it's background
- /// </summary>
- /// <param name="common">The Common elements object.</param>
- /// <param name="angle">Text angle.</param>
- /// <param name="textPosition">Text position.</param>
- /// <param name="backPosition">Text background position.</param>
- /// <param name="backColor">Back Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="series">Series</param>
- /// <param name="point">Point</param>
- /// <param name="pointIndex">Point index in series</param>
- private void DrawPointLabelBackground(
- CommonElements common,
- int angle,
- PointF textPosition,
- RectangleF backPosition,
- Color backColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Series series,
- DataPoint point,
- int pointIndex)
- {
- // Draw background
- if(!backPosition.IsEmpty)
- {
- RectangleF backPositionAbs = this.Round(this.GetAbsoluteRectangle(backPosition));
- // Get rotation point
- PointF rotationPoint = PointF.Empty;
- if(textPosition.IsEmpty)
- {
- rotationPoint = new PointF(backPositionAbs.X + backPositionAbs.Width/2f, backPositionAbs.Y + backPositionAbs.Height/2f);
- }
- else
- {
- rotationPoint = this.GetAbsolutePoint(textPosition);
- }
- // Create a matrix and rotate it.
- _myMatrix = this.Transform.Clone();
- _myMatrix.RotateAt( angle, rotationPoint );
- // Save old state
- IGraphicsState graphicsState = this.Save();
- // Set transformatino
- this.Transform = _myMatrix;
- // Check for empty colors
- if( !backColor.IsEmpty ||
- !borderColor.IsEmpty)
- {
- // Fill box around the label
- using(Brush brush = new SolidBrush(backColor))
- {
- this.FillRectangle(brush, backPositionAbs);
- }
- // deliant: Fix VSTS #156433 (2) Data Label Border in core always shows when the style is set to NotSet
- // Draw box border
- if( borderWidth > 0 &&
- !borderColor.IsEmpty && borderDashStyle != ChartDashStyle.NotSet)
- {
- AntiAliasingStyles saveAntiAliasing = this.AntiAliasing;
- try
- {
- this.AntiAliasing = AntiAliasingStyles.None;
- using(Pen pen = new Pen(borderColor, borderWidth))
- {
- pen.DashStyle = GetPenStyle( borderDashStyle );
- this.DrawRectangle(
- pen,
- backPositionAbs.X,
- backPositionAbs.Y,
- backPositionAbs.Width,
- backPositionAbs.Height);
- }
- }
- finally
- {
- this.AntiAliasing = saveAntiAliasing;
- }
- }
- }
- else
- {
- // Draw invisible rectangle to handle tooltips
- using(Brush brush = new SolidBrush(Color.Transparent))
- {
- this.FillRectangle(brush, backPositionAbs);
- }
- }
-
- // Restore old state
- this.Restore(graphicsState);
- // Add point label hot region
- if( common != null &&
- common.ProcessModeRegions)
- {
- // Insert area
- if(angle == 0)
- {
- common.HotRegionsList.AddHotRegion(
- backPosition,
- point,
- series.Name,
- pointIndex );
- }
- else
- {
- // Convert rectangle to the graphics path and apply rotation transformation
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddRectangle(backPositionAbs);
- path.Transform(_myMatrix);
- // Add hot region
- common.HotRegionsList.AddHotRegion(
- path,
- false,
- this,
- point,
- series.Name,
- pointIndex);
- }
- }
- // Set new hot region element type
- if (common.HotRegionsList.List != null && common.HotRegionsList.List.Count > 0)
- {
- ((HotRegion)common.HotRegionsList.List[common.HotRegionsList.List.Count - 1]).Type =
- ChartElementType.DataPointLabel;
- }
- }
- }
- }
- /// <summary>
- /// Draw a string.
- /// </summary>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="position">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="angle">Text angle.</param>
- internal void DrawStringRel(
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- PointF position,
- System.Drawing.StringFormat format,
- int angle
- )
- {
- DrawStringAbs(
- text,
- font,
- brush,
- GetAbsolutePoint(position),
- format,
- angle);
- }
- /// <summary>
- /// Draw a string.
- /// </summary>
- /// <param name="text">Text.</param>
- /// <param name="font">Text Font.</param>
- /// <param name="brush">Text Brush.</param>
- /// <param name="absPosition">Text Position.</param>
- /// <param name="format">Format and text alignment.</param>
- /// <param name="angle">Text angle.</param>
- internal void DrawStringAbs(
- string text,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- PointF absPosition,
- System.Drawing.StringFormat format,
- int angle
- )
- {
- // Create a matrix and rotate it.
- _myMatrix = this.Transform.Clone();
- _myMatrix.RotateAt(angle, absPosition);
-
- // Save aold state
- IGraphicsState graphicsState = this.Save();
- // Set Angle
- this.Transform = _myMatrix;
- // Draw text with anti-aliasing
- /*
- if( (AntiAliasing & AntiAliasing.Text) == AntiAliasing.Text )
- this.TextRenderingHint = TextRenderingHint.AntiAlias;
- else
- this.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
- */
- // Draw a string
- this.DrawString( text, font, brush, absPosition , format );
- // Restore old state
- this.Restore(graphicsState);
- }
- /// <summary>
- /// This method is used by the axis title hot region generation code.
- /// It transforms the centered rectangle the same way as the Axis title text.
- /// </summary>
- /// <param name="center">Title center</param>
- /// <param name="size">Title text size</param>
- /// <param name="angle">Title rotation angle</param>
- /// <returns></returns>
- internal GraphicsPath GetTranformedTextRectPath(PointF center, SizeF size, int angle)
- {
- // Text hot area is 10px greater than the size of text
- size.Width += 10;
- size.Height += 10;
-
- // Get the absolute center and create the centered rectangle points
- PointF absCenter = GetAbsolutePoint(center);
- PointF[] points = new PointF[] {
- new PointF(absCenter.X - size.Width / 2f, absCenter.Y - size.Height / 2f),
- new PointF(absCenter.X + size.Width / 2f, absCenter.Y - size.Height / 2f),
- new PointF(absCenter.X + size.Width / 2f, absCenter.Y + size.Height / 2f),
- new PointF(absCenter.X - size.Width / 2f, absCenter.Y + size.Height / 2f)};
- //Prepare the same tranformation matrix as used for the axis title
- Matrix matrix = this.Transform.Clone();
- matrix.RotateAt(angle, absCenter);
- //Tranform the rectangle points
- matrix.TransformPoints(points);
- //Return the path consisting of the rect points
- GraphicsPath path = new GraphicsPath();
- path.AddLines(points);
- path.CloseAllFigures();
- return path;
- }
- /// <summary>
- /// Draw label string.
- /// </summary>
- /// <param name="axis">Label axis.</param>
- /// <param name="labelRowIndex">Label text row index (0-10).</param>
- /// <param name="labelMark">Second row labels mark style.</param>
- /// <param name="markColor">Label mark line color.</param>
- /// <param name="text">Label text.</param>
- /// <param name="image">Label image name.</param>
- /// <param name="imageTransparentColor">Label image transparent color.</param>
- /// <param name="font">Text bont.</param>
- /// <param name="brush">Text brush.</param>
- /// <param name="position">Text position rectangle.</param>
- /// <param name="format">Label text format.</param>
- /// <param name="angle">Label text angle.</param>
- /// <param name="boundaryRect">Specifies the rectangle where the label text MUST be fitted.</param>
- /// <param name="label">Custom Label Item</param>
- /// <param name="truncatedLeft">Label is truncated on the left.</param>
- /// <param name="truncatedRight">Label is truncated on the right.</param>
- internal void DrawLabelStringRel(
- Axis axis,
- int labelRowIndex,
- LabelMarkStyle labelMark,
- Color markColor,
- string text,
- string image,
- Color imageTransparentColor,
- System.Drawing.Font font,
- System.Drawing.Brush brush,
- RectangleF position,
- System.Drawing.StringFormat format,
- int angle,
- RectangleF boundaryRect,
- CustomLabel label,
- bool truncatedLeft,
- bool truncatedRight)
- {
- Matrix oldTransform;
- using (StringFormat drawingFormat = (StringFormat)format.Clone())
- {
- SizeF labelSize = SizeF.Empty;
- // Check that rectangle is not empty
- if (position.Width == 0 || position.Height == 0)
- {
- return;
- }
- // Find absolute position
- RectangleF absPosition = this.GetAbsoluteRectangle(position);
- // Make sure the rectangle is not empty
- if (absPosition.Width < 1f)
- {
- absPosition.Width = 1f;
- }
- if (absPosition.Height < 1f)
- {
- absPosition.Height = 1f;
- }
- #if DEBUG
- // TESTING CODE: Shows labels rectangle position.
- // Rectangle rr = Rectangle.Round(absPosition);
- // rr.Width = (int)Math.Round(absPosition.Right) - rr.X;
- // rr.Height = (int)Math.Round(absPosition.Bottom) - rr.Y;
- // this.DrawRectangle(Pens.Red,rr.X, rr.Y, rr.Width, rr.Height);
- #endif // DEBUG
- CommonElements common = axis.Common;
- if (common.ProcessModeRegions)
- {
- common.HotRegionsList.AddHotRegion(Rectangle.Round(absPosition), label, ChartElementType.AxisLabels, false, true);
- }
- //********************************************************************
- //** Draw labels in the second row
- //********************************************************************
- if (labelRowIndex > 0)
- {
- drawingFormat.LineAlignment = StringAlignment.Center;
- drawingFormat.Alignment = StringAlignment.Center;
- angle = 0;
- if (axis.AxisPosition == AxisPosition.Left)
- {
- angle = -90;
- }
- else if (axis.AxisPosition == AxisPosition.Right)
- {
- angle = 90;
- }
- else if (axis.AxisPosition == AxisPosition.Top)
- {
- }
- else if (axis.AxisPosition == AxisPosition.Bottom)
- {
- }
- }
- //********************************************************************
- //** Calculate rotation point
- //********************************************************************
- PointF rotationPoint = PointF.Empty;
- if (axis.AxisPosition == AxisPosition.Left)
- {
- rotationPoint.X = absPosition.Right;
- rotationPoint.Y = absPosition.Y + absPosition.Height / 2F;
- }
- else if (axis.AxisPosition == AxisPosition.Right)
- {
- rotationPoint.X = absPosition.Left;
- rotationPoint.Y = absPosition.Y + absPosition.Height / 2F;
- }
- else if (axis.AxisPosition == AxisPosition.Top)
- {
- rotationPoint.X = absPosition.X + absPosition.Width / 2F;
- rotationPoint.Y = absPosition.Bottom;
- }
- else if (axis.AxisPosition == AxisPosition.Bottom)
- {
- rotationPoint.X = absPosition.X + absPosition.Width / 2F;
- rotationPoint.Y = absPosition.Top;
- }
- //********************************************************************
- //** Adjust rectangle for horisontal axis
- //********************************************************************
- if ((axis.AxisPosition == AxisPosition.Top || axis.AxisPosition == AxisPosition.Bottom) &&
- angle != 0)
- {
- // Get rectangle center
- rotationPoint.X = absPosition.X + absPosition.Width / 2F;
- rotationPoint.Y = (axis.AxisPosition == AxisPosition.Top) ? absPosition.Bottom : absPosition.Y;
- // Rotate rectangle 90 degrees
- RectangleF newRect = RectangleF.Empty;
- newRect.X = absPosition.X + absPosition.Width / 2F;
- newRect.Y = absPosition.Y - absPosition.Width / 2F;
- newRect.Height = absPosition.Width;
- newRect.Width = absPosition.Height;
- // Adjust values for bottom axis
- if (axis.AxisPosition == AxisPosition.Bottom)
- {
- if (angle < 0)
- {
- newRect.X -= newRect.Width;
- }
- // Replace string alignment
- drawingFormat.Alignment = StringAlignment.Near;
- if (angle < 0)
- {
- drawingFormat.Alignment = StringAlignment.Far;
- }
- drawingFormat.LineAlignment = StringAlignment.Center;
- }
- // Adjust values for bottom axis
- if (axis.AxisPosition == AxisPosition.Top)
- {
- newRect.Y += absPosition.Height;
- if (angle > 0)
- {
- newRect.X -= newRect.Width;
- }
- // Replace string alignment
- drawingFormat.Alignment = StringAlignment.Far;
- if (angle < 0)
- {
- drawingFormat.Alignment = StringAlignment.Near;
- }
- drawingFormat.LineAlignment = StringAlignment.Center;
- }
- // Set new label rect
- absPosition = newRect;
- }
- //********************************************************************
- //** 90 degrees is a special case for vertical axes
- //********************************************************************
- if ((axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right) &&
- (angle == 90 || angle == -90))
- {
- // Get rectangle center
- rotationPoint.X = absPosition.X + absPosition.Width / 2F;
- rotationPoint.Y = absPosition.Y + absPosition.Height / 2F;
- // Rotate rectangle 90 degrees
- RectangleF newRect = RectangleF.Empty;
- newRect.X = rotationPoint.X - absPosition.Height / 2F;
- newRect.Y = rotationPoint.Y - absPosition.Width / 2F;
- newRect.Height = absPosition.Width;
- newRect.Width = absPosition.Height;
- absPosition = newRect;
- // Replace string alignment
- StringAlignment align = drawingFormat.Alignment;
- drawingFormat.Alignment = drawingFormat.LineAlignment;
- drawingFormat.LineAlignment = align;
- if (angle == 90)
- {
- if (drawingFormat.LineAlignment == StringAlignment.Far)
- drawingFormat.LineAlignment = StringAlignment.Near;
- else if (drawingFormat.LineAlignment == StringAlignment.Near)
- drawingFormat.LineAlignment = StringAlignment.Far;
- }
- if (angle == -90)
- {
- if (drawingFormat.Alignment == StringAlignment.Far)
- drawingFormat.Alignment = StringAlignment.Near;
- else if (drawingFormat.Alignment == StringAlignment.Near)
- drawingFormat.Alignment = StringAlignment.Far;
- }
- }
- //********************************************************************
- //** Create a matrix and rotate it.
- //********************************************************************
- oldTransform = null;
- if (angle != 0)
- {
- _myMatrix = this.Transform.Clone();
- _myMatrix.RotateAt(angle, rotationPoint);
- // Old angle
- oldTransform = this.Transform;
- // Set Angle
- this.Transform = _myMatrix;
- }
- //********************************************************************
- //** Measure string exact rectangle and adjust label bounding rectangle
- //********************************************************************
- RectangleF labelRect = Rectangle.Empty;
- float offsetY = 0f;
- float offsetX = 0f;
-
- // Measure text size
- labelSize = this.MeasureString(text.Replace("\\n", "\n"), font, absPosition.Size, drawingFormat);
- // Calculate text rectangle
- labelRect.Width = labelSize.Width;
- labelRect.Height = labelSize.Height;
- if (drawingFormat.Alignment == StringAlignment.Far)
- {
- labelRect.X = absPosition.Right - labelSize.Width;
- }
- else if (drawingFormat.Alignment == StringAlignment.Near)
- {
- labelRect.X = absPosition.X;
- }
- else if (drawingFormat.Alignment == StringAlignment.Center)
- {
- labelRect.X = absPosition.X + absPosition.Width / 2F - labelSize.Width / 2F;
- }
- if (drawingFormat.LineAlignment == StringAlignment.Far)
- {
- labelRect.Y = absPosition.Bottom - labelSize.Height;
- }
- else if (drawingFormat.LineAlignment == StringAlignment.Near)
- {
- labelRect.Y = absPosition.Y;
- }
- else if (drawingFormat.LineAlignment == StringAlignment.Center)
- {
- labelRect.Y = absPosition.Y + absPosition.Height / 2F - labelSize.Height / 2F;
- }
- //If the angle is not vertical or horizontal
- if (angle != 0 && angle != 90 && angle != -90)
- {
- // Adjust label rectangle so it will not overlap the plotting area
- offsetY = (float)Math.Sin((90 - angle) / 180F * Math.PI) * labelRect.Height / 2F;
- offsetX = (float)Math.Sin((Math.Abs(angle)) / 180F * Math.PI) * labelRect.Height / 2F;
- if (axis.AxisPosition == AxisPosition.Left)
- {
- _myMatrix.Translate(-offsetX, 0);
- }
- else if (axis.AxisPosition == AxisPosition.Right)
- {
- _myMatrix.Translate(offsetX, 0);
- }
- else if (axis.AxisPosition == AxisPosition.Top)
- {
- _myMatrix.Translate(0, -offsetY);
- }
- else if (axis.AxisPosition == AxisPosition.Bottom)
- {
- _myMatrix.Translate(0, offsetY);
- }
- // Adjust label rectangle so it will be inside boundary
- if (boundaryRect != RectangleF.Empty)
- {
- Region region = new Region(labelRect);
- region.Transform(_myMatrix);
- // Extend boundary rectangle to the chart picture border
- if (axis.AxisPosition == AxisPosition.Left)
- {
- boundaryRect.Width += boundaryRect.X;
- boundaryRect.X = 0;
- }
- else if (axis.AxisPosition == AxisPosition.Right)
- {
- boundaryRect.Width = this._common.Width - boundaryRect.X;
- }
- else if (axis.AxisPosition == AxisPosition.Top)
- {
- boundaryRect.Height += boundaryRect.Y;
- boundaryRect.Y = 0;
- }
- else if (axis.AxisPosition == AxisPosition.Bottom)
- {
- boundaryRect.Height = this._common.Height - boundaryRect.Y;
- }
- // Exclude boundary rectangle from the label rectangle
- region.Exclude(this.GetAbsoluteRectangle(boundaryRect));
- // If any part of the label was outside bounding rectangle
- if (!region.IsEmpty(Graphics.Graphics))
- {
- this.Transform = oldTransform;
- RectangleF truncateRect = region.GetBounds(Graphics.Graphics);
- float sizeChange = truncateRect.Width / (float)Math.Cos(Math.Abs(angle) / 180F * Math.PI);
- if (axis.AxisPosition == AxisPosition.Left)
- {
- sizeChange -= labelRect.Height * (float)Math.Tan(Math.Abs(angle) / 180F * Math.PI);
- absPosition.Y = labelRect.Y;
- absPosition.X = labelRect.X + sizeChange;
- absPosition.Width = labelRect.Width - sizeChange;
- absPosition.Height = labelRect.Height;
- }
- else if (axis.AxisPosition == AxisPosition.Right)
- {
- sizeChange -= labelRect.Height * (float)Math.Tan(Math.Abs(angle) / 180F * Math.PI);
- absPosition.Y = labelRect.Y;
- absPosition.X = labelRect.X;
- absPosition.Width = labelRect.Width - sizeChange;
- absPosition.Height = labelRect.Height;
- }
- else if (axis.AxisPosition == AxisPosition.Top)
- {
- absPosition.Y = labelRect.Y;
- absPosition.X = labelRect.X;
- absPosition.Width = labelRect.Width - sizeChange;
- absPosition.Height = labelRect.Height;
- if (angle > 0)
- {
- absPosition.X += sizeChange;
- }
- }
- else if (axis.AxisPosition == AxisPosition.Bottom)
- {
- absPosition.Y = labelRect.Y;
- absPosition.X = labelRect.X;
- absPosition.Width = labelRect.Width - sizeChange;
- absPosition.Height = labelRect.Height;
- if (angle < 0)
- {
- absPosition.X += sizeChange;
- }
- }
- }
- }
- // Update transformation matrix
- this.Transform = _myMatrix;
- }
- //********************************************************************
- //** Reserve space on the left for the label iamge
- //********************************************************************
- RectangleF absPositionWithoutImage = new RectangleF(absPosition.Location, absPosition.Size);
-
- System.Drawing.Image labelImage = null;
- SizeF imageAbsSize = new SizeF();
- if (image.Length > 0)
- {
- labelImage = axis.Common.ImageLoader.LoadImage(label.Image);
- if (labelImage != null)
- {
- ImageLoader.GetAdjustedImageSize(labelImage, this.Graphics, ref imageAbsSize);
- // Adjust label position using image size
- absPositionWithoutImage.Width -= imageAbsSize.Width;
- absPositionWithoutImage.X += imageAbsSize.Width;
- }
- if (absPositionWithoutImage.Width < 1f)
- {
- absPositionWithoutImage.Width = 1f;
- }
- }
- //********************************************************************
- //** Draw tick marks for labels in second row
- //********************************************************************
- if (labelRowIndex > 0 && labelMark != LabelMarkStyle.None)
- {
- // Make sure that me know the exact size of the text
- labelSize = this.MeasureString(
- text.Replace("\\n", "\n"),
- font,
- absPositionWithoutImage.Size,
- drawingFormat);
- // Adjust for label image
- SizeF labelSizeWithImage = new SizeF(labelSize.Width, labelSize.Height);
- if (labelImage != null)
- {
- labelSizeWithImage.Width += imageAbsSize.Width;
- }
- // Draw mark
- DrawSecondRowLabelMark(
- axis,
- markColor,
- absPosition,
- labelSizeWithImage,
- labelMark,
- truncatedLeft,
- truncatedRight,
- oldTransform);
- }
- //********************************************************************
- //** Make sure that one line label will not disapear with LineLimit
- //** flag on.
- //********************************************************************
- if ((drawingFormat.FormatFlags & StringFormatFlags.LineLimit) != 0)
- {
- // Measure string height out of one character
- drawingFormat.FormatFlags ^= StringFormatFlags.LineLimit;
- SizeF size = this.MeasureString("I", font, absPosition.Size, drawingFormat);
- // If height of one characte is more than rectangle heigjt - remove LineLimit flag
- if (size.Height < absPosition.Height)
- {
- drawingFormat.FormatFlags |= StringFormatFlags.LineLimit;
- }
- }
- else
- {
- // Set NoClip flag
- if ((drawingFormat.FormatFlags & StringFormatFlags.NoClip) != 0)
- {
- drawingFormat.FormatFlags ^= StringFormatFlags.NoClip;
- }
- // Measure string height out of one character without clipping
- SizeF size = this.MeasureString("I", font, absPosition.Size, drawingFormat);
- // Clear NoClip flag
- drawingFormat.FormatFlags ^= StringFormatFlags.NoClip;
- // If height of one characte is more than rectangle heigt - set NoClip flag
- if (size.Height > absPosition.Height)
- {
- float delta = size.Height - absPosition.Height;
- absPosition.Y -= delta / 2f;
- absPosition.Height += delta;
- }
- }
- //********************************************************************
- //** Draw a string
- //********************************************************************
- if (IsRightToLeft)
- {
- // label alignment on the axis should appear as not RTL.
- using (StringFormat fmt = (StringFormat)drawingFormat.Clone())
- {
- if (fmt.Alignment == StringAlignment.Far)
- {
- fmt.Alignment = StringAlignment.Near;
- }
- else if (fmt.Alignment == StringAlignment.Near)
- {
- fmt.Alignment = StringAlignment.Far;
- }
- this.DrawString(text.Replace("\\n", "\n"), font, brush,
- absPositionWithoutImage,
- fmt);
- }
- }
- else
- this.DrawString(text.Replace("\\n", "\n"), font, brush,
- absPositionWithoutImage,
- drawingFormat);
- // Add separate hot region for the label
- if (common.ProcessModeRegions)
- {
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddRectangle(labelRect);
- path.Transform(this.Transform);
- string url = string.Empty;
- string mapAreaAttributes = string.Empty;
- string postbackValue = string.Empty;
- common.HotRegionsList.AddHotRegion(
- this,
- path,
- false,
- label.ToolTip,
- url,
- mapAreaAttributes,
- postbackValue,
- label,
- ChartElementType.AxisLabels);
- }
- }
- //********************************************************************
- //** Draw an image
- //********************************************************************
- if (labelImage != null)
- {
- // Make sure we no the text size
- if (labelSize.IsEmpty)
- {
- labelSize = this.MeasureString(
- text.Replace("\\n", "\n"),
- font,
- absPositionWithoutImage.Size,
- drawingFormat);
- }
- // Calculate image rectangle
- RectangleF imageRect = new RectangleF(
- absPosition.X + (absPosition.Width - imageAbsSize.Width - labelSize.Width) / 2,
- absPosition.Y + (absPosition.Height - imageAbsSize.Height) / 2,
- imageAbsSize.Width,
- imageAbsSize.Height);
- if (drawingFormat.LineAlignment == StringAlignment.Center)
- {
- imageRect.Y = absPosition.Y + (absPosition.Height - imageAbsSize.Height) / 2;
- }
- else if (drawingFormat.LineAlignment == StringAlignment.Far)
- {
- imageRect.Y = absPosition.Bottom - (labelSize.Height + imageAbsSize.Height) / 2;
- }
- else if (drawingFormat.LineAlignment == StringAlignment.Near)
- {
- imageRect.Y = absPosition.Top + (labelSize.Height - imageAbsSize.Height) / 2;
- }
- if (drawingFormat.Alignment == StringAlignment.Center)
- {
- imageRect.X = absPosition.X + (absPosition.Width - imageAbsSize.Width - labelSize.Width) / 2;
- }
- else if (drawingFormat.Alignment == StringAlignment.Far)
- {
- imageRect.X = absPosition.Right - imageAbsSize.Width - labelSize.Width;
- }
- else if (drawingFormat.Alignment == StringAlignment.Near)
- {
- imageRect.X = absPosition.X;
- }
- // Create image attribute
- ImageAttributes attrib = new ImageAttributes();
- if (imageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(imageTransparentColor, imageTransparentColor, ColorAdjustType.Default);
- }
- // Draw image
- this.DrawImage(
- labelImage,
- Rectangle.Round(imageRect),
- 0, 0, labelImage.Width, labelImage.Height,
- GraphicsUnit.Pixel,
- attrib);
- // Add separate hot region for the label image
- if (common.ProcessModeRegions)
- {
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddRectangle(imageRect);
- path.Transform(this.Transform);
- string imageUrl = string.Empty;
- string imageMapAreaAttributes = string.Empty;
- string postbackValue = string.Empty;
- common.HotRegionsList.AddHotRegion(
- this,
- path,
- false,
- string.Empty,
- imageUrl,
- imageMapAreaAttributes,
- postbackValue,
- label,
- ChartElementType.AxisLabelImage);
- }
- }
- }
- }
- // Set Old Angle
- if(oldTransform != null)
- {
- this.Transform = oldTransform;
- }
- }
- /// <summary>
- /// Draw box marks for the labels in second row
- /// </summary>
- /// <param name="axis">Axis object.</param>
- /// <param name="markColor">Label mark color.</param>
- /// <param name="absPosition">Absolute position of the text.</param>
- /// <param name="truncatedLeft">Label is truncated on the left.</param>
- /// <param name="truncatedRight">Label is truncated on the right.</param>
- /// <param name="originalTransform">Original transformation matrix.</param>
- private void DrawSecondRowLabelBoxMark(
- Axis axis,
- Color markColor,
- RectangleF absPosition,
- bool truncatedLeft,
- bool truncatedRight,
- Matrix originalTransform)
- {
- // Remeber current and then reset original matrix
- Matrix curentMatrix = this.Transform;
- if(originalTransform != null)
- {
- this.Transform = originalTransform;
- }
- // Calculate center of the text rectangle
- PointF centerNotRound = new PointF(absPosition.X + absPosition.Width/2F, absPosition.Y + absPosition.Height/2F);
- // Rotate rectangle 90 degrees
- if( axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
- {
- RectangleF newRect = RectangleF.Empty;
- newRect.X = centerNotRound.X - absPosition.Height / 2F;
- newRect.Y = centerNotRound.Y - absPosition.Width / 2F;
- newRect.Height = absPosition.Width;
- newRect.Width = absPosition.Height;
- absPosition = newRect;
- }
- // Get axis position
- float axisPosRelative = (float)axis.GetAxisPosition(true);
- PointF axisPositionAbs = new PointF(axisPosRelative, axisPosRelative);
- axisPositionAbs = this.GetAbsolutePoint(axisPositionAbs);
- // Round position to achieve crisp lines with antialiasing
- Rectangle absPositionRounded = Rectangle.Round(absPosition);
- // Make sure the right and bottom position is not shifted during rounding
- absPositionRounded.Width = (int)Math.Round(absPosition.Right) - absPositionRounded.X;
- absPositionRounded.Height = (int)Math.Round(absPosition.Bottom) - absPositionRounded.Y;
- // Create pen
- Pen markPen = new Pen(
- (markColor.IsEmpty) ? axis.MajorTickMark.LineColor : markColor,
- axis.MajorTickMark.LineWidth);
- // Set pen style
- markPen.DashStyle = GetPenStyle( axis.MajorTickMark.LineDashStyle );
- // Draw top/bottom lines
- if( axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
- {
- this.DrawLine(markPen, absPositionRounded.Left, absPositionRounded.Top, absPositionRounded.Left, absPositionRounded.Bottom);
- this.DrawLine(markPen, absPositionRounded.Right, absPositionRounded.Top, absPositionRounded.Right, absPositionRounded.Bottom);
- }
- else
- {
- this.DrawLine(markPen, absPositionRounded.Left, absPositionRounded.Top, absPositionRounded.Right, absPositionRounded.Top);
- this.DrawLine(markPen, absPositionRounded.Left, absPositionRounded.Bottom, absPositionRounded.Right, absPositionRounded.Bottom);
- }
- // Draw left line
- if(!truncatedLeft)
- {
- if( axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
- {
- this.DrawLine(
- markPen,
- (axis.AxisPosition == AxisPosition.Left) ? absPositionRounded.Left : absPositionRounded.Right,
- absPositionRounded.Bottom,
- axisPositionAbs.X,
- absPositionRounded.Bottom);
- }
- else
- {
- this.DrawLine(
- markPen,
- absPositionRounded.Left,
- (axis.AxisPosition == AxisPosition.Top) ? absPositionRounded.Top : absPositionRounded.Bottom,
- absPositionRounded.Left,
- axisPositionAbs.Y);
- }
- }
- // Draw right line
- if(!truncatedRight)
- {
- if( axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right)
- {
- this.DrawLine(
- markPen,
- (axis.AxisPosition == AxisPosition.Left) ? absPositionRounded.Left : absPositionRounded.Right,
- absPositionRounded.Top,
- axisPositionAbs.X,
- absPositionRounded.Top);
- }
- else
- {
- this.DrawLine(
- markPen,
- absPositionRounded.Right,
- (axis.AxisPosition == AxisPosition.Top) ? absPositionRounded.Top : absPositionRounded.Bottom,
- absPositionRounded.Right,
- axisPositionAbs.Y);
- }
- }
- // Dispose Pen
- if( markPen != null )
- {
- markPen.Dispose();
- }
- // Restore currentmatrix
- if(originalTransform != null)
- {
- this.Transform = curentMatrix;
- }
- }
- /// <summary>
- /// Draw marks for the labels in second row
- /// </summary>
- /// <param name="axis">Axis object.</param>
- /// <param name="markColor">Label mark color.</param>
- /// <param name="absPosition">Absolute position of the text.</param>
- /// <param name="labelSize">Exact mesured size of the text.</param>
- /// <param name="labelMark">Label mark style to draw.</param>
- /// <param name="truncatedLeft">Label is truncated on the left.</param>
- /// <param name="truncatedRight">Label is truncated on the right.</param>
- /// <param name="oldTransform">Original transformation matrix.</param>
- private void DrawSecondRowLabelMark(
- Axis axis,
- Color markColor,
- RectangleF absPosition,
- SizeF labelSize,
- LabelMarkStyle labelMark,
- bool truncatedLeft,
- bool truncatedRight,
- Matrix oldTransform)
- {
- // Do not draw marking line if width is 0 and style or color are not set
- if( axis.MajorTickMark.LineWidth == 0 ||
- axis.MajorTickMark.LineDashStyle == ChartDashStyle.NotSet ||
- axis.MajorTickMark.LineColor == Color.Empty)
- {
- return;
- }
- // Remember SmoothingMode and turn off anti aliasing for
- // vertical or horizontal lines of the label markers.
- SmoothingMode oldSmoothingMode = this.SmoothingMode;
- this.SmoothingMode = SmoothingMode.None;
- // Draw box marker
- if(labelMark == LabelMarkStyle.Box)
- {
- DrawSecondRowLabelBoxMark(
- axis,
- markColor,
- absPosition,
- truncatedLeft,
- truncatedRight,
- oldTransform);
- }
- else
- {
- // Calculate center of the text rectangle
- System.Drawing.Point center = System.Drawing.Point.Round(new PointF(absPosition.X + absPosition.Width/2F, absPosition.Y + absPosition.Height/2F));
- // Round position to achieve crisp lines with antialiasing
- Rectangle absPositionRounded = Rectangle.Round(absPosition);
- // Make sure the right and bottom position is not shifted during rounding
- absPositionRounded.Width = (int)Math.Round(absPosition.Right) - absPositionRounded.X;
- absPositionRounded.Height = (int)Math.Round(absPosition.Bottom) - absPositionRounded.Y;
- // Arrays of points for the left and right marking lines
- PointF[] leftLine = new PointF[3];
- PointF[] rightLine = new PointF[3];
- // Calculate marking lines coordinates
- leftLine[0].X = absPositionRounded.Left;
- leftLine[0].Y = absPositionRounded.Bottom;
- leftLine[1].X = absPositionRounded.Left;
- leftLine[1].Y = center.Y;
- leftLine[2].X = (float)Math.Round((double)center.X - labelSize.Width/2F - 1F);
- leftLine[2].Y = center.Y;
- rightLine[0].X = absPositionRounded.Right;
- rightLine[0].Y = absPositionRounded.Bottom;
- rightLine[1].X = absPositionRounded.Right;
- rightLine[1].Y = center.Y;
- rightLine[2].X = (float)Math.Round((double)center.X + labelSize.Width/2F - 1F);
- rightLine[2].Y = center.Y;
- if(axis.AxisPosition == AxisPosition.Bottom)
- {
- leftLine[0].Y = absPositionRounded.Top;
- rightLine[0].Y = absPositionRounded.Top;
- }
- // Remove third point to draw only side marks
- if(labelMark == LabelMarkStyle.SideMark)
- {
- leftLine[2] = leftLine[1];
- rightLine[2] = rightLine[1];
- }
- if(truncatedLeft)
- {
- leftLine[0] = leftLine[1];
- }
- if(truncatedRight)
- {
- rightLine[0] = rightLine[1];
- }
- // Create pen
- Pen markPen = new Pen(
- (markColor.IsEmpty) ? axis.MajorTickMark.LineColor : markColor,
- axis.MajorTickMark.LineWidth);
- // Set pen style
- markPen.DashStyle = GetPenStyle( axis.MajorTickMark.LineDashStyle );
- // Draw marking lines
- this.DrawLines(markPen, leftLine);
- this.DrawLines(markPen, rightLine);
- // Dispose Pen
- if( markPen != null )
- {
- markPen.Dispose();
- }
- }
- // Restore previous SmoothingMode
- this.SmoothingMode = oldSmoothingMode;
- }
- /// <summary>
- /// Measures the specified text string when drawn with
- /// the specified Font object and formatted with the
- /// specified StringFormat object.
- /// </summary>
- /// <param name="text">The string to measure</param>
- /// <param name="font">The Font object used to determine the size of the text string. </param>
- /// <returns>A SizeF structure that represents the size of text as drawn with font.</returns>
- internal SizeF MeasureStringRel( string text, Font font )
- {
- SizeF newSize;
- // Measure string
- newSize = this.MeasureString( text, font );
- // Convert to relative Coordinates
- return GetRelativeSize( newSize );
- }
- /// <summary>
- /// Measures the specified text string when drawn with
- /// the specified Font object and formatted with the
- /// specified StringFormat object.
- /// </summary>
- /// <param name="text">The string to measure</param>
- /// <param name="font">The Font object used to determine the size of the text string. </param>
- /// <param name="layoutArea">A SizeF structure that specifies the layout rectangle for the text. </param>
- /// <param name="stringFormat">A StringFormat object that represents formatting information, such as line spacing, for the text string. </param>
- /// <returns>A SizeF structure that represents the size of text as drawn with font.</returns>
- internal SizeF MeasureStringRel( string text, Font font, SizeF layoutArea, StringFormat stringFormat )
- {
- SizeF size, newSize;
- // Get absolute coordinates
- size = GetAbsoluteSize( layoutArea );
- newSize = this.MeasureString( text, font, size, stringFormat );
- // Convert to relative Coordinates
- return GetRelativeSize( newSize );
- }
- /// <summary>
- /// Measures the specified text string when drawn with
- /// the specified Font object and formatted with the
- /// specified StringFormat object.
- /// </summary>
- /// <param name="text">The string to measure</param>
- /// <param name="font">The Font object used to determine the size of the text string. </param>
- /// <returns>A SizeF structure that represents the size of text as drawn with font.</returns>
- internal Size MeasureStringAbs( string text, Font font )
- {
- // Measure string
- SizeF size = this.MeasureString( text, font );
- return new Size( (int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height));
- }
- /// <summary>
- /// Measures the specified text string when drawn with
- /// the specified Font object and formatted with the
- /// specified StringFormat object.
- /// </summary>
- /// <param name="text">The string to measure</param>
- /// <param name="font">The Font object used to determine the size of the text string. </param>
- /// <param name="layoutArea">A SizeF structure that specifies the layout rectangle for the text. </param>
- /// <param name="stringFormat">A StringFormat object that represents formatting information, such as line spacing, for the text string. </param>
- /// <returns>A SizeF structure that represents the size of text as drawn with font.</returns>
- internal Size MeasureStringAbs( string text, Font font, SizeF layoutArea, StringFormat stringFormat )
- {
- SizeF size = this.MeasureString( text, font, layoutArea, stringFormat );
- return new Size( (int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height));
- }
- /// <summary>
- /// Draws the specified text string at the specified location
- /// with the specified Brush object and font. The formatting
- /// properties in the specified StringFormat object are applied
- /// to the text.
- /// </summary>
- /// <param name="text">A string object that specifies the text to draw.</param>
- /// <param name="font">A Font object that specifies the font face and size with which to draw the text.</param>
- /// <param name="brush">A Brush object that determines the color and/or texture of the drawn text.</param>
- /// <param name="layoutRectangle">A RectangleF structure that specifies the location of the drawn text.</param>
- /// <param name="format">A StringFormat object that specifies formatting properties, such as line spacing and alignment, that are applied to the drawn text.</param>
- internal void DrawStringRel( string text, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format )
- {
- RectangleF rect;
- // Check that rectangle is not empty
- if(layoutRectangle.Width == 0 || layoutRectangle.Height == 0)
- {
- return;
- }
- // Get absolute coordinates
- rect = GetAbsoluteRectangle( layoutRectangle );
- // Draw text with anti-aliasing
- /*
- if( (this.AntiAliasing & AntiAliasing.Text) == AntiAliasing.Text )
- {
- this.TextRenderingHint = TextRenderingHint.AntiAlias;
- }
- else
- {
- this.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
- }
- */
- this.DrawString( text, font, brush, rect, format );
- }
-
- /// <summary>
- /// Draws the specified text string at the specified location
- /// with the specified angle and with the specified Brush object and font. The
- /// formatting properties in the specified StringFormat object are applied
- /// to the text.
- /// </summary>
- /// <param name="text">A string object that specifies the text to draw.</param>
- /// <param name="font">A Font object that specifies the font face and size with which to draw the text.</param>
- /// <param name="brush">A Brush object that determines the color and/or texture of the drawn text.</param>
- /// <param name="layoutRectangle">A RectangleF structure that specifies the location of the drawn text.</param>
- /// <param name="format">A StringFormat object that specifies formatting properties, such as line spacing and alignment, that are applied to the drawn text.</param>
- /// <param name="angle">A angle of the text</param>
- internal void DrawStringRel(
- string text,
- Font font,
- Brush brush,
- RectangleF layoutRectangle,
- StringFormat format,
- int angle
- )
- {
- RectangleF rect;
- SizeF size;
- Matrix oldTransform;
- PointF rotationCenter = PointF.Empty;
- // Check that rectangle is not empty
- if(layoutRectangle.Width == 0 || layoutRectangle.Height == 0)
- {
- return;
- }
- // Get absolute coordinates
- rect = GetAbsoluteRectangle( layoutRectangle );
- size = this.MeasureString( text, font, rect.Size, format );
- // Find the center of rotation
- if( format.Alignment == StringAlignment.Near )
- { // Near
- rotationCenter.X = rect.X + size.Width / 2;
- rotationCenter.Y = ( rect.Bottom + rect.Top ) / 2;
- }
- else if( format.Alignment == StringAlignment.Far )
- { // Far
- rotationCenter.X = rect.Right - size.Width / 2;
- rotationCenter.Y = ( rect.Bottom + rect.Top ) / 2;
- }
- else
- { // Center
- rotationCenter.X = ( rect.Left + rect.Right ) / 2;
- rotationCenter.Y = ( rect.Bottom + rect.Top ) / 2;
- }
- // Create a matrix and rotate it.
- _myMatrix = this.Transform.Clone();
- _myMatrix.RotateAt( angle, rotationCenter);
- // Old angle
- oldTransform = this.Transform;
- // Set Angle
- this.Transform = _myMatrix;
- // Draw text with anti-aliasing
- /*
- if( (AntiAliasing & AntiAliasing.Text) == AntiAliasing.Text )
- {
- this.TextRenderingHint = TextRenderingHint.AntiAlias;
- }
- else
- {
- this.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
- }
- */
- this.DrawString( text, font, brush, rect, format );
- // Set Old Angle
- this.Transform = oldTransform;
- }
- #endregion
- #region Rectangle Methods
- /// <summary>
- /// Draws different shadows to create bar styles.
- /// </summary>
- /// <param name="barDrawingStyle">Bar drawing style.</param>
- /// <param name="isVertical">True if a vertical bar.</param>
- /// <param name="rect">Rectangle position.</param>
- internal void DrawRectangleBarStyle(BarDrawingStyle barDrawingStyle, bool isVertical, RectangleF rect)
- {
- // Check if non-default bar drawing style is specified
- if(barDrawingStyle != BarDrawingStyle.Default)
- {
- // Check column/bar size
- if(rect.Width > 0 && rect.Height > 0)
- {
- // Draw gradient(s)
- if(barDrawingStyle == BarDrawingStyle.Cylinder)
- {
- // Calculate gradient position
- RectangleF gradientRect = rect;
- if(isVertical)
- {
- gradientRect.Width *= 0.3f;
- }
- else
- {
- gradientRect.Height *= 0.3f;
- }
- if(gradientRect.Width > 0 && gradientRect.Height > 0)
- {
- this.FillRectangleAbs(
- gradientRect,
- Color.Transparent,
- ChartHatchStyle.None,
- string.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- (isVertical) ? GradientStyle.LeftRight : GradientStyle.TopBottom,
- Color.FromArgb(120, Color.White),
- Color.Empty,
- 0,
- ChartDashStyle.NotSet,
- PenAlignment.Inset );
-
- if(isVertical)
- {
- gradientRect.X += gradientRect.Width + 1f;
- gradientRect.Width = rect.Right - gradientRect.X;
- }
- else
- {
- gradientRect.Y += gradientRect.Height + 1f;
- gradientRect.Height = rect.Bottom - gradientRect.Y;
- }
- this.FillRectangleAbs(
- gradientRect,
- Color.FromArgb(120, Color.White),
- ChartHatchStyle.None,
- string.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- (isVertical) ? GradientStyle.LeftRight : GradientStyle.TopBottom,
- Color.FromArgb(150, Color.Black),
- Color.Empty,
- 0,
- ChartDashStyle.NotSet,
- PenAlignment.Inset );
- }
- }
- else if(barDrawingStyle == BarDrawingStyle.Emboss)
- {
- // Calculate width of shadows used to create the effect
- float shadowSize = 3f;
- if(rect.Width < 6f || rect.Height < 6f)
- {
- shadowSize = 1f;
- }
- else if(rect.Width < 15f || rect.Height < 15f)
- {
- shadowSize = 2f;
- }
- // Create and draw left/top path
- using(GraphicsPath path = new GraphicsPath())
- {
- // Add shadow polygon to the path
- PointF[] points = new PointF[] {
- new PointF(rect.Left, rect.Bottom),
- new PointF(rect.Left, rect.Top),
- new PointF(rect.Right, rect.Top),
- new PointF(rect.Right - shadowSize, rect.Top + shadowSize),
- new PointF(rect.Left + shadowSize, rect.Top + shadowSize),
- new PointF(rect.Left + shadowSize, rect.Bottom - shadowSize) };
- path.AddPolygon(points);
- // Create brush
- using(SolidBrush leftTopBrush = new SolidBrush(Color.FromArgb(100, Color.White)))
- {
- // Fill shadow path on the left-bottom side of the bar
- this.FillPath(leftTopBrush, path);
- }
- }
- // Create and draw top/right path
- using(GraphicsPath path = new GraphicsPath())
- {
- // Add shadow polygon to the path
- PointF[] points = new PointF[] {
- new PointF(rect.Right, rect.Top),
- new PointF(rect.Right, rect.Bottom),
- new PointF(rect.Left, rect.Bottom),
- new PointF(rect.Left + shadowSize, rect.Bottom - shadowSize),
- new PointF(rect.Right - shadowSize, rect.Bottom - shadowSize),
- new PointF(rect.Right - shadowSize, rect.Top + shadowSize) };
- path.AddPolygon(points);
- // Create brush
- using(SolidBrush bottomRightBrush = new SolidBrush(Color.FromArgb(80, Color.Black)))
- {
- // Fill shadow path on the left-bottom side of the bar
- this.FillPath(bottomRightBrush, path);
- }
- }
- }
- else if(barDrawingStyle == BarDrawingStyle.LightToDark)
- {
- // Calculate width of shadows used to create the effect
- float shadowSize = 4f;
- if(rect.Width < 6f || rect.Height < 6f)
- {
- shadowSize = 2f;
- }
- else if(rect.Width < 15f || rect.Height < 15f)
- {
- shadowSize = 3f;
- }
- // Calculate gradient position
- RectangleF gradientRect = rect;
- gradientRect.Inflate(-shadowSize, -shadowSize);
- if(isVertical)
- {
- gradientRect.Height = (float)Math.Floor(gradientRect.Height / 3f);
- }
- else
- {
- gradientRect.X = gradientRect.Right - (float)Math.Floor(gradientRect.Width / 3f);
- gradientRect.Width = (float)Math.Floor(gradientRect.Width / 3f);
- }
- if(gradientRect.Width > 0 && gradientRect.Height > 0)
- {
- this.FillRectangleAbs(
- gradientRect,
- (isVertical) ? Color.FromArgb(120, Color.White) : Color.Transparent,
- ChartHatchStyle.None,
- string.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- (isVertical) ? GradientStyle.TopBottom : GradientStyle.LeftRight,
- (isVertical) ? Color.Transparent : Color.FromArgb(120, Color.White),
- Color.Empty,
- 0,
- ChartDashStyle.NotSet,
- PenAlignment.Inset );
- gradientRect = rect;
- gradientRect.Inflate(-shadowSize, -shadowSize);
- if(isVertical)
- {
- gradientRect.Y = gradientRect.Bottom - (float)Math.Floor(gradientRect.Height / 3f);
- gradientRect.Height = (float)Math.Floor(gradientRect.Height / 3f);
- }
- else
- {
- gradientRect.Width = (float)Math.Floor(gradientRect.Width / 3f);
- }
- this.FillRectangleAbs(
- gradientRect,
- (!isVertical) ? Color.FromArgb(80, Color.Black) : Color.Transparent,
- ChartHatchStyle.None,
- string.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- (isVertical) ? GradientStyle.TopBottom : GradientStyle.LeftRight,
- (!isVertical) ? Color.Transparent : Color.FromArgb(80, Color.Black),
- Color.Empty,
- 0,
- ChartDashStyle.NotSet,
- PenAlignment.Inset );
- }
- }
- else if(barDrawingStyle == BarDrawingStyle.Wedge)
- {
- // Calculate wedge size to fit the rectangle
- float size = (isVertical) ? rect.Width / 2f : rect.Height / 2f;
- if(isVertical && 2f * size > rect.Height)
- {
- size = rect.Height/2f;
- }
- if(!isVertical && 2f * size > rect.Width)
- {
- size = rect.Width/2f;
- }
- // Draw left/bottom shadow
- RectangleF gradientRect = rect;
- using(GraphicsPath path = new GraphicsPath())
- {
- if(isVertical)
- {
- path.AddLine(gradientRect.X + gradientRect.Width/2f, gradientRect.Y + size, gradientRect.X + gradientRect.Width/2f, gradientRect.Bottom - size);
- path.AddLine(gradientRect.X + gradientRect.Width/2f, gradientRect.Bottom - size, gradientRect.Right, gradientRect.Bottom);
- path.AddLine(gradientRect.Right, gradientRect.Bottom, gradientRect.Right, gradientRect.Y);
- }
- else
- {
- path.AddLine(gradientRect.X + size, gradientRect.Y + gradientRect.Height/2f, gradientRect.Right - size, gradientRect.Y + gradientRect.Height/2f);
- path.AddLine(gradientRect.Right - size, gradientRect.Y + gradientRect.Height/2f, gradientRect.Right, gradientRect.Bottom);
- path.AddLine(gradientRect.Right, gradientRect.Bottom, gradientRect.Left, gradientRect.Bottom);
- }
- path.CloseAllFigures();
- // Create brush and fill path
- using(SolidBrush brush = new SolidBrush(Color.FromArgb(90, Color.Black)))
- {
- this.FillPath(brush, path);
- }
- }
- // Draw top/right triangle
- using(GraphicsPath path = new GraphicsPath())
- {
- if(isVertical)
- {
- path.AddLine(gradientRect.X, gradientRect.Y, gradientRect.X + gradientRect.Width/2f, gradientRect.Y + size);
- path.AddLine(gradientRect.X + gradientRect.Width/2f, gradientRect.Y + size, gradientRect.Right, gradientRect.Y);
- }
- else
- {
- path.AddLine(gradientRect.Right, gradientRect.Y, gradientRect.Right - size, gradientRect.Y + gradientRect.Height / 2f);
- path.AddLine(gradientRect.Right - size, gradientRect.Y + gradientRect.Height / 2f, gradientRect.Right, gradientRect.Bottom);
- }
- // Create brush and fill path
- using(SolidBrush brush = new SolidBrush(Color.FromArgb(50, Color.Black)))
- {
- // Fill shadow path on the left-bottom side of the bar
- this.FillPath(brush, path);
- // Draw Lines
- using(Pen penDark = new Pen(Color.FromArgb(20, Color.Black), 1))
- {
- this.DrawPath(penDark, path);
- if(isVertical)
- {
- this.DrawLine(
- penDark,
- rect.X + rect.Width/2f,
- rect.Y + size,
- rect.X + rect.Width/2f,
- rect.Bottom - size);
- }
- else
- {
- this.DrawLine(
- penDark,
- rect.X + size,
- rect.Y + rect.Height/2f,
- rect.X + size,
- rect.Bottom - rect.Height/2f);
- }
- }
- // Draw Lines
- using(Pen pen = new Pen(Color.FromArgb(40, Color.White), 1))
- {
- this.DrawPath(pen, path);
- if(isVertical)
- {
- this.DrawLine(
- pen,
- rect.X + rect.Width/2f,
- rect.Y + size,
- rect.X + rect.Width/2f,
- rect.Bottom - size);
- }
- else
- {
- this.DrawLine(
- pen,
- rect.X + size,
- rect.Y + rect.Height/2f,
- rect.X + size,
- rect.Bottom - rect.Height/2f);
- }
- }
- }
- }
- // Draw bottom/left triangle
- using(GraphicsPath path = new GraphicsPath())
- {
- if(isVertical)
- {
- path.AddLine(gradientRect.X, gradientRect.Bottom, gradientRect.X + gradientRect.Width/2f, gradientRect.Bottom - size);
- path.AddLine(gradientRect.X + gradientRect.Width/2f, gradientRect.Bottom - size, gradientRect.Right, gradientRect.Bottom);
- }
- else
- {
- path.AddLine(gradientRect.X, gradientRect.Y, gradientRect.X + size, gradientRect.Y + gradientRect.Height / 2f);
- path.AddLine(gradientRect.X + size, gradientRect.Y + gradientRect.Height / 2f, gradientRect.X, gradientRect.Bottom);
- }
- // Create brush
- using(SolidBrush brush = new SolidBrush(Color.FromArgb(50, Color.Black)))
- {
- // Fill shadow path on the left-bottom side of the bar
- this.FillPath(brush, path);
- // Draw edges
- using(Pen penDark = new Pen(Color.FromArgb(20, Color.Black), 1))
- {
- this.DrawPath(penDark, path);
- }
- using(Pen pen = new Pen(Color.FromArgb(40, Color.White), 1))
- {
- this.DrawPath(pen, path);
- }
- }
- }
- }
- }
- }
- }
- /// <summary>
- /// Draw a bar with shadow.
- /// </summary>
- /// <param name="rectF">Size of rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="penAlignment">Pen Alignment</param>
- /// <param name="barDrawingStyle">Bar drawing style.</param>
- /// <param name="isVertical">True if a vertical bar.</param>
- internal void FillRectangleRel( RectangleF rectF,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Color shadowColor,
- int shadowOffset,
- PenAlignment penAlignment,
- BarDrawingStyle barDrawingStyle,
- bool isVertical)
- {
- this.FillRectangleRel(
- rectF,
- backColor,
- backHatchStyle,
- backImage,
- backImageWrapMode,
- backImageTransparentColor,
- backImageAlign,
- backGradientStyle,
- backSecondaryColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- shadowColor,
- shadowOffset,
- penAlignment,
- false,
- 0,
- false,
- barDrawingStyle,
- isVertical);
- }
- /// <summary>
- /// Draw a bar with shadow.
- /// </summary>
- /// <param name="rectF">Size of rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="penAlignment">Pen Alignment</param>
- internal void FillRectangleRel( RectangleF rectF,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Color shadowColor,
- int shadowOffset,
- PenAlignment penAlignment )
- {
- this.FillRectangleRel(
- rectF,
- backColor,
- backHatchStyle,
- backImage,
- backImageWrapMode,
- backImageTransparentColor,
- backImageAlign,
- backGradientStyle,
- backSecondaryColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- shadowColor,
- shadowOffset,
- penAlignment,
- false,
- 0,
- false,
- BarDrawingStyle.Default,
- true);
- }
- /// <summary>
- /// Draws rectangle or circle (inside rectangle) with shadow.
- /// </summary>
- /// <param name="rectF">Size of rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="penAlignment">Pen Alignment</param>
- /// <param name="circular">Draw circular shape inside the rectangle.</param>
- /// <param name="circularSectorsCount">Number of sectors in circle when drawing the polygon.</param>
- /// <param name="circle3D">3D Circle must be drawn.</param>
- internal void FillRectangleRel( RectangleF rectF,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Color shadowColor,
- int shadowOffset,
- PenAlignment penAlignment,
- bool circular,
- int circularSectorsCount,
- bool circle3D)
- {
- this.FillRectangleRel(
- rectF,
- backColor,
- backHatchStyle,
- backImage,
- backImageWrapMode,
- backImageTransparentColor,
- backImageAlign,
- backGradientStyle,
- backSecondaryColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- shadowColor,
- shadowOffset,
- penAlignment,
- circular,
- circularSectorsCount,
- circle3D,
- BarDrawingStyle.Default,
- true);
- }
-
- /// <summary>
- /// Draws rectangle or circle (inside rectangle) with shadow.
- /// </summary>
- /// <param name="rectF">Size of rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="penAlignment">Pen Alignment</param>
- /// <param name="circular">Draw circular shape inside the rectangle.</param>
- /// <param name="circularSectorsCount">Number of sectors in circle when drawing the polygon.</param>
- /// <param name="circle3D">3D Circle must be drawn.</param>
- /// <param name="barDrawingStyle">Bar drawing style.</param>
- /// <param name="isVertical">True if a vertical bar.</param>
- internal void FillRectangleRel( RectangleF rectF,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- Color shadowColor,
- int shadowOffset,
- PenAlignment penAlignment,
- bool circular,
- int circularSectorsCount,
- bool circle3D,
- BarDrawingStyle barDrawingStyle,
- bool isVertical)
- {
- Brush brush = null;
- Brush backBrush = null;
- // Remember SmoothingMode and turn off anti aliasing
- SmoothingMode oldSmoothingMode = this.SmoothingMode;
- if(!circular)
- {
- this.SmoothingMode = SmoothingMode.Default;
- }
- // Color is empty
- if( backColor.IsEmpty )
- {
- backColor = Color.White;
- }
- if( backSecondaryColor.IsEmpty )
- {
- backSecondaryColor = Color.White;
- }
- if( borderColor.IsEmpty || borderDashStyle == ChartDashStyle.NotSet)
- {
- borderWidth = 0;
- }
-
- // Get absolute coordinates
- RectangleF rect = GetAbsoluteRectangle( rectF );
-
- // Rectangle width and height can not be very small value
- if( rect.Width < 1.0F && rect.Width > 0.0F )
- {
- rect.Width = 1.0F;
- }
- if( rect.Height < 1.0F && rect.Height > 0.0F )
- {
- rect.Height = 1.0F;
- }
- // Round the values
- rect = Round( rect );
- // For inset alignment resize fill rectangle
- RectangleF fillRect;
- if( penAlignment == PenAlignment.Inset &&
- borderWidth > 0)
- {
- // SVG and Metafiles do not support inset pen styles - use same rectangle
- if( this.ActiveRenderingType == RenderingType.Svg ||
- this.IsMetafile)
- {
- fillRect = new RectangleF( rect.X, rect.Y, rect.Width, rect.Height);
- }
- else if (this.Graphics.Transform.Elements[0] != 1f ||
- this.Graphics.Transform.Elements[3] != 1f)
- {
- // Do not reduce filling rectangle if scaling is used in the graphics
- // transformations. Rounding may cause a 1 pixel gap between the border
- // and the filling.
- fillRect = new RectangleF( rect.X, rect.Y, rect.Width, rect.Height);
- }
- else
- {
- // The fill rectangle is resized because of border size.
- fillRect = new RectangleF(
- rect.X + borderWidth,
- rect.Y + borderWidth,
- rect.Width - borderWidth * 2f + 1,
- rect.Height - borderWidth * 2f + 1);
- }
- }
- else
- {
- // The fill rectangle is same
- fillRect = rect;
- }
- // Fix for issue #6714:
- // Make sure the rectangle coordinates fit the control. In same cases rectangle width or
- // hight ca be extremly large. Drawing such a rectangle may cause an overflow exception.
- // The code below restricts the maximum size to double the chart size. See issue
- // description for more information. -AG.
- if(fillRect.Width > 2f * this._width)
- {
- fillRect.Width = 2f * this._width;
- }
- if(fillRect.Height > 2f * this._height)
- {
- fillRect.Height = 2f * this._height;
- }
- if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled)
- {
- backBrush = brush;
- brush = GetTextureBrush(backImage, backImageTransparentColor, backImageWrapMode, backColor);
- }
- else if( backHatchStyle != ChartHatchStyle.None )
- {
- brush = GetHatchBrush( backHatchStyle, backColor, backSecondaryColor );
- }
- else if( backGradientStyle != GradientStyle.None )
- {
- // If a gradient type is set create a brush with gradient
- brush = GetGradientBrush( rect, backColor, backSecondaryColor, backGradientStyle );
- }
- else
- {
- // Set a bar color.
- if(backColor == Color.Empty || backColor == Color.Transparent)
- {
- brush = null;
- }
- else
- {
- brush = new SolidBrush(backColor);
- }
- }
- // Draw shadow
- FillRectangleShadowAbs( rect, shadowColor, shadowOffset, backColor, circular, circularSectorsCount );
- // Draw rectangle image
- if( backImage.Length > 0 && (backImageWrapMode == ChartImageWrapMode.Unscaled || backImageWrapMode == ChartImageWrapMode.Scaled))
- {
- // Load image
- System.Drawing.Image image = _common.ImageLoader.LoadImage( backImage );
- // Prepare image properties (transparent color)
- ImageAttributes attrib = new ImageAttributes();
- if(backImageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(backImageTransparentColor, backImageTransparentColor, ColorAdjustType.Default);
- }
- // Draw scaled image
- RectangleF imageRect = new RectangleF();
- imageRect.X = fillRect.X;
- imageRect.Y = fillRect.Y;
- imageRect.Width = fillRect.Width;
- imageRect.Height = fillRect.Height;
- SizeF imageAbsSize = new SizeF();
- // Calculate unscaled image position
- if(backImageWrapMode == ChartImageWrapMode.Unscaled)
- {
- ImageLoader.GetAdjustedImageSize(image, this.Graphics, ref imageAbsSize);
- // Calculate image position
- imageRect.Width = Math.Min(fillRect.Width, imageAbsSize.Width);
- imageRect.Height = Math.Min(fillRect.Height, imageAbsSize.Height);
- // Adjust position with alignment property
- if(imageRect.Width < fillRect.Width)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Right ||
- backImageAlign == ChartImageAlignmentStyle.TopRight)
- {
- imageRect.X = fillRect.Right - imageRect.Width;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Top)
- {
- imageRect.X = fillRect.X + (fillRect.Width - imageRect.Width)/2;
- }
- }
- if(imageRect.Height < fillRect.Height)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.BottomLeft)
- {
- imageRect.Y = fillRect.Bottom - imageRect.Height;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Left ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Right)
- {
- imageRect.Y = fillRect.Y + (fillRect.Height - imageRect.Height)/2;
- }
- }
- }
- // Fill background with brush
- if(brush != null)
- {
- if(circular)
- this.DrawCircleAbs( null, brush, fillRect, circularSectorsCount, circle3D );
- else
- this.FillRectangle( brush, fillRect );
- }
-
- // Draw image
- this.DrawImage(image,
- new Rectangle((int)Math.Round(imageRect.X),(int)Math.Round(imageRect.Y), (int)Math.Round(imageRect.Width), (int)Math.Round(imageRect.Height)),
- 0, 0,
- (backImageWrapMode == ChartImageWrapMode.Unscaled) ? imageRect.Width * image.Width / imageAbsSize.Width : image.Width,
- (backImageWrapMode == ChartImageWrapMode.Unscaled) ? imageRect.Height * image.Height / imageAbsSize.Height : image.Height,
- GraphicsUnit.Pixel,
- attrib);
- }
- // Draw rectangle
- else
- {
- if(backBrush != null && backImageTransparentColor != Color.Empty)
- {
- // Fill background with brush
- if(circular)
- this.DrawCircleAbs( null, backBrush, fillRect, circularSectorsCount, circle3D );
- else
- this.FillRectangle( backBrush, fillRect );
- }
- if(brush != null)
- {
- if(circular)
- this.DrawCircleAbs( null, brush, fillRect, circularSectorsCount, circle3D );
- else
- this.FillRectangle( brush, fillRect );
- }
- }
- // Draw different bar style
- this.DrawRectangleBarStyle(barDrawingStyle, isVertical, fillRect);
- // Draw border
- if( borderWidth > 0 && borderDashStyle != ChartDashStyle.NotSet)
- {
- // Set a border line color
- if(_pen.Color != borderColor)
- {
- _pen.Color = borderColor;
- }
-
- // Set a border line width
- if(_pen.Width != borderWidth)
- {
- _pen.Width = borderWidth;
- }
- // Set pen alignment
- if(_pen.Alignment != penAlignment)
- {
- _pen.Alignment = penAlignment;
- }
- // Set a border line style
- if(_pen.DashStyle != GetPenStyle( borderDashStyle ))
- {
- _pen.DashStyle = GetPenStyle( borderDashStyle );
- }
- // Draw border
- if(circular)
- {
- this.DrawCircleAbs( _pen, null, rect, circularSectorsCount, false );
- }
- else
- {
- // NOTE: Rectangle with single pixel inset border is drawn 1 pixel larger
- // in the .Net Framework. Increase size by 1 pixel to solve the issue.
- if(_pen.Alignment == PenAlignment.Inset && _pen.Width > 1f)
- {
- rect.Width += 1;
- rect.Height += 1;
- }
- // Draw rectangle
- this.DrawRectangle( _pen, rect.X, rect.Y, rect.Width, rect.Height );
- }
- }
- // Dispose Image and Gradient
- if(brush != null)
- {
- brush.Dispose();
- }
- // Return old smoothing mode
- this.SmoothingMode = oldSmoothingMode;
- }
- /// <summary>
- /// Draw Shadow for a bar
- /// </summary>
- /// <param name="rect">Bar rectangle</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="backColor">Back Color</param>
- internal void FillRectangleShadowAbs(
- RectangleF rect,
- Color shadowColor,
- float shadowOffset,
- Color backColor)
- {
- FillRectangleShadowAbs(
- rect,
- shadowColor,
- shadowOffset,
- backColor,
- false,
- 0);
- }
- /// <summary>
- /// Draw Shadow for a bar
- /// </summary>
- /// <param name="rect">Bar rectangle</param>
- /// <param name="shadowColor">Shadow Color</param>
- /// <param name="shadowOffset">Shadow Offset</param>
- /// <param name="backColor">Back Color</param>
- /// <param name="circular">Draw circular shape inside the rectangle.</param>
- /// <param name="circularSectorsCount">Number of sectors in circle when drawing the polygon.</param>
- internal void FillRectangleShadowAbs(
- RectangleF rect,
- Color shadowColor,
- float shadowOffset,
- Color backColor,
- bool circular,
- int circularSectorsCount)
- {
- // Do not draw shadoe for empty rectangle
- if(rect.Height == 0 || rect.Width == 0 || shadowOffset == 0)
- {
- return;
- }
- // Do not draw shadow if color is IsEmpty or offset is 0
- if (shadowOffset == 0 || shadowColor == Color.Empty)
- {
- return;
- }
- // For non-circualr shadow with transparent background - use clipping
- bool clippingUsed = false;
- Region oldClipRegion = null;
- if (!circular && backColor == Color.Transparent)
- {
- clippingUsed = true;
- oldClipRegion = this.Clip;
- Region region = new Region();
- region.MakeInfinite();
- region.Xor(rect);
- this.Clip = region;
- }
-
- // Draw usual or "soft" shadows
- if(!softShadows || circularSectorsCount > 2)
- {
- RectangleF absolute;
- RectangleF offset = RectangleF.Empty;
- absolute = Round( rect );
- // Change shadow color
- using (SolidBrush shadowBrush = new SolidBrush((shadowColor.A != 255) ? shadowColor : Color.FromArgb(backColor.A / 2, shadowColor)))
- {
- // Shadow Position
- offset.X = absolute.X + shadowOffset;
- offset.Y = absolute.Y + shadowOffset;
- offset.Width = absolute.Width;
- offset.Height = absolute.Height;
- // Draw rectangle
- if (circular)
- this.DrawCircleAbs(null, shadowBrush, offset, circularSectorsCount, false);
- else
- this.FillRectangle(shadowBrush, offset);
- }
- }
- else
- {
- RectangleF absolute;
- RectangleF offset = RectangleF.Empty;
- absolute = Round( rect );
-
- // Shadow Position
- offset.X = absolute.X + shadowOffset - 1;
- offset.Y = absolute.Y + shadowOffset - 1;
- offset.Width = absolute.Width + 2;
- offset.Height = absolute.Height + 2;
-
- // Calculate rounded rect radius
- float radius = shadowOffset * 0.7f;
- radius = (float)Math.Max(radius, 2f);
- radius = (float)Math.Min(radius, offset.Width/4f);
- radius = (float)Math.Min(radius, offset.Height/4f);
- radius = (float)Math.Ceiling(radius);
- if(circular)
- {
- radius = offset.Width/2f;
- }
- // Create rounded rectangle path
- GraphicsPath path = new GraphicsPath();
- if(circular && offset.Width != offset.Height)
- {
- float radiusX = offset.Width/2f;
- float radiusY = offset.Height/2f;
- path.AddLine(offset.X+radiusX, offset.Y, offset.Right-radiusX, offset.Y);
- path.AddArc(offset.Right-2f*radiusX, offset.Y, 2f*radiusX, 2f*radiusY, 270, 90);
- path.AddLine(offset.Right, offset.Y + radiusY, offset.Right, offset.Bottom - radiusY);
- path.AddArc(offset.Right-2f*radiusX, offset.Bottom-2f*radiusY, 2f*radiusX, 2f*radiusY, 0, 90);
- path.AddLine(offset.Right-radiusX, offset.Bottom, offset.X + radiusX, offset.Bottom);
- path.AddArc(offset.X, offset.Bottom-2f*radiusY, 2f*radiusX, 2f*radiusY, 90, 90);
- path.AddLine(offset.X, offset.Bottom-radiusY, offset.X, offset.Y+radiusY);
- path.AddArc(offset.X, offset.Y, 2f*radiusX, 2f*radiusY, 180, 90);
- }
- else
- {
- path.AddLine(offset.X+radius, offset.Y, offset.Right-radius, offset.Y);
- path.AddArc(offset.Right-2f*radius, offset.Y, 2f*radius, 2f*radius, 270, 90);
- path.AddLine(offset.Right, offset.Y + radius, offset.Right, offset.Bottom - radius);
- path.AddArc(offset.Right-2f*radius, offset.Bottom-2f*radius, 2f*radius, 2f*radius, 0, 90);
- path.AddLine(offset.Right-radius, offset.Bottom, offset.X + radius, offset.Bottom);
- path.AddArc(offset.X, offset.Bottom-2f*radius, 2f*radius, 2f*radius, 90, 90);
- path.AddLine(offset.X, offset.Bottom-radius, offset.X, offset.Y+radius);
- path.AddArc(offset.X, offset.Y, 2f*radius, 2f*radius, 180, 90);
- }
- PathGradientBrush shadowBrush = new PathGradientBrush(path);
- shadowBrush.CenterColor = shadowColor;
- // Set the color along the entire boundary of the path
- Color[] colors = {Color.Transparent};
- shadowBrush.SurroundColors = colors;
- shadowBrush.CenterPoint = new PointF(offset.X + offset.Width/2f, offset.Y + offset.Height/2f);
- // Define brush focus scale
- PointF focusScale = new PointF(1-2f*shadowOffset/offset.Width, 1-2f*shadowOffset/offset.Height);
- if(focusScale.X < 0)
- focusScale.X = 0;
- if(focusScale.Y < 0)
- focusScale.Y = 0;
- shadowBrush.FocusScales = focusScale;
- // Draw rectangle
- this.FillPath(shadowBrush, path);
- }
- // Reset clip region
- if (clippingUsed)
- {
- Region region = this.Clip;
- this.Clip = oldClipRegion;
- region.Dispose();
- }
- }
- /// <summary>
- /// Gets the path of the polygon which represent the circular area.
- /// </summary>
- /// <param name="position">Circle position.</param>
- /// <param name="polygonSectorsNumber">Number of sectors for the polygon.</param>
- /// <returns>Graphics path of the polygon circle.</returns>
- internal GraphicsPath GetPolygonCirclePath(RectangleF position, int polygonSectorsNumber)
- {
- PointF firstPoint = new PointF(position.X + position.Width/2f, position.Y);
- PointF centerPoint = new PointF(position.X + position.Width/2f, position.Y + position.Height/2f);
- float sectorSize = 0f;
- GraphicsPath path = new GraphicsPath();
- PointF prevPoint = PointF.Empty;
- float curentSector = 0f;
- // Get sector size
- if(polygonSectorsNumber <= 2)
- {
- // Circle sector size
- sectorSize = 1f;
- }
- else
- {
- // Polygon sector size
- sectorSize = 360f / ((float)polygonSectorsNumber);
- }
- // Loop throug all sectors
- for(curentSector = 0f; curentSector < 360f; curentSector += sectorSize)
- {
- // Create matrix
- Matrix matrix = new Matrix();
- matrix.RotateAt(curentSector, centerPoint);
- // Get point and rotate it
- PointF[] points = new PointF[] { firstPoint };
- matrix.TransformPoints(points);
- // Add point into the path
- if(!prevPoint.IsEmpty)
- {
- path.AddLine(prevPoint, points[0]);
- }
- // Remember last point
- prevPoint = points[0];
- }
- path.CloseAllFigures();
- return path;
- }
- /// <summary>
- /// Fills and/or draws border as circle or polygon.
- /// </summary>
- /// <param name="pen">Border pen.</param>
- /// <param name="brush">Border brush.</param>
- /// <param name="position">Circle position.</param>
- /// <param name="polygonSectorsNumber">Number of sectors for the polygon.</param>
- /// <param name="circle3D">Indicates that circle should be 3D..</param>
- internal void DrawCircleAbs(Pen pen, Brush brush, RectangleF position, int polygonSectorsNumber, bool circle3D)
- {
- bool fill3DCircle = (circle3D && brush != null);
- // Draw 2D circle
- if(polygonSectorsNumber <= 2 && !fill3DCircle)
- {
- if(brush != null)
- {
- this.FillEllipse(brush, position);
- }
- if(pen != null)
- {
- this.DrawEllipse(pen, position);
- }
- }
- // Draw circle as polygon with specified number of sectors
- else
- {
- PointF firstPoint = new PointF(position.X + position.Width/2f, position.Y);
- PointF centerPoint = new PointF(position.X + position.Width/2f, position.Y + position.Height/2f);
- float sectorSize = 0f;
- PointF prevPoint = PointF.Empty;
- float curentSector = 0f;
- using (GraphicsPath path = new GraphicsPath())
- {
- // Remember current smoothing mode
- SmoothingMode oldMode = this.SmoothingMode;
- if (fill3DCircle)
- {
- this.SmoothingMode = SmoothingMode.None;
- }
- // Get sector size
- if (polygonSectorsNumber <= 2)
- {
- // Circle sector size
- sectorSize = 1f;
- }
- else
- {
- // Polygon sector size
- sectorSize = 360f / ((float)polygonSectorsNumber);
- }
- // Loop throug all sectors
- for (curentSector = 0f; curentSector < 360f; curentSector += sectorSize)
- {
- // Create matrix
- Matrix matrix = new Matrix();
- matrix.RotateAt(curentSector, centerPoint);
- // Get point and rotate it
- PointF[] points = new PointF[] { firstPoint };
- matrix.TransformPoints(points);
- // Add point into the path
- if (!prevPoint.IsEmpty)
- {
- path.AddLine(prevPoint, points[0]);
- // Fill each segment separatly for the 3D look
- if (fill3DCircle)
- {
- path.AddLine(points[0], centerPoint);
- path.AddLine(centerPoint, prevPoint);
- using (Brush sectorBrush = GetSector3DBrush(brush, curentSector, sectorSize))
- {
- this.FillPath(sectorBrush, path);
- }
- path.Reset();
- }
- }
- // Remember last point
- prevPoint = points[0];
- }
- path.CloseAllFigures();
- // Fill last segment for the 3D look
- if (!prevPoint.IsEmpty && fill3DCircle)
- {
- path.AddLine(prevPoint, firstPoint);
- path.AddLine(firstPoint, centerPoint);
- path.AddLine(centerPoint, prevPoint);
- using (Brush sectorBrush = GetSector3DBrush(brush, curentSector, sectorSize))
- {
- this.FillPath(sectorBrush, path);
- }
- path.Reset();
- }
- // Restore old mode
- if (fill3DCircle)
- {
- this.SmoothingMode = oldMode;
- }
- if (brush != null && !circle3D)
- {
- this.FillPath(brush, path);
- }
- if (pen != null)
- {
- this.DrawPath(pen, path);
- }
- }
- }
- }
- /// <summary>
- /// Creates 3D sector brush.
- /// </summary>
- /// <param name="brush">Original brush.</param>
- /// <param name="curentSector">Sector position.</param>
- /// <param name="sectorSize">Sector size.</param>
- /// <returns>3D brush.</returns>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily",
- Justification = "Too large of a code change to justify making this change")]
- internal Brush GetSector3DBrush(Brush brush, float curentSector, float sectorSize)
- {
- // Get color from the brush
- Color brushColor = Color.Gray;
- if(brush is HatchBrush)
- {
- brushColor = ((HatchBrush)brush).BackgroundColor;
- }
- else if(brush is LinearGradientBrush)
- {
- brushColor = ((LinearGradientBrush)brush).LinearColors[0];
- }
- else if(brush is PathGradientBrush)
- {
- brushColor = ((PathGradientBrush)brush).CenterColor;
- }
- else if(brush is SolidBrush)
- {
- brushColor = ((SolidBrush)brush).Color;
- }
- // Adjust sector angle
- curentSector -= sectorSize / 2f;
- // Make adjustment for polygon circle with 5 segments
- // to avoid the issue that bottom segment is too dark
- if(sectorSize == 72f && curentSector == 180f)
- {
- curentSector *= 0.8f;
- }
- // No angles more than 180
- if(curentSector > 180)
- {
- curentSector = 360f - curentSector;
- }
- curentSector = curentSector / 180F;
- // Get brush
- brushColor = GetBrightGradientColor( brushColor, curentSector);
- // Get brush
- return new SolidBrush(brushColor);
- }
- /// <summary>
- /// This method creates gradient color with brightness
- /// </summary>
- /// <param name="beginColor">Start color for gradient.</param>
- /// <param name="position">Position used between Start and end color.</param>
- /// <returns>Calculated Gradient color from gradient position</returns>
- internal Color GetBrightGradientColor( Color beginColor, double position )
- {
- double brightness = 0.5;
- if( position < brightness )
- {
- return GetGradientColor( Color.FromArgb(beginColor.A,255,255,255), beginColor, 1 - brightness + position );
- }
- else if( -brightness + position < 1 )
- {
- return GetGradientColor( beginColor, Color.Black, -brightness + position);
- }
- else
- {
- return Color.FromArgb( beginColor.A, 0, 0, 0 );
- }
- }
- /// <summary>
- /// Draw Rectangle using absolute coordinates.
- /// </summary>
- /// <param name="rect">Size of rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch Style</param>
- /// <param name="backImage">Image URL</param>
- /// <param name="backImageWrapMode">Image Mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment.</param>
- /// <param name="backGradientStyle">Gradient AxisName</param>
- /// <param name="backSecondaryColor">End Gradient color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="penAlignment">Border is outside or inside rectangle</param>
- internal void FillRectangleAbs( RectangleF rect,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- PenAlignment penAlignment )
- {
- Brush brush = null;
- Brush backBrush = null;
- // Turn off Antialias
- SmoothingMode oldMode = this.SmoothingMode;
- this.SmoothingMode = SmoothingMode.None;
- // Color is empty
- if( backColor.IsEmpty )
- backColor = Color.White;
- if( backSecondaryColor.IsEmpty )
- backSecondaryColor = Color.White;
- if( borderColor.IsEmpty )
- {
- borderColor = Color.White;
- borderWidth = 0;
- }
-
- // Set a border line color
- _pen.Color = borderColor;
- // Set a border line width
- _pen.Width = borderWidth;
- // Set pen alignment
- _pen.Alignment = penAlignment;
- // Set a border line style
- _pen.DashStyle = GetPenStyle( borderDashStyle );
- if( backGradientStyle == GradientStyle.None )
- {
- // Set a bar color.
- _solidBrush.Color = backColor;
- brush = _solidBrush;
- }
- else
- {
- // If a gradient type is set create a brush with gradient
- brush = GetGradientBrush( rect, backColor, backSecondaryColor, backGradientStyle );
- }
- if( backHatchStyle != ChartHatchStyle.None )
- {
- brush = GetHatchBrush( backHatchStyle, backColor, backSecondaryColor );
- }
- if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled)
- {
- backBrush = brush;
- brush = GetTextureBrush(backImage, backImageTransparentColor, backImageWrapMode, backColor );
- }
- // For inset alignment resize fill rectangle
- RectangleF fillRect;
-
- // The fill rectangle is same
- fillRect = new RectangleF( rect.X + borderWidth, rect.Y + borderWidth, rect.Width - borderWidth * 2, rect.Height - borderWidth * 2 );
- // FillRectangle and DrawRectangle works differently with RectangleF.
- fillRect.Width += 1;
- fillRect.Height += 1;
- // Draw rectangle image
- if( backImage.Length > 0 && (backImageWrapMode == ChartImageWrapMode.Unscaled || backImageWrapMode == ChartImageWrapMode.Scaled))
- {
- // Load image
- System.Drawing.Image image = _common.ImageLoader.LoadImage( backImage );
-
- // Prepare image properties (transparent color)
- ImageAttributes attrib = new ImageAttributes();
- if(backImageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(backImageTransparentColor, backImageTransparentColor, ColorAdjustType.Default);
- }
- // Draw scaled image
- RectangleF imageRect = new RectangleF();
- imageRect.X = fillRect.X;
- imageRect.Y = fillRect.Y;
- imageRect.Width = fillRect.Width;
- imageRect.Height = fillRect.Height;
- // Draw unscaled image using align property
- if(backImageWrapMode == ChartImageWrapMode.Unscaled)
- {
- SizeF imageAbsSize = new SizeF();
- ImageLoader.GetAdjustedImageSize(image, this.Graphics, ref imageAbsSize);
- // Calculate image position
- imageRect.Width = imageAbsSize.Width;
- imageRect.Height = imageAbsSize.Height;
- // Adjust position with alignment property
- if(imageRect.Width < fillRect.Width)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Right ||
- backImageAlign == ChartImageAlignmentStyle.TopRight)
- {
- imageRect.X = fillRect.Right - imageRect.Width;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Top)
- {
- imageRect.X = fillRect.X + (fillRect.Width - imageRect.Width)/2;
- }
- }
- if(imageRect.Height < fillRect.Height)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.BottomLeft)
- {
- imageRect.Y = fillRect.Bottom - imageRect.Height;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Left ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Right)
- {
- imageRect.Y = fillRect.Y + (fillRect.Height - imageRect.Height)/2;
- }
- }
- }
- // Fill background with brush
- this.FillRectangle( brush, rect.X, rect.Y, rect.Width + 1, rect.Height + 1);
- // Draw image
- this.DrawImage(image,
- new Rectangle((int)Math.Round(imageRect.X),(int)Math.Round(imageRect.Y), (int)Math.Round(imageRect.Width), (int)Math.Round(imageRect.Height)),
- 0, 0, image.Width, image.Height,
- GraphicsUnit.Pixel,
- attrib);
- }
- // Draw rectangle
- else
- {
- if(backBrush != null && backImageTransparentColor != Color.Empty)
- {
- // Fill background with brush
- this.FillRectangle( backBrush, rect.X, rect.Y, rect.Width + 1, rect.Height + 1 );
- }
- this.FillRectangle( brush, rect.X, rect.Y, rect.Width + 1, rect.Height + 1 );
- }
- // Set pen alignment
- if(borderDashStyle != ChartDashStyle.NotSet)
- {
- if( borderWidth > 1 )
- this.DrawRectangle( _pen, rect.X, rect.Y, rect.Width + 1, rect.Height + 1 );
- else if( borderWidth == 1 )
- this.DrawRectangle( _pen, rect.X, rect.Y, rect.Width, rect.Height );
- }
- // Dispose Image and Gradient
- if( backGradientStyle != GradientStyle.None )
- {
- brush.Dispose();
- }
- if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled)
- {
- brush.Dispose();
- }
- if( backHatchStyle != ChartHatchStyle.None )
- {
- brush.Dispose();
- }
- // Set Old Smoothing Mode
- this.SmoothingMode = oldMode;
- }
- /// <summary>
- /// Fills graphics path with shadow using absolute coordinates.
- /// </summary>
- /// <param name="path">Graphics path to fill.</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch Style</param>
- /// <param name="backImage">Image URL</param>
- /// <param name="backImageWrapMode">Image Mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment.</param>
- /// <param name="backGradientStyle">Gradient AxisName</param>
- /// <param name="backSecondaryColor">End Gradient color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="penAlignment">Border is outside or inside rectangle</param>
- /// <param name="shadowOffset">Shadow offset.</param>
- /// <param name="shadowColor">Shadow color.</param>
- internal void DrawPathAbs(
- GraphicsPath path,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- PenAlignment penAlignment,
- int shadowOffset,
- Color shadowColor)
- {
- // Draw patj shadow
- if(shadowOffset != 0 && shadowColor != Color.Transparent)
- {
- // Save graphics state and apply translate transformation
- IGraphicsState graphicsState = this.Save();
- this.TranslateTransform(shadowOffset, shadowOffset);
- if(backColor == Color.Transparent &&
- backSecondaryColor.IsEmpty )
- {
- this.DrawPathAbs(
- path,
- Color.Transparent,
- ChartHatchStyle.None,
- String.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- GradientStyle.None,
- Color.Empty,
- shadowColor,
- borderWidth,
- borderDashStyle,
- PenAlignment.Center);
- }
- else
- {
- this.DrawPathAbs(
- path,
- shadowColor,
- ChartHatchStyle.None,
- String.Empty,
- ChartImageWrapMode.Scaled,
- Color.Empty,
- ChartImageAlignmentStyle.Center,
- GradientStyle.None,
- Color.Empty,
- Color.Transparent,
- 0,
- ChartDashStyle.NotSet,
- PenAlignment.Center);
- }
- // Restore graphics state
- this.Restore(graphicsState);
- }
- // Draw path
- this.DrawPathAbs(
- path,
- backColor,
- backHatchStyle,
- backImage,
- backImageWrapMode,
- backImageTransparentColor,
- backImageAlign,
- backGradientStyle,
- backSecondaryColor,
- borderColor,
- borderWidth,
- borderDashStyle,
- penAlignment);
- }
- /// <summary>
- /// Fills graphics path using absolute coordinates.
- /// </summary>
- /// <param name="path">Graphics path to fill.</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch Style</param>
- /// <param name="backImage">Image URL</param>
- /// <param name="backImageWrapMode">Image Mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment.</param>
- /// <param name="backGradientStyle">Gradient AxisName</param>
- /// <param name="backSecondaryColor">End Gradient color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="penAlignment">Border is outside or inside rectangle</param>
- internal void DrawPathAbs( GraphicsPath path,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- PenAlignment penAlignment )
- {
- Brush brush = null;
- Brush backBrush = null;
- // Color is empty
- if( backColor.IsEmpty )
- backColor = Color.White;
- if( backSecondaryColor.IsEmpty )
- backSecondaryColor = Color.White;
- if( borderColor.IsEmpty )
- {
- borderColor = Color.White;
- borderWidth = 0;
- }
-
- // Set pen properties
- _pen.Color = borderColor;
- _pen.Width = borderWidth;
- _pen.Alignment = penAlignment;
- _pen.DashStyle = GetPenStyle( borderDashStyle );
- if( backGradientStyle == GradientStyle.None )
- {
- // Set solid brush color.
- _solidBrush.Color = backColor;
- brush = _solidBrush;
- }
- else
- {
- // If a gradient type is set create a brush with gradient
- RectangleF pathRect = path.GetBounds();
- pathRect.Inflate(new SizeF(2,2));
- brush = GetGradientBrush(
- pathRect,
- backColor,
- backSecondaryColor,
- backGradientStyle );
- }
- if( backHatchStyle != ChartHatchStyle.None )
- {
- brush = GetHatchBrush( backHatchStyle, backColor, backSecondaryColor );
- }
- if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled)
- {
- backBrush = brush;
- brush = GetTextureBrush(backImage, backImageTransparentColor, backImageWrapMode, backColor );
- }
- // For inset alignment resize fill rectangle
- RectangleF fillRect = path.GetBounds();
-
- // Draw rectangle image
- if( backImage.Length > 0 && (backImageWrapMode == ChartImageWrapMode.Unscaled || backImageWrapMode == ChartImageWrapMode.Scaled))
- {
- // Load image
- System.Drawing.Image image = _common.ImageLoader.LoadImage( backImage );
- // Prepare image properties (transparent color)
- ImageAttributes attrib = new ImageAttributes();
- if(backImageTransparentColor != Color.Empty)
- {
- attrib.SetColorKey(backImageTransparentColor, backImageTransparentColor, ColorAdjustType.Default);
- }
- // Draw scaled image
- RectangleF imageRect = new RectangleF();
- imageRect.X = fillRect.X;
- imageRect.Y = fillRect.Y;
- imageRect.Width = fillRect.Width;
- imageRect.Height = fillRect.Height;
- // Draw unscaled image using align property
- if(backImageWrapMode == ChartImageWrapMode.Unscaled)
- {
- SizeF imageSize = new SizeF();
- ImageLoader.GetAdjustedImageSize(image, this.Graphics, ref imageSize);
- // Calculate image position
- imageRect.Width = imageSize.Width;
- imageRect.Height = imageSize.Height;
- // Adjust position with alignment property
- if(imageRect.Width < fillRect.Width)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Right ||
- backImageAlign == ChartImageAlignmentStyle.TopRight)
- {
- imageRect.X = fillRect.Right - imageRect.Width;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Top)
- {
- imageRect.X = fillRect.X + (fillRect.Width - imageRect.Width)/2;
- }
- }
- if(imageRect.Height < fillRect.Height)
- {
- if(backImageAlign == ChartImageAlignmentStyle.BottomRight ||
- backImageAlign == ChartImageAlignmentStyle.Bottom ||
- backImageAlign == ChartImageAlignmentStyle.BottomLeft)
- {
- imageRect.Y = fillRect.Bottom - imageRect.Height;
- }
- else if(backImageAlign == ChartImageAlignmentStyle.Left ||
- backImageAlign == ChartImageAlignmentStyle.Center ||
- backImageAlign == ChartImageAlignmentStyle.Right)
- {
- imageRect.Y = fillRect.Y + (fillRect.Height - imageRect.Height)/2;
- }
- }
- }
- // Fill background with brush
- this.FillPath( brush, path );
- // Draw image
- Region oldClipRegion = this.Clip;
- this.Clip = new Region(path);
- this.DrawImage(image,
- new Rectangle((int)Math.Round(imageRect.X),(int)Math.Round(imageRect.Y), (int)Math.Round(imageRect.Width), (int)Math.Round(imageRect.Height)),
- 0, 0, image.Width, image.Height,
- GraphicsUnit.Pixel,
- attrib);
- this.Clip = oldClipRegion;
- }
-
- // Draw rectangle
- else
- {
- if(backBrush != null && backImageTransparentColor != Color.Empty)
- {
- // Fill background with brush
- this.FillPath( backBrush, path);
- }
- this.FillPath( brush, path);
- }
- // Draw border
- if(borderColor != Color.Empty && borderWidth > 0 && borderDashStyle != ChartDashStyle.NotSet)
- {
- this.DrawPath( _pen, path );
- }
- }
- /// <summary>
- /// Creates brush with specified properties.
- /// </summary>
- /// <param name="rect">Gradient rectangle</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <returns>New brush object.</returns>
- internal Brush CreateBrush(
- RectangleF rect,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- GradientStyle backGradientStyle,
- Color backSecondaryColor
- )
- {
- Brush brush = new SolidBrush(backColor);
- if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled)
- {
- brush = GetTextureBrush(backImage, backImageTransparentColor, backImageWrapMode, backColor );
- }
- else if( backHatchStyle != ChartHatchStyle.None )
- {
- brush = GetHatchBrush( backHatchStyle, backColor, backSecondaryColor );
- }
- else if( backGradientStyle != GradientStyle.None )
- {
- // If a gradient type is set create a brush with gradient
- brush = GetGradientBrush( rect, backColor, backSecondaryColor, backGradientStyle );
- }
- return brush;
- }
- #endregion
- #region Coordinates converter
- /// <summary>
- /// This method takes a RectangleF structure that is using absolute coordinates
- /// and returns a RectangleF object that uses relative coordinates.
- /// </summary>
- /// <param name="rectangle">RectangleF structure in absolute coordinates.</param>
- /// <returns>RectangleF structure in relative coordinates.</returns>
- public RectangleF GetRelativeRectangle( RectangleF rectangle )
- {
- // Check arguments
- if (rectangle == null)
- throw new ArgumentNullException("rectangle");
-
- RectangleF relative = RectangleF.Empty;
- // Convert absolute coordinates to relative coordinates
- relative.X = rectangle.X * 100F / ((float)(_width - 1));
- relative.Y = rectangle.Y * 100F / ((float)(_height - 1));
- relative.Width = rectangle.Width * 100F / ((float)(_width - 1));
- relative.Height = rectangle.Height * 100F / ((float)(_height - 1));
- // Return Relative coordinates
- return relative;
- }
- /// <summary>
- /// This method takes a PointF object that is using absolute coordinates
- /// and returns a PointF object that uses relative coordinates.
- /// </summary>
- /// <param name="point">PointF object in absolute coordinates.</param>
- /// <returns>PointF object in relative coordinates.</returns>
- public PointF GetRelativePoint( PointF point )
- {
- // Check arguments
- if (point == null)
- throw new ArgumentNullException("point");
-
- PointF relative = PointF.Empty;
- // Convert absolute coordinates to relative coordinates
- relative.X = point.X * 100F / ((float)(_width - 1));
- relative.Y = point.Y * 100F / ((float)(_height - 1));
-
- // Return Relative coordinates
- return relative;
- }
- /// <summary>
- /// This method takes a SizeF object that uses absolute coordinates
- /// and returns a SizeF object that uses relative coordinates.
- /// </summary>
- /// <param name="size">SizeF object in absolute coordinates.</param>
- /// <returns>SizeF object in relative coordinates.</returns>
- public SizeF GetRelativeSize( SizeF size )
- {
- // Check arguments
- if (size == null)
- throw new ArgumentNullException("size");
-
- SizeF relative = SizeF.Empty;
- // Convert absolute coordinates to relative coordinates
- relative.Width = size.Width * 100F / ((float)(_width - 1));
- relative.Height = size.Height * 100F / ((float)(_height - 1));
-
- // Return relative coordinates
- return relative;
- }
- /// <summary>
- /// This method takes a PointF object and converts its relative coordinates
- /// to absolute coordinates.
- /// </summary>
- /// <param name="point">PointF object in relative coordinates.</param>
- /// <returns>PointF object in absolute coordinates.</returns>
- public PointF GetAbsolutePoint( PointF point )
- {
- // Check arguments
- if (point == null)
- throw new ArgumentNullException("point");
- PointF absolute = PointF.Empty;
- // Convert relative coordinates to absolute coordinates
- absolute.X = point.X * (_width - 1) / 100F;
- absolute.Y = point.Y * (_height - 1) / 100F;
- // Return Absolute coordinates
- return absolute;
- }
- /// <summary>
- /// This method takes a RectangleF structure and converts its relative coordinates
- /// to absolute coordinates.
- /// </summary>
- /// <param name="rectangle">RectangleF object in relative coordinates.</param>
- /// <returns>RectangleF object in absolute coordinates.</returns>
- public RectangleF GetAbsoluteRectangle( RectangleF rectangle )
- {
- // Check arguments
- if (rectangle == null)
- throw new ArgumentNullException("rectangle");
- RectangleF absolute = RectangleF.Empty;
- // Convert relative coordinates to absolute coordinates
- absolute.X = rectangle.X * (_width - 1) / 100F;
- absolute.Y = rectangle.Y * (_height - 1) / 100F;
- absolute.Width = rectangle.Width * (_width - 1) / 100F;
- absolute.Height = rectangle.Height * (_height - 1) / 100F;
- // Return Absolute coordinates
- return absolute;
- }
- /// <summary>
- /// This method takes a SizeF object that uses relative coordinates
- /// and returns a SizeF object that uses absolute coordinates.
- /// </summary>
- /// <param name="size">SizeF object in relative coordinates.</param>
- /// <returns>SizeF object in absolute coordinates.</returns>
- public SizeF GetAbsoluteSize( SizeF size )
- {
- // Check arguments
- if (size == null)
- throw new ArgumentNullException("size");
-
- SizeF absolute = SizeF.Empty;
- // Convert relative coordinates to absolute coordinates
- absolute.Width = size.Width * (_width - 1) / 100F;
- absolute.Height = size.Height * (_height - 1) / 100F;
-
- // Return Absolute coordinates
- return absolute;
- }
-
- #endregion
- #region Border drawing helper methods
- /// <summary>
- /// Helper function which creates a rounded rectangle path.
- /// </summary>
- /// <param name="rect">Rectangle coordinates.</param>
- /// <param name="cornerRadius">Array of 4 corners radius.</param>
- /// <returns>Graphics path object.</returns>
- internal GraphicsPath CreateRoundedRectPath(RectangleF rect, float[] cornerRadius)
- {
- // Create rounded rectangle path
- GraphicsPath path = new GraphicsPath();
- path.AddLine(rect.X+cornerRadius[0], rect.Y, rect.Right-cornerRadius[1], rect.Y);
- path.AddArc(rect.Right-2f*cornerRadius[1], rect.Y, 2f*cornerRadius[1], 2f*cornerRadius[2], 270, 90);
- path.AddLine(rect.Right, rect.Y + cornerRadius[2], rect.Right, rect.Bottom - cornerRadius[3]);
- path.AddArc(rect.Right-2f*cornerRadius[4], rect.Bottom-2f*cornerRadius[3], 2f*cornerRadius[4], 2f*cornerRadius[3], 0, 90);
- path.AddLine(rect.Right-cornerRadius[4], rect.Bottom, rect.X + cornerRadius[5], rect.Bottom);
- path.AddArc(rect.X, rect.Bottom-2f*cornerRadius[6], 2f*cornerRadius[5], 2f*cornerRadius[6], 90, 90);
- path.AddLine(rect.X, rect.Bottom-cornerRadius[6], rect.X, rect.Y+cornerRadius[7]);
- path.AddArc(rect.X, rect.Y, 2f*cornerRadius[0], 2f*cornerRadius[7], 180, 90);
- return path;
- }
- /// <summary>
- /// Helper function which draws a shadow of the rounded rect.
- /// </summary>
- /// <param name="rect">Rectangle coordinates.</param>
- /// <param name="cornerRadius">Array of 4 corners radius.</param>
- /// <param name="radius">Rounding radius.</param>
- /// <param name="centerColor">Center color.</param>
- /// <param name="surroundColor">Surrounding color.</param>
- /// <param name="shadowScale">Shadow scale value.</param>
- internal void DrawRoundedRectShadowAbs(RectangleF rect, float[] cornerRadius, float radius, Color centerColor, Color surroundColor, float shadowScale)
- {
- // Create rounded rectangle path
- GraphicsPath path = CreateRoundedRectPath(rect, cornerRadius);
- // Create gradient brush
- PathGradientBrush shadowBrush = new PathGradientBrush(path);
- shadowBrush.CenterColor = centerColor;
- // Set the color along the entire boundary of the path
- Color[] colors = {surroundColor};
- shadowBrush.SurroundColors = colors;
- shadowBrush.CenterPoint = new PointF(rect.X + rect.Width/2f, rect.Y + rect.Height/2f);
- // Define brush focus scale
- PointF focusScale = new PointF(1-shadowScale*radius/rect.Width, 1-shadowScale*radius/rect.Height);
- shadowBrush.FocusScales = focusScale;
- // Draw rounded rectangle
- this.FillPath(shadowBrush, path);
- if( path != null )
- {
- path.Dispose();
- }
- }
- /// <summary>
- /// Draws 3D border in absolute coordinates.
- /// </summary>
- /// <param name="borderSkin">Border skin object.</param>
- /// <param name="rect">Rectangle of the border (pixel coordinates).</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- internal void Draw3DBorderRel(
- BorderSkin borderSkin,
- RectangleF rect,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle)
- {
- Draw3DBorderAbs(borderSkin, GetAbsoluteRectangle(rect), backColor, backHatchStyle,
- backImage, backImageWrapMode, backImageTransparentColor, backImageAlign, backGradientStyle,
- backSecondaryColor, borderColor, borderWidth, borderDashStyle);
- }
- /// <summary>
- /// Draws 3D border in absolute coordinates.
- /// </summary>
- /// <param name="borderSkin">Border skin object.</param>
- /// <param name="absRect">Rectangle of the border (pixel coordinates).</param>
- /// <param name="backColor">Color of rectangle</param>
- /// <param name="backHatchStyle">Hatch style</param>
- /// <param name="backImage">Back Image</param>
- /// <param name="backImageWrapMode">Image mode</param>
- /// <param name="backImageTransparentColor">Image transparent color.</param>
- /// <param name="backImageAlign">Image alignment</param>
- /// <param name="backGradientStyle">Gradient type </param>
- /// <param name="backSecondaryColor">Gradient End Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- internal void Draw3DBorderAbs(
- BorderSkin borderSkin,
- RectangleF absRect,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- ChartImageAlignmentStyle backImageAlign,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle)
- {
- // Check input parameters
- if(_common == null || borderSkin.SkinStyle == BorderSkinStyle.None || absRect.Width == 0 || absRect.Height == 0)
- {
- return;
- }
- // Find required border interface
- IBorderType borderTypeInterface = _common.BorderTypeRegistry.GetBorderType(borderSkin.SkinStyle.ToString());
- if(borderTypeInterface != null)
- {
- borderTypeInterface.Resolution = 96;//this.Graphics.DpiX;
- // Draw border
- borderTypeInterface.DrawBorder(this, borderSkin, absRect, backColor, backHatchStyle, backImage, backImageWrapMode,
- backImageTransparentColor, backImageAlign, backGradientStyle, backSecondaryColor,
- borderColor, borderWidth, borderDashStyle);
- }
- }
- #endregion
- #region Pie Method
- /// <summary>
- /// Helper function that retrieves pie drawing style.
- /// </summary>
- /// <param name="point">Data point to get the drawing style for.</param>
- /// <returns>pie drawing style.</returns>
- internal static PieDrawingStyle GetPieDrawingStyle(DataPoint point)
- {
- // Get column drawing style
- PieDrawingStyle pieDrawingStyle = PieDrawingStyle.Default;
- string styleName = point[CustomPropertyName.PieDrawingStyle];
- if(styleName != null)
- {
- if(String.Compare(styleName, "Default", StringComparison.OrdinalIgnoreCase) == 0)
- {
- pieDrawingStyle = PieDrawingStyle.Default;
- }
- else if (String.Compare(styleName, "SoftEdge", StringComparison.OrdinalIgnoreCase) == 0)
- {
- pieDrawingStyle = PieDrawingStyle.SoftEdge;
- }
- else if (String.Compare(styleName, "Concave", StringComparison.OrdinalIgnoreCase) == 0)
- {
- pieDrawingStyle = PieDrawingStyle.Concave;
- }
- else
- {
- throw( new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid( styleName, "PieDrawingStyle")));
- }
- }
- return pieDrawingStyle;
- }
- /// <summary>
- /// Draws a pie defined by an ellipse specified by a Rectangle structure and two radial lines.
- /// </summary>
- /// <param name="rect">Rectangle structure that represents the bounding rectangle that defines the ellipse from which the pie shape comes.</param>
- /// <param name="startAngle">Angle measured in degrees clockwise from the x-axis to the first side of the pie shape.</param>
- /// <param name="sweepAngle">Angle measured in degrees clockwise from the startAngle parameter to the second side of the pie shape.</param>
- /// <param name="backColor">Fill color</param>
- /// <param name="backHatchStyle">Fill Hatch Style</param>
- /// <param name="backImage">Fill texture</param>
- /// <param name="backImageWrapMode">Texture image mode</param>
- /// <param name="backImageTransparentColor">Texture transparent color</param>
- /// <param name="backGradientStyle">Fill Gradient type </param>
- /// <param name="backSecondaryColor">Fill Gradient Second Color</param>
- /// <param name="borderColor">Border Color</param>
- /// <param name="borderWidth">Border Width</param>
- /// <param name="borderDashStyle">Border Style</param>
- /// <param name="shadow">True if shadow is active</param>
- /// <param name="doughnut">True if Doughnut is drawn instead of pie</param>
- /// <param name="doughnutRadius">Internal radius of the doughnut</param>
- /// <param name="pieDrawingStyle">Pie drawing style.</param>
- internal void DrawPieRel(
- RectangleF rect,
- float startAngle,
- float sweepAngle,
- Color backColor,
- ChartHatchStyle backHatchStyle,
- string backImage,
- ChartImageWrapMode backImageWrapMode,
- Color backImageTransparentColor,
- GradientStyle backGradientStyle,
- Color backSecondaryColor,
- Color borderColor,
- int borderWidth,
- ChartDashStyle borderDashStyle,
- bool shadow,
- bool doughnut,
- float doughnutRadius,
- PieDrawingStyle pieDrawingStyle
- )
- {
- Pen borderPen = null; // Pen
- Brush fillBrush; // Brush
- // Get absolute rectangle
- RectangleF absRect = GetAbsoluteRectangle( rect );
- if( doughnutRadius == 100.0 )
- {
- doughnut = false;
- }
- if( doughnutRadius == 0.0 )
- {
- return;
- }
- // Create Brush
- if( backHatchStyle != ChartHatchStyle.None )
- {
- // Create Hatch Brush
- fillBrush = GetHatchBrush( backHatchStyle, backColor, backSecondaryColor );
- }
- else if( backGradientStyle != GradientStyle.None )
- {
- // Create gradient brush
- if( backGradientStyle == GradientStyle.Center )
- {
- fillBrush = GetPieGradientBrush( absRect, backColor, backSecondaryColor );
- }
- else
- {
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddPie(absRect.X, absRect.Y, absRect.Width, absRect.Height, startAngle, sweepAngle);
- fillBrush = GetGradientBrush(path.GetBounds(), backColor, backSecondaryColor, backGradientStyle);
- }
- }
- }
- else if( backImage.Length > 0 && backImageWrapMode != ChartImageWrapMode.Unscaled && backImageWrapMode != ChartImageWrapMode.Scaled )
- {
- // Create textured brush
- fillBrush = GetTextureBrush(backImage, backImageTransparentColor, backImageWrapMode, backColor );
- }
- else
- {
- // Create solid brush
- fillBrush = new SolidBrush( backColor );
- }
- // Create border Pen
- borderPen = new Pen( borderColor, borderWidth );
-
- // Set a border line style
- borderPen.DashStyle = GetPenStyle( borderDashStyle );
- // Use rounded line joins
- borderPen.LineJoin = LineJoin.Round;
- // Draw Doughnut
- if( doughnut )
- {
- using (GraphicsPath path = new GraphicsPath())
- {
- path.AddArc(absRect.X + absRect.Width * doughnutRadius / 200 - 1, absRect.Y + absRect.Height * doughnutRadius / 200 - 1, absRect.Width - absRect.Width * doughnutRadius / 100 + 2, absRect.Height - absRect.Height * doughnutRadius / 100 + 2, startAngle, sweepAngle);
- path.AddArc(absRect.X, absRect.Y, absRect.Width, absRect.Height, startAngle + sweepAngle, -sweepAngle);
- path.CloseFigure();
- this.FillPath(fillBrush, path);
- // Draw Pie gradien effects
- this.DrawPieGradientEffects(pieDrawingStyle, absRect, startAngle, sweepAngle, doughnutRadius);
- // Draw Doughnut Border
- if (!shadow &&
- borderWidth > 0 &&
- borderDashStyle != ChartDashStyle.NotSet)
- {
- this.DrawPath(borderPen, path);
- }
- }
- }
- else // Draw Pie
- {
- // Draw Soft shadow for pie slice
- if( shadow && softShadows )
- {
- DrawPieSoftShadow( startAngle, sweepAngle, absRect, backColor );
- }
- else
- {
- // Fill Pie for normal shadow or colored pie slice
- this.FillPie( fillBrush, absRect.X, absRect.Y, absRect.Width, absRect.Height, startAngle, sweepAngle );
- // Draw Pie gradien effects
- this.DrawPieGradientEffects( pieDrawingStyle, absRect, startAngle, sweepAngle, -1f);
- }
-
- // Draw Pie Border
- if( !shadow &&
- borderWidth > 0 &&
- borderDashStyle != ChartDashStyle.NotSet)
- {
- this.DrawPie( borderPen, absRect.X, absRect.Y, absRect.Width, absRect.Height, startAngle, sweepAngle );
- }
- }
- // Dispose graphics objects
- if( borderPen != null )
- {
- borderPen.Dispose();
- }
- if( fillBrush != null )
- {
- fillBrush.Dispose();
- }
- }
- private void DrawPieGradientEffects(
- PieDrawingStyle pieDrawingStyle,
- RectangleF position,
- float startAngle,
- float sweepAngle,
- float doughnutRadius)
- {
- if(pieDrawingStyle == PieDrawingStyle.Concave)
- {
- // Calculate the size of the shadow. Note: For Doughnut chart shadow is drawn
- // twice on the outside and inside radius.
- float minSize = (float)Math.Min(position.Width, position.Height);
- float shadowSize = minSize * 0.05f;
-
- // Create brush path
- RectangleF gradientPath = position;
- gradientPath.Inflate(-shadowSize, -shadowSize);
- using(GraphicsPath brushPath = new GraphicsPath())
- {
- brushPath.AddEllipse(gradientPath);
- // Create shadow path
- using(GraphicsPath path = new GraphicsPath())
- {
- if(doughnutRadius < 0f)
- {
- path.AddPie(Rectangle.Round(gradientPath), startAngle, sweepAngle);
- }
- else
- {
- path.AddArc(
- gradientPath.X + position.Width * doughnutRadius /200 - 1 - shadowSize,
- gradientPath.Y + position.Height * doughnutRadius /200 - 1 - shadowSize,
- gradientPath.Width - position.Width * doughnutRadius / 100 + 2 + 2f * shadowSize,
- gradientPath.Height - position.Height * doughnutRadius / 100 + 2 + 2f * shadowSize,
- startAngle,
- sweepAngle );
- path.AddArc( gradientPath.X, gradientPath.Y, gradientPath.Width, gradientPath.Height, startAngle + sweepAngle, -sweepAngle );
- }
- // Create linear gradient brush
- gradientPath.Inflate(1f, 1f);
- using(LinearGradientBrush brush = new LinearGradientBrush(
- gradientPath,
- Color.Red,
- Color.Green,
- LinearGradientMode.Vertical) )
- {
- ColorBlend colorBlend = new ColorBlend(3);
- colorBlend.Colors[0] = Color.FromArgb(100, Color.Black);
- colorBlend.Colors[1] = Color.Transparent;
- colorBlend.Colors[2] = Color.FromArgb(140, Color.White);
- colorBlend.Positions[0] = 0f;
- colorBlend.Positions[1] = 0.5f;
- colorBlend.Positions[2] = 1f;
- brush.InterpolationColors = colorBlend;
- // Fill shadow
- this.FillPath( brush, path );
- }
- }
- }
- }
- else if(pieDrawingStyle == PieDrawingStyle.SoftEdge)
- {
- // Calculate the size of the shadow. Note: For Doughnut chart shadow is drawn
- // twice on the outside and inside radius.
- float minSize = (float)Math.Min(position.Width, position.Height);
- float shadowSize = minSize/10f;
- if(doughnutRadius > 0f)
- {
- shadowSize = (minSize * doughnutRadius / 100f) / 8f;
- }
- // Create brush path
- using(GraphicsPath brushPath = new GraphicsPath())
- {
- brushPath.AddEllipse(position);
- // Create shadow path
- using(GraphicsPath path = new GraphicsPath())
- {
- path.AddArc( position.X + shadowSize, position.Y + shadowSize, position.Width - shadowSize * 2f, position.Height - shadowSize * 2f, startAngle, sweepAngle );
- path.AddArc( position.X, position.Y, position.Width, position.Height, startAngle + sweepAngle, -sweepAngle );
- path.CloseFigure();
- // Create shadow brush
- using( PathGradientBrush brush = new PathGradientBrush(brushPath) )
- {
- brush.CenterColor = Color.Transparent;
- brush.SurroundColors = new Color[] { Color.FromArgb(100, Color.Black) };
- Blend blend = new Blend(3);
- blend.Positions[0] = 0f;
- blend.Factors[0] = 0f;
- blend.Positions[1] = shadowSize / (minSize / 2f);
- blend.Factors[1] = 1f;
- blend.Positions[2] = 1f;
- blend.Factors[2] = 1f;
- brush.Blend = blend;
- // Fill shadow
- this.FillPath( brush, path );
- }
- }
- // Draw inner shadow for the doughnut chart
- if(doughnutRadius > 0f)
- {
- // Create brush path
- using(GraphicsPath brushInsidePath = new GraphicsPath())
- {
- RectangleF innerPosition = position;
- innerPosition.Inflate(- position.Width * doughnutRadius / 200f + shadowSize, -position.Height * doughnutRadius / 200f + shadowSize);
- brushInsidePath.AddEllipse(innerPosition);
- // Create shadow path
- using(GraphicsPath path = new GraphicsPath())
- {
- path.AddArc( innerPosition.X + shadowSize, innerPosition.Y + shadowSize, innerPosition.Width - 2f * shadowSize, innerPosition.Height - 2f * shadowSize, startAngle, sweepAngle );
- path.AddArc( innerPosition.X, innerPosition.Y, innerPosition.Width, innerPosition.Height, startAngle + sweepAngle, -sweepAngle );
- path.CloseFigure();
- // Create shadow brush
- using( PathGradientBrush brushInner = new PathGradientBrush(brushInsidePath) )
- {
- brushInner.CenterColor = Color.FromArgb(100, Color.Black);
- brushInner.SurroundColors = new Color[] { Color.Transparent };
- Blend blend = new Blend(3);
- blend.Positions[0] = 0f;
- blend.Factors[0] = 0f;
- blend.Positions[1] = shadowSize / (innerPosition.Width / 2f);
- blend.Factors[1] = 1f;
- blend.Positions[2] = 1f;
- blend.Factors[2] = 1f;
- brushInner.Blend = blend;
- // Fill shadow
- this.FillPath( brushInner, path );
- }
- }
- }
- }
- }
- }
- }
- /// <summary>
- /// The soft shadow of the pie
- /// </summary>
- /// <param name="startAngle">Angle measured in degrees clockwise from the x-axis to the first side of the pie shape.</param>
- /// <param name="sweepAngle">Angle measured in degrees clockwise from the startAngle parameter to the second side of the pie shape.</param>
- /// <param name="absRect">Rectangle of the pie in absolute coordinates</param>
- /// <param name="backColor">Fill color</param>
- private void DrawPieSoftShadow( float startAngle, float sweepAngle, RectangleF absRect, Color backColor )
- {
- GraphicsPath path = new GraphicsPath();
-
- path.AddEllipse( absRect.X, absRect.Y, absRect.Width, absRect.Height );
- PathGradientBrush brush = new PathGradientBrush( path );
-
- Color[] colors = {
- Color.FromArgb( 0, backColor ),
- Color.FromArgb( backColor.A, backColor ),
- Color.FromArgb( backColor.A, backColor )};
- float[] relativePositions = {
- 0f,
- 0.05f,
- 1.0f}; // at the center point.
- ColorBlend colorBlend = new ColorBlend();
- colorBlend.Colors = colors;
- colorBlend.Positions = relativePositions;
- brush.InterpolationColors = colorBlend;
- this.FillPie( brush, absRect.X, absRect.Y, absRect.Width, absRect.Height, startAngle, sweepAngle );
- }
- #endregion
- #region Arrow Methods
- /// <summary>
- /// Draw Arrow.
- /// </summary>
- /// <param name="position">Position of the arrow</param>
- /// <param name="orientation">Orientation of the arrow - left, right, top, bottom </param>
- /// <param name="type">Arrow style: Triangle, Sharp Triangle, Lines</param>
- /// <param name="color">Color of the arrow</param>
- /// <param name="lineWidth">Line width</param>
- /// <param name="lineDashStyle">Line Dash style</param>
- /// <param name="shift">Distance from the chart area</param>
- /// <param name="size">Arrow size</param>
- internal void DrawArrowRel( PointF position, ArrowOrientation orientation, AxisArrowStyle type, Color color, int lineWidth, ChartDashStyle lineDashStyle, double shift, double size )
- {
- // Check if arrow should be drawn
- if(type == AxisArrowStyle.None)
- {
- return;
- }
- // Set a color
- using (SolidBrush brush = new SolidBrush(color))
- {
- PointF endPoint = PointF.Empty; // End point of axis line
- PointF[] points; // arrow points
- PointF absolutePosition; // Absolute position of axis
- absolutePosition = GetAbsolutePoint(position);
- // Arrow type is triangle
- if (type == AxisArrowStyle.Triangle)
- {
- points = GetArrowShape(absolutePosition, orientation, shift, size, type, ref endPoint);
- endPoint = GetRelativePoint(endPoint);
- // Draw center line
- DrawLineRel(color, lineWidth, lineDashStyle, position, endPoint);
- // Draw arrow
- this.FillPolygon(brush, points);
- }
- // Arrow type is sharp triangle
- else if (type == AxisArrowStyle.SharpTriangle)
- {
- points = GetArrowShape(absolutePosition, orientation, shift, size, type, ref endPoint);
- endPoint = GetRelativePoint(endPoint);
- // Draw center line
- DrawLineRel(color, lineWidth, lineDashStyle, position, endPoint);
- // Draw arrow
- this.FillPolygon(brush, points);
- }
- // Arrow type is 'Lines'
- else if (type == AxisArrowStyle.Lines)
- {
- points = GetArrowShape(absolutePosition, orientation, shift, size, type, ref endPoint);
- points[0] = GetRelativePoint(points[0]);
- points[1] = GetRelativePoint(points[1]);
- points[2] = GetRelativePoint(points[2]);
- endPoint = GetRelativePoint(endPoint);
- // Draw arrow
- DrawLineRel(color, lineWidth, lineDashStyle, position, endPoint);
- DrawLineRel(color, lineWidth, lineDashStyle, points[0], points[2]);
- DrawLineRel(color, lineWidth, lineDashStyle, points[1], points[2]);
- }
- }
- }
- /// <summary>
- /// This function calculates points for polygon, which represents
- /// shape of an arrow. There are four different orientations
- /// of arrow and three arrow types.
- /// </summary>
- /// <param name="position">Arrow position</param>
- /// <param name="orientation">Arrow orientation ( Left, Right, Top, Bottom )</param>
- /// <param name="shift">Distance from chart area to the arrow</param>
- /// <param name="size">Arrow size</param>
- /// <param name="type">Arrow style.</param>
- /// <param name="endPoint">End point of the axis and the beginning of arrow</param>
- /// <returns>Polygon points</returns>
- private PointF[] GetArrowShape( PointF position, ArrowOrientation orientation, double shift, double size, AxisArrowStyle type, ref PointF endPoint )
- {
- PointF[] points = new PointF[3]; // Polygon points
- double sharp; // Size for sharp triangle
- // Four different orientations for AxisArrowStyle
- switch( orientation )
- {
- // Top orientation
- case ArrowOrientation.Top:
- // Get absolute size for arrow
- // Arrow size has to have the same shape when width and height
- // are changed. When the picture is resized, width of the chart
- // picture is used only for arrow size.
- size = GetAbsoluteSize( new SizeF((float)size, (float)size) ).Width;
- shift = GetAbsoluteSize( new SizeF((float)shift,(float)shift) ).Height;
- // Size for sharp and regular triangle
- if( type == AxisArrowStyle.SharpTriangle )
- sharp = size * 4;
- else
- sharp = size * 2;
- points[0].X = position.X - (float)size;
- points[0].Y = position.Y - (float)shift;
- points[1].X = position.X + (float)size;
- points[1].Y = position.Y - (float)shift;
- points[2].X = position.X;
- points[2].Y = position.Y - (float)shift - (float)sharp;
- // End of the axis line
- endPoint.X = position.X;
- if( type == AxisArrowStyle.SharpTriangle || type == AxisArrowStyle.Triangle )
- endPoint.Y = points[1].Y;
- else
- endPoint.Y = points[2].Y;
-
- break;
- // Bottom orientation
- case ArrowOrientation.Bottom:
- // Get absolute size for arrow
- // Arrow size has to have the same shape when width and height
- // are changed. When the picture is resized, width of the chart
- // picture is used only for arrow size.
- size = GetAbsoluteSize( new SizeF((float)size, (float)size) ).Width;
- shift = GetAbsoluteSize( new SizeF((float)shift,(float)shift) ).Height;
- // Size for sharp and regular triangle
- if( type == AxisArrowStyle.SharpTriangle )
- sharp = size * 4;
- else
- sharp = size * 2;
- points[0].X = position.X - (float)size;
- points[0].Y = position.Y + (float)shift;
- points[1].X = position.X + (float)size;
- points[1].Y = position.Y + (float)shift;
- points[2].X = position.X;
- points[2].Y = position.Y + (float)shift + (float)sharp;
- // End of the axis line
- endPoint.X = position.X;
- if( type == AxisArrowStyle.SharpTriangle || type == AxisArrowStyle.Triangle )
- endPoint.Y = points[1].Y;
- else
- endPoint.Y = points[2].Y;
- break;
- // Left orientation
- case ArrowOrientation.Left:
- // Get absolute size for arrow
- size = GetAbsoluteSize( new SizeF((float)size, (float)size) ).Width;
- shift = GetAbsoluteSize( new SizeF((float)shift,(float)shift) ).Width;
- // Size for sharp and regular triangle
- if( type == AxisArrowStyle.SharpTriangle )
- sharp = size * 4;
- else
- sharp = size * 2;
- points[0].Y = position.Y - (float)size;
- points[0].X = position.X - (float)shift;
- points[1].Y = position.Y + (float)size;
- points[1].X = position.X - (float)shift;
- points[2].Y = position.Y;
- points[2].X = position.X - (float)shift - (float)sharp;
- // End of the axis line
- endPoint.Y = position.Y;
- if( type == AxisArrowStyle.SharpTriangle || type == AxisArrowStyle.Triangle )
- endPoint.X = points[1].X;
- else
- endPoint.X = points[2].X;
- break;
- // Right orientation
- case ArrowOrientation.Right:
- // Get absolute size for arrow
- size = GetAbsoluteSize( new SizeF((float)size, (float)size) ).Width;
- shift = GetAbsoluteSize( new SizeF((float)shift,(float)shift) ).Width;
- // Size for sharp and regular triangle
- if( type == AxisArrowStyle.SharpTriangle )
- sharp = size * 4;
- else
- sharp = size * 2;
- points[0].Y = position.Y - (float)size;
- points[0].X = position.X + (float)shift;
- points[1].Y = position.Y + (float)size;
- points[1].X = position.X + (float)shift;
- points[2].Y = position.Y;
- points[2].X = position.X + (float)shift + (float)sharp;
- // End of the axis line
- endPoint.Y = position.Y;
- if( type == AxisArrowStyle.SharpTriangle || type == AxisArrowStyle.Triangle )
- endPoint.X = points[1].X;
- else
- endPoint.X = points[2].X;
- break;
- }
- return points;
- }
- #endregion
-
- #region Other methods and properties
- /// <summary>
- /// Helper function that retrieves bar drawing style.
- /// </summary>
- /// <param name="point">Data point to get the drawing style for.</param>
- /// <returns>Bar drawing style.</returns>
- internal static BarDrawingStyle GetBarDrawingStyle(DataPoint point)
- {
- // Get column drawing style
- BarDrawingStyle barDrawingStyle = BarDrawingStyle.Default;
- string styleName = point[CustomPropertyName.DrawingStyle];
- if(styleName != null)
- {
- if(String.Compare(styleName, "Default", StringComparison.OrdinalIgnoreCase) == 0)
- {
- barDrawingStyle = BarDrawingStyle.Default;
- }
- else if (String.Compare(styleName, "Cylinder", StringComparison.OrdinalIgnoreCase) == 0)
- {
- barDrawingStyle = BarDrawingStyle.Cylinder;
- }
- else if (String.Compare(styleName, "Emboss", StringComparison.OrdinalIgnoreCase) == 0)
- {
- barDrawingStyle = BarDrawingStyle.Emboss;
- }
- else if (String.Compare(styleName, "LightToDark", StringComparison.OrdinalIgnoreCase) == 0)
- {
- barDrawingStyle = BarDrawingStyle.LightToDark;
- }
- else if (String.Compare(styleName, "Wedge", StringComparison.OrdinalIgnoreCase) == 0)
- {
- barDrawingStyle = BarDrawingStyle.Wedge;
- }
- else
- {
- throw (new InvalidOperationException(SR.ExceptionCustomAttributeValueInvalid(styleName, "DrawingStyle")));
- }
- }
- return barDrawingStyle;
- }
- /// <summary>
- /// Find rounding coordinates for a rectangle
- /// </summary>
- /// <param name="rect">Rectangle which has to be rounded</param>
- /// <returns>Rounded rectangle</returns>
- internal RectangleF Round(RectangleF rect)
- {
- float left = (float)Math.Round( (double)rect.Left );
- float right = (float)Math.Round( (double)rect.Right );
- float top = (float)Math.Round( (double)rect.Top );
- float bottom = (float)Math.Round( (double)rect.Bottom );
- return new RectangleF( left, top, right - left, bottom - top );
- }
-
- /// <summary>
- /// This method takes a given axis value for a specified axis and returns the relative pixel value.
- /// </summary>
- /// <param name="chartAreaName">Chart area name.</param>
- /// <param name="axis">An AxisName enum value that identifies the relevant axis.</param>
- /// <param name="axisValue">The axis value that needs to be converted to a relative pixel value.</param>
- /// <returns>The converted axis value, in relative pixel coordinates.</returns>
- public double GetPositionFromAxis( string chartAreaName, AxisName axis, double axisValue )
- {
- if( axis == AxisName.X )
- return _common.ChartPicture.ChartAreas[chartAreaName].AxisX.GetLinearPosition( axisValue );
- if( axis == AxisName.X2 )
- return _common.ChartPicture.ChartAreas[chartAreaName].AxisX2.GetLinearPosition( axisValue );
- if( axis == AxisName.Y )
- return _common.ChartPicture.ChartAreas[chartAreaName].AxisY.GetLinearPosition( axisValue );
- if( axis == AxisName.Y2 )
- return _common.ChartPicture.ChartAreas[chartAreaName].AxisY2.GetLinearPosition( axisValue );
- return 0;
- }
- /// <summary>
- /// Set picture size
- /// </summary>
- /// <param name="width">Width</param>
- /// <param name="height">Height</param>
- internal void SetPictureSize( int width, int height )
- {
- this._width = width;
- this._height = height;
- }
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="common">Common elements class</param>
- internal ChartGraphics(CommonElements common)
- {
- // Set Common elements
- this._common = common;
- base.Common = common;
- // Create a pen object
- _pen = new Pen(Color.Black);
- // Create a brush object
- _solidBrush = new SolidBrush(Color.Black);
- }
- /// <summary>
- /// Chart Graphics Anti alias mode
- /// </summary>
- internal AntiAliasingStyles AntiAliasing
- {
- get
- {
- return _antiAliasing;
- }
- set
- {
- _antiAliasing = value;
- // Graphics mode not set
- if( Graphics == null )
- return;
- // Convert Chart's anti alias enumeration to GDI+ SmoothingMode
- if( (_antiAliasing & AntiAliasingStyles.Graphics) == AntiAliasingStyles.Graphics )
- {
- this.SmoothingMode = SmoothingMode.AntiAlias;
- }
- else
- {
- this.SmoothingMode = SmoothingMode.None;
- }
- }
- }
- /// <summary>
- /// Gets reusable pen.
- /// </summary>
- internal Pen Pen
- {
- get { return _pen; }
- }
- /// <summary>
- /// Sets the clipping region of this Graphics object
- /// to the rectangle specified by a RectangleF structure.
- /// </summary>
- /// <param name="region">Region rectangle</param>
- internal void SetClip( RectangleF region )
- {
- this.SetClipAbs( GetAbsoluteRectangle( region ) );
- }
-
- #endregion
- #region Color manipulation methods
- /// <summary>
- /// Returns the gradient color from a gradient position.
- /// </summary>
- /// <param name="beginColor">The color from the gradient beginning</param>
- /// <param name="endColor">The color from the gradient end.</param>
- /// <param name="relativePosition">The relative position.</param>
- /// <returns>Result color.</returns>
- static internal Color GetGradientColor(Color beginColor, Color endColor, double relativePosition)
- {
- // Check if position is valid
- if(relativePosition < 0 || relativePosition > 1 || double.IsNaN(relativePosition))
- {
- return beginColor;
- }
-
- // Extracts Begin color
- int nBRed = beginColor.R;
- int nBGreen = beginColor.G;
- int nBBlue = beginColor.B;
- // Extracts End color
- int nERed = endColor.R;
- int nEGreen = endColor.G;
- int nEBlue = endColor.B;
- // Gradient positions for Red, Green and Blue colors
- double dRRed = nBRed + (nERed - nBRed) * relativePosition;
- double dRGreen = nBGreen + (nEGreen - nBGreen) * relativePosition;
- double dRBlue = nBBlue + (nEBlue - nBBlue) * relativePosition;
- // Make sure colors are in range from 0 to 255
- if(dRRed > 255.0)
- dRRed = 255.0;
- if(dRRed < 0.0)
- dRRed = 0.0;
- if(dRGreen > 255.0)
- dRGreen = 255.0;
- if(dRGreen < 0.0)
- dRGreen = 0.0;
- if(dRBlue > 255.0)
- dRBlue = 255.0;
- if(dRBlue < 0.0)
- dRBlue = 0.0;
- // Return a gradient color position
- return Color.FromArgb(beginColor.A, (int)dRRed, (int)dRGreen, (int)dRBlue);
- }
- #endregion
- #region RightToLeft
- /// <summary>
- /// Returns chart right to left flag
- /// </summary>
- internal bool IsRightToLeft
- {
- get
- {
- if (Common == null)
- {
- return false;
- }
- return Common.ChartPicture.RightToLeft == RightToLeft.Yes;
- }
- }
-
- #endregion //RightToLeft
- #region IDisposable Members
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- // Free up managed resources
- if (_pen != null)
- {
- _pen.Dispose();
- _pen = null;
- }
- if (_solidBrush != null)
- {
- _solidBrush.Dispose();
- _solidBrush = null;
- }
- if (_myMatrix != null)
- {
- _myMatrix.Dispose();
- _myMatrix = null;
- }
- }
- base.Dispose(disposing);
- }
- #endregion
- }
- }
|