lcvectororiginal.pas 117 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit LCVectorOriginal;
  3. {$mode objfpc}{$H+}
  4. {$modeswitch advancedrecords}
  5. interface
  6. uses
  7. Classes, SysUtils, BGRABitmap, BGRALayerOriginal, fgl, BGRAGradientOriginal, BGRABitmapTypes,
  8. BGRAPen, LCVectorialFill, LCResourceString, BGRASVGShapes, BGRASVGType,
  9. BGRASVG, BGRAUnits;
  10. const
  11. InfiniteRect : TRect = (Left: -MaxLongInt; Top: -MaxLongInt; Right: MaxLongInt; Bottom: MaxLongInt);
  12. EmptyTextureId = 0;
  13. DefaultShapeOutlineWidth = 2;
  14. MediumShapeCost = 100;
  15. //not translated because unexpected internal errors are not useful for users
  16. errDuplicateVectorClass = 'Duplicate class name "%1" for vector shape';
  17. errMergeNotAllowed = 'Merge not allowed';
  18. errCannotBeComputedFromShape = 'Cannot be computed from shape';
  19. errFillFieldMismatch = 'Fill field mismatch';
  20. errInvalidStoredPointer = 'Invalid stored pointer';
  21. errUndefinedContainer = 'Undefined container';
  22. errContainerAlreadyAssigned = 'Container already assigned';
  23. errDiffHandlerOnlyDuringUpdate = 'Diff handler expected only between BeginUpdate and EndUpdate';
  24. errUnexpectedNil = 'Unexpected nil value';
  25. errContainerMismatch = 'Container mismatch';
  26. errAlreadyRemovingShape = 'Already removing shape';
  27. errUnableToFindTexture = 'Unable to find texture';
  28. errErrorLoadingShape = 'Error loading shape';
  29. type
  30. TVectorOriginal = class;
  31. ArrayOfBGRABitmap = array of TBGRABitmap;
  32. TVectorShapeDiff = class;
  33. TShapeChangeEvent = procedure(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff) of object;
  34. TShapeEditingChangeEvent = procedure(ASender: TObject) of object;
  35. TShapeRemoveQuery = procedure(ASender: TObject; var AHandled: boolean) of object;
  36. TRenderBoundsOption = (rboAssumePenFill, rboAssumeBackFill);
  37. TRenderBoundsOptions = set of TRenderBoundsOption;
  38. TVectorShapeField = (vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill, vsfOutlineFill, vsfOutlineWidth);
  39. TVectorShapeFields = set of TVectorShapeField;
  40. TVectorShapeUsermode = (vsuEdit, vsuCreate, vsuEditPenFill, vsuEditBackFill, vsuEditOutlineFill,
  41. vsuCurveSetAuto, vsuCurveSetCurve, vsuCurveSetAngle,
  42. vsuEditText);
  43. TVectorShapeUsermodes = set of TVectorShapeUsermode;
  44. TVectorShape = class;
  45. TVectorShapes = specialize TFPGList<TVectorShape>;
  46. { TVectorShapeDiff }
  47. TVectorShapeDiff = class
  48. constructor Create(AStartShape: TVectorShape); virtual; abstract;
  49. procedure ComputeDiff(AEndShape: TVectorShape); virtual; abstract;
  50. procedure Apply(AStartShape: TVectorShape); virtual; abstract;
  51. procedure Unapply(AEndShape: TVectorShape); virtual; abstract;
  52. function CanAppend(ADiff: TVectorShapeDiff): boolean; virtual;
  53. procedure Append(ADiff: TVectorShapeDiff); virtual; abstract;
  54. function IsIdentity: boolean; virtual; abstract;
  55. end;
  56. TCustomMultiSelectionDiff = class(TVectorShapeDiff)
  57. protected
  58. function GetShapeCount: integer; virtual; abstract;
  59. function GetShapeId(AIndex: integer): integer; virtual; abstract;
  60. public
  61. property ShapeCount: integer read GetShapeCount;
  62. property ShapeId[AIndex: integer]: integer read GetShapeId;
  63. end;
  64. TVectorShapeDiffList = specialize TFPGList<TVectorShapeDiff>;
  65. TVectorShapeDiffAny = class of TVectorShapeDiff;
  66. { TVectorShapeComposedDiff }
  67. TVectorShapeComposedDiff = class(TVectorShapeDiff)
  68. protected
  69. FDiffs: array of TVectorShapeDiff;
  70. public
  71. constructor Create(ADiffs: TVectorShapeDiffList);
  72. constructor Create(ADiffs: array of TVectorShapeDiff);
  73. constructor Create({%H-}AStartShape: TVectorShape); override;
  74. destructor Destroy; override;
  75. procedure ComputeDiff({%H-}AEndShape: TVectorShape); override;
  76. procedure Apply(AStartShape: TVectorShape); override;
  77. procedure Unapply(AEndShape: TVectorShape); override;
  78. function CanAppend(ADiff: TVectorShapeDiff): boolean; override;
  79. procedure Append(ADiff: TVectorShapeDiff); override;
  80. function IsIdentity: boolean; override;
  81. function GetMultiselection: TCustomMultiSelectionDiff;
  82. end;
  83. { TVectorShapeEmbeddedFillDiff }
  84. TVectorShapeEmbeddedFillDiff = class(TVectorShapeDiff)
  85. protected
  86. FField: TVectorShapeField;
  87. FFillDiff: TCustomVectorialFillDiff;
  88. public
  89. constructor Create(AField: TVectorShapeField; AFillDiff: TCustomVectorialFillDiff);
  90. constructor Create({%H-}AStartShape: TVectorShape); override;
  91. destructor Destroy; override;
  92. procedure ComputeDiff({%H-}AEndShape: TVectorShape); override;
  93. procedure Apply(AStartShape: TVectorShape); override;
  94. procedure Unapply(AEndShape: TVectorShape); override;
  95. function CanAppend(ADiff: TVectorShapeDiff): boolean; override;
  96. procedure Append(ADiff: TVectorShapeDiff); override;
  97. function IsIdentity: boolean; override;
  98. end;
  99. { TVectorShapeCommonDiff }
  100. TVectorShapeCommonDiff = class(TVectorShapeDiff)
  101. protected
  102. FStartPenWidth: single;
  103. FStartPenStyle: TBGRAPenStyle;
  104. FStartOutlineWidth: single;
  105. FStartJoinStyle: TPenJoinStyle;
  106. FEndPenWidth: single;
  107. FEndPenStyle: TBGRAPenStyle;
  108. FEndOutlineWidth: single;
  109. FEndJoinStyle: TPenJoinStyle;
  110. public
  111. constructor Create(AStartShape: TVectorShape); override;
  112. procedure ComputeDiff(AEndShape: TVectorShape); override;
  113. procedure Apply(AStartShape: TVectorShape); override;
  114. procedure Unapply(AEndShape: TVectorShape); override;
  115. procedure Append(ADiff: TVectorShapeDiff); override;
  116. function IsIdentity: boolean; override;
  117. end;
  118. { TVectorShapeCommonFillDiff }
  119. TVectorShapeCommonFillDiff = class(TVectorShapeDiff)
  120. protected
  121. FStartPenFill: TVectorialFill;
  122. FStartBackFill: TVectorialFill;
  123. FStartOutlineFill: TVectorialFill;
  124. FEndPenFill: TVectorialFill;
  125. FEndBackFill: TVectorialFill;
  126. FEndOutlineFill: TVectorialFill;
  127. public
  128. constructor Create(AStartShape: TVectorShape); override;
  129. destructor Destroy; override;
  130. procedure ComputeDiff(AEndShape: TVectorShape); override;
  131. procedure Apply(AStartShape: TVectorShape); override;
  132. procedure Unapply(AEndShape: TVectorShape); override;
  133. procedure Append(ADiff: TVectorShapeDiff); override;
  134. function IsIdentity: boolean; override;
  135. end;
  136. IVectorMultishape = interface
  137. procedure ClearShapes;
  138. procedure AddShape(AShape: TVectorShape);
  139. procedure RemoveShape(AShape: TVectorShape);
  140. function ContainsShape(AShape: TVectorShape): boolean;
  141. function ShapeCount: integer;
  142. function GetShape(AIndex: integer): TVectorShape;
  143. function SetShapes(AShapes: TVectorShapes): boolean;
  144. function FrontShape: TVectorShape;
  145. function BackShape: TVectorShape;
  146. procedure SetOnSelectionChange(AHandler: TNotifyEvent);
  147. function GetOnSelectionChange: TNotifyEvent;
  148. end;
  149. { TShapeRenderStorage }
  150. TShapeRenderStorage = object
  151. persistent, temporary: TBGRACustomOriginalStorage;
  152. class function OpenOrCreate(ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer): TShapeRenderStorage; static;
  153. class function Open(ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer): TShapeRenderStorage; static;
  154. class procedure Discard(ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer); static;
  155. class function None: TShapeRenderStorage; static;
  156. function IsOpened: boolean;
  157. procedure Close;
  158. end;
  159. { TVectorShape }
  160. TVectorShape = class
  161. private
  162. FId: integer;
  163. FOnRemoveQuery: TShapeRemoveQuery;
  164. FRenderIteration: integer; // increased at each BeginUpdate
  165. FOnChange: TShapeChangeEvent;
  166. FOnEditingChange: TShapeEditingChangeEvent;
  167. FTemporaryStorage: TBGRACustomOriginalStorage;
  168. FUpdateCount, FUpdateEditingCount: integer;
  169. FBoundsBeforeUpdate: TRectF;
  170. FPenFill, FBackFill, FOutlineFill: TVectorialFill;
  171. FStoreTexturePointer: boolean;
  172. FStroker: TBGRAPenStroker;
  173. FUsermode: TVectorShapeUsermode;
  174. FContainer: TVectorOriginal;
  175. FRemoving: boolean;
  176. FDiffs: TVectorShapeDiffList;
  177. FFillBeforeChangeBounds: TRectF;
  178. function GetIsUpdating: boolean;
  179. procedure SetContainer(AValue: TVectorOriginal);
  180. function GetFill(var AFillVariable: TVectorialFill): TVectorialFill;
  181. procedure SetFill(var AFillVariable: TVectorialFill; AValue: TVectorialFill; AUpdate: boolean);
  182. procedure SetId(AValue: integer);
  183. protected
  184. FPenWidth: single;
  185. FOutlineWidth: single;
  186. FFillChangeWithoutUpdate: boolean;
  187. procedure BeginEditingUpdate;
  188. procedure EndEditingUpdate;
  189. procedure DoOnChange(ABoundsBefore: TRectF; ADiff: TVectorShapeDiff); virtual;
  190. function GetIsBack: boolean; virtual;
  191. function GetIsFront: boolean; virtual;
  192. function GetPenColor: TBGRAPixel; virtual;
  193. function GetPenWidth: single; virtual;
  194. function GetPenStyle: TBGRAPenStyle; virtual;
  195. function GetJoinStyle: TPenJoinStyle;
  196. function GetBackFill: TVectorialFill; virtual;
  197. function GetPenFill: TVectorialFill; virtual;
  198. function GetOutlineFill: TVectorialFill; virtual;
  199. function GetOutlineWidth: single; virtual;
  200. procedure SetPenColor(AValue: TBGRAPixel); virtual;
  201. procedure SetPenWidth(AValue: single); virtual;
  202. procedure SetPenStyle({%H-}AValue: TBGRAPenStyle); virtual;
  203. procedure SetJoinStyle(AValue: TPenJoinStyle); virtual;
  204. procedure SetBackFill(AValue: TVectorialFill); virtual;
  205. procedure SetPenFill(AValue: TVectorialFill); virtual;
  206. procedure SetOutlineFill(AValue: TVectorialFill); virtual;
  207. procedure SetOutlineWidth(AValue: single); virtual;
  208. procedure SetUsermode(AValue: TVectorShapeUsermode); virtual;
  209. function LoadTexture(AStorage: TBGRACustomOriginalStorage; AName: string): TBGRABitmap;
  210. procedure SaveTexture(AStorage: TBGRACustomOriginalStorage; AName: string; AValue: TBGRABitmap);
  211. procedure LoadFill(AStorage: TBGRACustomOriginalStorage; AObjectName: string; var AValue: TVectorialFill);
  212. procedure SaveFill(AStorage: TBGRACustomOriginalStorage; AObjectName: string; AValue: TVectorialFill);
  213. function ComputeStroke(APoints: ArrayOfTPointF; AClosed: boolean; AStrokeMatrix: TAffineMatrix): ArrayOfTPointF; virtual;
  214. function ComputeStrokeEnvelope(APoints: ArrayOfTPointF; AClosed: boolean; AWidth: single): ArrayOfTPointF; virtual;
  215. function GetStroker: TBGRAPenStroker;
  216. procedure FillChange({%H-}ASender: TObject; var ADiff: TCustomVectorialFillDiff); virtual;
  217. procedure FillBeforeChange({%H-}ASender: TObject); virtual;
  218. function OpenRenderStorage(ACreateIfNecessary: boolean): TShapeRenderStorage;
  219. procedure UpdateRenderStorage(ARenderBounds: TRect; AImage: TBGRACustomBitmap = nil);
  220. procedure DiscardRenderStorage;
  221. procedure RetrieveRenderStorage(AMatrix: TAffineMatrix; out ARenderBounds: TRect; out AImage: TBGRABitmap);
  222. function CanHaveRenderStorage: boolean;
  223. function AddDiffHandler(AClass: TVectorShapeDiffAny): TVectorShapeDiff;
  224. procedure AddFillDiffHandler(AFill: TVectorialFill; ADiff: TCustomVectorialFillDiff);
  225. function GetDiffHandler(AClass: TVectorShapeDiffAny): TVectorShapeDiff;
  226. function GetIsFollowingMouse: boolean; virtual;
  227. function GetPenVisible(AAssumePenFill: boolean = False): boolean; virtual;
  228. function GetPenVisibleNow: boolean;
  229. function GetBackVisible: boolean; virtual;
  230. function GetOutlineVisible: boolean; virtual;
  231. function AppendVectorialFillToSVGDefs(AFill: TVectorialFill; const AMatrix: TAffineMatrix;
  232. ADefs: TSVGDefine; ANamePrefix: string): string;
  233. procedure ApplyStrokeStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
  234. procedure ApplyFillStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
  235. property Stroker: TBGRAPenStroker read GetStroker;
  236. public
  237. constructor Create(AContainer: TVectorOriginal); virtual;
  238. class function CreateFromStorage(AStorage: TBGRACustomOriginalStorage; AContainer: TVectorOriginal): TVectorShape;
  239. destructor Destroy; override;
  240. function AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): TSVGElement; virtual; abstract;
  241. procedure BeginUpdate(ADiffHandler: TVectorShapeDiffAny=nil); virtual;
  242. procedure EndUpdate; virtual;
  243. procedure FillFit;
  244. procedure QuickDefine(constref APoint1,APoint2: TPointF); virtual; abstract;
  245. //one of the two Render functions must be overriden
  246. procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); overload; virtual;
  247. procedure Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix; ADraft: boolean); overload; virtual;
  248. function GetRenderBounds(ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; virtual; abstract;
  249. function SuggestGradientBox(AMatrix: TAffineMatrix): TAffineBox; virtual;
  250. function PointInShape(APoint: TPointF): boolean; overload; virtual; abstract;
  251. function PointInShape(APoint: TPointF; ARadius: single): boolean; overload; virtual; abstract;
  252. function PointInBack(APoint: TPointF): boolean; overload; virtual;
  253. function PointInPen(APoint: TPointF): boolean; overload; virtual;
  254. procedure ConfigureCustomEditor(AEditor: TBGRAOriginalEditor); virtual; abstract;
  255. procedure ConfigureEditor(AEditor: TBGRAOriginalEditor); virtual;
  256. procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); virtual;
  257. procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); virtual;
  258. procedure MouseMove({%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var {%H-}AHandled: boolean); virtual;
  259. procedure MouseDown({%H-}RightButton: boolean; {%H-}ClickCount: integer; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var {%H-}AHandled: boolean); virtual;
  260. procedure MouseUp({%H-}RightButton: boolean; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: single; var {%H-}ACursor: TOriginalEditorCursor; var {%H-}AHandled: boolean); virtual;
  261. procedure KeyDown({%H-}Shift: TShiftState; {%H-}Key: TSpecialKey; var {%H-}AHandled: boolean); virtual;
  262. procedure KeyUp({%H-}Shift: TShiftState; {%H-}Key: TSpecialKey; var {%H-}AHandled: boolean); virtual;
  263. procedure KeyPress({%H-}UTF8Key: string; var {%H-}AHandled: boolean); virtual;
  264. procedure BringToFront; virtual;
  265. procedure SendToBack; virtual;
  266. procedure MoveUp(APassNonIntersectingShapes: boolean); virtual;
  267. procedure MoveDown(APassNonIntersectingShapes: boolean); virtual;
  268. procedure Remove;
  269. procedure AlignHorizontally(AAlign: TAlignment; const AMatrix: TAffineMatrix; const ABounds: TRect); virtual;
  270. procedure AlignVertically(AAlign: TTextLayout; const AMatrix: TAffineMatrix; const ABounds: TRect); virtual;
  271. function GetAlignBounds(const ALayoutRect: TRect; const AMatrix: TAffineMatrix): TRectF; virtual;
  272. procedure AlignTransform(const AMatrix: TAffineMatrix); virtual;
  273. function Duplicate: TVectorShape;
  274. class function StorageClassName: RawByteString; virtual; abstract;
  275. function GetIsSlow(const {%H-}AMatrix: TAffineMatrix): boolean; virtual;
  276. function GetGenericCost: integer; virtual;
  277. function GetUsedTextures: ArrayOfBGRABitmap; virtual;
  278. function GetAsMultishape: IVectorMultishape; virtual;
  279. procedure Transform(const AMatrix: TAffineMatrix); virtual;
  280. procedure TransformFrame(const AMatrix: TAffineMatrix); virtual; abstract;
  281. procedure TransformFill(const AMatrix: TAffineMatrix; ABackOnly: boolean); virtual;
  282. function AllowShearTransform: boolean; virtual;
  283. function MultiFields: TVectorShapeFields; virtual;
  284. class function Fields: TVectorShapeFields; virtual;
  285. class function Usermodes: TVectorShapeUsermodes; virtual;
  286. function MultiUsermodes: TVectorShapeUsermodes; virtual;
  287. class function PreferPixelCentered: boolean; virtual;
  288. class function CreateEmpty: boolean; virtual; //create shape even if empty?
  289. property OnChange: TShapeChangeEvent read FOnChange write FOnChange;
  290. property OnEditingChange: TShapeEditingChangeEvent read FOnEditingChange write FOnEditingChange;
  291. property OnRemoveQuery: TShapeRemoveQuery read FOnRemoveQuery write FOnRemoveQuery;
  292. property PenColor: TBGRAPixel read GetPenColor write SetPenColor;
  293. property PenFill: TVectorialFill read GetPenFill write SetPenFill;
  294. property BackFill: TVectorialFill read GetBackFill write SetBackFill;
  295. property OutlineFill: TVectorialFill read GetOutlineFill write SetOutlineFill;
  296. property PenWidth: single read GetPenWidth write SetPenWidth;
  297. property PenStyle: TBGRAPenStyle read GetPenStyle write SetPenStyle;
  298. property OutlineWidth: single read GetOutlineWidth write SetOutlineWidth;
  299. property JoinStyle: TPenJoinStyle read GetJoinStyle write SetJoinStyle;
  300. property Usermode: TVectorShapeUsermode read FUsermode write SetUsermode;
  301. property Container: TVectorOriginal read FContainer write SetContainer;
  302. property TemporaryStorage: TBGRACustomOriginalStorage read FTemporaryStorage write FTemporaryStorage;
  303. property IsFront: boolean read GetIsFront;
  304. property IsBack: boolean read GetIsBack;
  305. property IsRemoving: boolean read FRemoving;
  306. property Id: integer read FId write SetId;
  307. property IsFollowingMouse: boolean read GetIsFollowingMouse;
  308. property IsUpdating: boolean read GetIsUpdating;
  309. property BackVisible: boolean read GetBackVisible;
  310. property PenVisible: boolean read GetPenVisibleNow;
  311. property OutlineVisible: boolean read GetOutlineVisible;
  312. end;
  313. TVectorShapeAny = class of TVectorShape;
  314. TVectorOriginalSelectShapeEvent = procedure(ASender: TObject; AShape: TVectorShape; APreviousShape: TVectorShape) of object;
  315. { TVectorOriginalShapeDiff }
  316. TVectorOriginalShapeDiff = class(TBGRAOriginalDiff)
  317. protected
  318. FShapeIndex: integer;
  319. FShapeDiff: TVectorShapeDiff;
  320. function GetShape(AOriginal: TBGRALayerCustomOriginal): TVectorShape;
  321. public
  322. constructor Create(AShapeIndex: integer; AShapeDiff: TVectorShapeDiff);
  323. destructor Destroy; override;
  324. procedure Apply(AOriginal: TBGRALayerCustomOriginal); override;
  325. procedure Unapply(AOriginal: TBGRALayerCustomOriginal); override;
  326. function CanAppend(ADiff: TBGRAOriginalDiff): boolean; override;
  327. procedure Append(ADiff: TBGRAOriginalDiff); override;
  328. function IsIdentity: boolean; override;
  329. end;
  330. { TVectorOriginalShapeRangeDiff }
  331. TVectorOriginalShapeRangeDiff = class(TBGRAOriginalDiff)
  332. protected
  333. FRangeStart: integer;
  334. FShapesBefore, FShapesAfter: TVectorShapes;
  335. FSelectedShapeBefore, FSelectedShapeAfter: integer;
  336. public
  337. constructor Create(ARangeStart: integer; AShapesBefore, AShapesAfter: TVectorShapes;
  338. ASelectedShapeBefore, ASelectedShapeAfter: integer);
  339. destructor Destroy; override;
  340. procedure Apply(AOriginal: TBGRALayerCustomOriginal); override;
  341. procedure Unapply(AOriginal: TBGRALayerCustomOriginal); override;
  342. function CanAppend({%H-}ADiff: TBGRAOriginalDiff): boolean; override;
  343. procedure Append({%H-}ADiff: TBGRAOriginalDiff); override;
  344. function IsIdentity: boolean; override;
  345. end;
  346. { TVectorOriginalMoveShapeToIndexDiff }
  347. TVectorOriginalMoveShapeToIndexDiff = class(TBGRAOriginalDiff)
  348. protected
  349. FFromIndex,FToIndex: array of integer;
  350. FShapeCount: integer;
  351. procedure InternalMove(AOriginal: TBGRALayerCustomOriginal; AFromIndex,AToIndex: array of integer; ASendDiff: boolean);
  352. public
  353. constructor Create(AFromIndex,AToIndex: array of integer);
  354. procedure Apply(AOriginal: TBGRALayerCustomOriginal); overload; override;
  355. procedure Apply(AOriginal: TBGRALayerCustomOriginal; ASendDiff: boolean); overload;
  356. procedure Unapply(AOriginal: TBGRALayerCustomOriginal); override;
  357. function CanAppend(ADiff: TBGRAOriginalDiff): boolean; override;
  358. procedure Append(ADiff: TBGRAOriginalDiff); override;
  359. function IsIdentity: boolean; override;
  360. end;
  361. TVectorOriginalEditor = class;
  362. { TVectorOriginal }
  363. TVectorOriginal = class(TBGRALayerCustomOriginal)
  364. private
  365. procedure MultiSelection_SelectionChange(Sender: TObject);
  366. protected
  367. FShapes: TVectorShapes;
  368. FDeletedShapes: TVectorShapes;
  369. FSelectedShape: TVectorShape;
  370. FMultiselection: TVectorShape;
  371. FFrozenShapesUnderSelection,
  372. FFrozenShapesOverSelection: TBGRABitmap;
  373. FFrozenShapesUnderBounds,
  374. FFrozenShapesOverBounds: TRect;
  375. FFrozenShapesRenderOffset: TPoint;
  376. FFrozenShapesComputed: boolean;
  377. FFrozenShapeMatrix: TAffineMatrix;
  378. FUnfrozenRangeStart, FUnfrozenRangeEnd: integer;
  379. FOnSelectShape: TVectorOriginalSelectShapeEvent;
  380. FTextures: array of record
  381. Bitmap: TBGRABitmap;
  382. Id, Counter: integer;
  383. end;
  384. FTextureCount: integer;
  385. FLastTextureId: integer;
  386. FLastShapeId: integer;
  387. procedure FreeDeletedShapes;
  388. procedure OnShapeChange(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff);
  389. procedure OnShapeEditingChange({%H-}ASender: TObject);
  390. procedure DiscardFrozenShapes;
  391. function GetShape(AIndex: integer): TVectorShape;
  392. function GetTextureId(ABitmap: TBGRABitmap): integer;
  393. function IndexOfTexture(AId: integer): integer;
  394. procedure AddTextureWithId(ATexture: TBGRABitmap; AId: integer);
  395. procedure ClearTextures;
  396. function GetShapeCount: integer;
  397. function OpenShapeRenderStorage(AShapeIndex: integer; ACreate: boolean): TBGRACustomOriginalStorage;
  398. procedure DiscardUnusedRenderStorage;
  399. function InternalInsertShape(AShape: TVectorShape; AIndex: integer): TRectF;
  400. function InternalInsertShapeRange(AShapes: TVectorShapes; AIndex: integer): TRectF;
  401. function InternalDeleteShapeRange(AStartIndex,ACount: integer): TRectF;
  402. function GetNewShapeId: integer;
  403. public
  404. constructor Create; override;
  405. destructor Destroy; override;
  406. procedure Clear;
  407. function ConvertToSVG(const AMatrix: TAffineMatrix; out AOffset: TPoint): TObject; override;
  408. function AddTexture(ATexture: TBGRABitmap): integer;
  409. function GetTexture(AId: integer): TBGRABitmap;
  410. procedure DiscardUnusedTextures;
  411. function AddShape(AShape: TVectorShape): integer; overload;
  412. function AddShape(AShape: TVectorShape; AUsermode: TVectorShapeUsermode): integer; overload;
  413. function AddShapes(AShapes: TVectorShapes): integer;
  414. procedure InsertShape(AShape: TVectorShape; AIndex: integer);
  415. procedure InsertShapes(AShapes: TVectorShapes; AIndex: integer);
  416. function RemoveShape(AShape: TVectorShape): boolean;
  417. procedure DeleteShape(AIndex: integer);
  418. procedure DeleteShapeRange(AStartIndex,ACount: integer);
  419. procedure ReplaceShape(AIndex: integer; ANewShape: TVectorShape);
  420. procedure ReplaceShapeRange(AStartIndex: integer; ACountBefore: integer; ANewShapes: TVectorShapes);
  421. function SelectShapes(AShapes: TVectorShapes): boolean;
  422. function SelectShape(AIndex: integer; AToggle: boolean = false): boolean; overload;
  423. function SelectShape(AShape: TVectorShape; AToggle: boolean = false): boolean; overload;
  424. function DeselectShapes: boolean;
  425. procedure DeselectShape(AIndex: integer); overload;
  426. procedure DeselectShape(AShape: TVectorShape); overload;
  427. function GetShapesCost: integer;
  428. function PreferDraftMode(AEditor: TBGRAOriginalEditor; const AMatrix: TAffineMatrix): boolean;
  429. function MouseClick(APoint: TPointF; ARadius: single; AToggle: boolean): boolean;
  430. procedure Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix; ADraft: boolean); override;
  431. procedure ConfigureEditor(AEditor: TBGRAOriginalEditor); override;
  432. function CreateEditor: TBGRAOriginalEditor; override;
  433. function GetRenderBounds(ADestRect: TRect; {%H-}AMatrix: TAffineMatrix): TRect; overload; override;
  434. function GetRenderBounds(ADestRect: TRect; {%H-}AMatrix: TAffineMatrix; AStartIndex, AEndIndex: integer): TRect; overload;
  435. function GetAlignBounds(ADestRect: TRect; {%H-}AMatrix: TAffineMatrix): TRect;
  436. procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
  437. procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
  438. function IndexOfShape(AShape: TVectorShape): integer;
  439. function FindShapeById(AId: integer): TVectorShape;
  440. procedure MoveShapeToIndex(AFromIndex, AToIndex: integer); overload;
  441. procedure MoveShapeToIndex(AFromIndex, AToIndex: array of integer); overload;
  442. class function StorageClassName: RawByteString; override;
  443. class function CanConvertToSVG: boolean; override;
  444. property OnSelectShape: TVectorOriginalSelectShapeEvent read FOnSelectShape write FOnSelectShape;
  445. property SelectedShape: TVectorShape read FSelectedShape;
  446. property ShapeCount: integer read GetShapeCount;
  447. property Shape[AIndex: integer]: TVectorShape read GetShape;
  448. end;
  449. { TVectorOriginalEditor }
  450. TVectorOriginalEditor = class(TBGRAOriginalEditor)
  451. protected
  452. FOriginal: TVectorOriginal;
  453. FLabels: array of record
  454. Coord: TPointF;
  455. Text: string;
  456. HorizAlign: TAlignment;
  457. VertAlign: TTextLayout;
  458. Padding: integer;
  459. end;
  460. function NiceText(ADest: TBGRABitmap; x, y: integer; const ALayoutRect: TRect;
  461. AText: string; AHorizAlign: TAlignment; AVertAlign: TTextLayout;
  462. APadding: integer): TRect;
  463. public
  464. constructor Create(AOriginal: TVectorOriginal);
  465. procedure Clear; override;
  466. function Render(ADest: TBGRABitmap; const ALayoutRect: TRect): TRect; override;
  467. function GetRenderBounds(const ALayoutRect: TRect): TRect; override;
  468. procedure AddLabel(const ACoord: TPointF; AText: string; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
  469. procedure AddLabel(APointIndex: integer; AText: string; AHorizAlign: TAlignment; AVertAlign: TTextLayout);
  470. procedure MouseMove(Shift: TShiftState; ViewX, ViewY: single; out ACursor: TOriginalEditorCursor; out AHandled: boolean); override;
  471. procedure MouseDown(RightButton: boolean; Shift: TShiftState; ViewX, ViewY: single; out ACursor: TOriginalEditorCursor; out AHandled: boolean); override;
  472. procedure MouseUp(RightButton: boolean; {%H-}Shift: TShiftState; {%H-}ViewX, {%H-}ViewY: single; out ACursor: TOriginalEditorCursor; out AHandled: boolean); override;
  473. procedure KeyDown(Shift: TShiftState; Key: TSpecialKey; out AHandled: boolean); override;
  474. procedure KeyUp(Shift: TShiftState; Key: TSpecialKey; out AHandled: boolean); override;
  475. procedure KeyPress(UTF8Key: string; out AHandled: boolean); override;
  476. end;
  477. function MatrixForPixelCentered(const AMatrix: TAffineMatrix): TAffineMatrix;
  478. procedure RegisterVectorShape(AClass: TVectorShapeAny);
  479. function GetVectorShapeByStorageClassName(AName: string): TVectorShapeAny;
  480. var
  481. VectorMultiselectionFactory: TVectorShapeAny;
  482. implementation
  483. uses math, BGRATransform, BGRAFillInfo, BGRAGraphics, BGRAPath, Types,
  484. BGRAText, BGRATextFX, BGRALayers;
  485. function MatrixForPixelCentered(const AMatrix: TAffineMatrix): TAffineMatrix;
  486. begin
  487. result := AffineMatrixTranslation(-0.5,-0.5) * AMatrix * AffineMatrixTranslation(0.5,0.5);
  488. end;
  489. var
  490. VectorShapeClasses: array of TVectorShapeAny;
  491. function GetVectorShapeByStorageClassName(AName: string): TVectorShapeAny;
  492. var
  493. i: Integer;
  494. begin
  495. for i := 0 to high(VectorShapeClasses) do
  496. if VectorShapeClasses[i].StorageClassName = AName then exit(VectorShapeClasses[i]);
  497. exit(nil);
  498. end;
  499. procedure RegisterVectorShape(AClass: TVectorShapeAny);
  500. var
  501. i: Integer;
  502. begin
  503. for i := 0 to high(VectorShapeClasses) do
  504. if VectorShapeClasses[i]=AClass then exit;
  505. if Assigned(GetVectorShapeByStorageClassName(AClass.StorageClassName)) then
  506. raise exception.Create(StringReplace(errDuplicateVectorClass, '%1', AClass.StorageClassName, []));
  507. setlength(VectorShapeClasses, length(VectorShapeClasses)+1);
  508. VectorShapeClasses[high(VectorShapeClasses)] := AClass;
  509. end;
  510. { TVectorOriginalMoveShapeToIndexDiff }
  511. type
  512. TMovedShape = record
  513. shape: TVectorShape;
  514. targetIndex: integer;
  515. class operator =(const ms1, ms2: TMovedShape): boolean;
  516. end;
  517. { TShapeRenderStorage }
  518. class function TShapeRenderStorage.OpenOrCreate(ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer): TShapeRenderStorage;
  519. begin
  520. result.persistent := ARenderStorage.OpenObject(inttostr(AShapeId));
  521. if result.persistent = nil then
  522. result.persistent := ARenderStorage.CreateObject(inttostr(AShapeId));
  523. result.temporary := result.persistent.OpenObject(RenderTempSubDirectory);
  524. if result.temporary = nil then
  525. result.temporary := result.persistent.CreateObject(RenderTempSubDirectory);
  526. end;
  527. class function TShapeRenderStorage.Open(
  528. ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer): TShapeRenderStorage;
  529. begin
  530. result.persistent := ARenderStorage.OpenObject(inttostr(AShapeId));
  531. if Assigned(result.persistent) then
  532. result.temporary := result.persistent.OpenObject(RenderTempSubDirectory)
  533. else
  534. result.temporary := nil;
  535. end;
  536. class procedure TShapeRenderStorage.Discard(
  537. ARenderStorage: TBGRACustomOriginalStorage; AShapeId: integer);
  538. begin
  539. ARenderStorage.RemoveObject(inttostr(AShapeId));
  540. end;
  541. class function TShapeRenderStorage.None: TShapeRenderStorage;
  542. begin
  543. result.persistent := nil;
  544. result.temporary := nil;
  545. end;
  546. function TShapeRenderStorage.IsOpened: boolean;
  547. begin
  548. result := (persistent <> nil) or (temporary <> nil);
  549. end;
  550. procedure TShapeRenderStorage.Close;
  551. var
  552. freeTemp: Boolean;
  553. begin
  554. if Assigned(temporary) then
  555. begin
  556. freeTemp := temporary.Empty;
  557. FreeAndNil(temporary);
  558. if freeTemp and Assigned(persistent) then persistent.RemoveObject(RenderTempSubDirectory);
  559. end;
  560. FreeAndNil(persistent);
  561. end;
  562. class operator TMovedShape.=(const ms1, ms2: TMovedShape): boolean;
  563. begin
  564. result := (ms1.shape = ms2.shape) and (ms1.targetIndex = ms2.targetIndex);
  565. end;
  566. function CompareMovedShapeTargetIndex(const ms1, ms2: TMovedShape): integer;
  567. begin
  568. result := ms1.targetIndex - ms2.targetIndex;
  569. end;
  570. procedure TVectorOriginalMoveShapeToIndexDiff.InternalMove(AOriginal: TBGRALayerCustomOriginal; AFromIndex,
  571. AToIndex: array of integer; ASendDiff: boolean);
  572. type
  573. TMovedShapeList = specialize TFPGList<TMovedShape>;
  574. var
  575. movedShapes: TMovedShapeList;
  576. ms: TMovedShape;
  577. r: TRectF;
  578. i: Integer;
  579. orig: TVectorOriginal;
  580. begin
  581. if FShapeCount = 0 then exit;
  582. orig := AOriginal as TVectorOriginal;
  583. movedShapes := TMovedShapeList.Create;
  584. for i := 0 to FShapeCount-1 do
  585. begin
  586. ms.shape := orig.Shape[AFromIndex[i]];
  587. ms.targetIndex:= AToIndex[i];
  588. movedShapes.Add(ms);
  589. end;
  590. movedShapes.Sort(@CompareMovedShapeTargetIndex);
  591. if movedShapes[0].targetIndex > orig.IndexOfShape(movedShapes[0].shape) then
  592. begin
  593. for i := movedShapes.Count-1 downto 0 do
  594. orig.FShapes.Move(orig.IndexOfShape(movedShapes[i].shape), movedShapes[i].targetIndex);
  595. end else
  596. for i := 0 to movedShapes.Count-1 do
  597. orig.FShapes.Move(orig.IndexOfShape(movedShapes[i].shape), movedShapes[i].targetIndex);
  598. orig.DiscardFrozenShapes;
  599. r := EmptyRectF;
  600. for i := 0 to movedShapes.Count-1 do
  601. r := r.Union(movedShapes[i].shape.GetRenderBounds(InfiniteRect, AffineMatrixIdentity), true);
  602. movedShapes.Free;
  603. if ASendDiff then orig.NotifyChange(r,self)
  604. else orig.NotifyChange(r);
  605. end;
  606. constructor TVectorOriginalMoveShapeToIndexDiff.Create(AFromIndex,
  607. AToIndex: array of integer);
  608. var
  609. i: Integer;
  610. begin
  611. if length(AFromIndex) <> length(AToIndex) then
  612. raise exception.Create('Dimension mismatch');
  613. FShapeCount:= length(AFromIndex);
  614. setlength(FFromIndex, FShapeCount);
  615. setlength(FToIndex, FShapeCount);
  616. for i := 0 to FShapeCount-1 do
  617. begin
  618. FFromIndex[i] := AFromIndex[i];
  619. FToIndex[i] := AToIndex[i];
  620. end;
  621. end;
  622. procedure TVectorOriginalMoveShapeToIndexDiff.Apply(
  623. AOriginal: TBGRALayerCustomOriginal);
  624. begin
  625. Apply(AOriginal, False);
  626. end;
  627. procedure TVectorOriginalMoveShapeToIndexDiff.Apply(
  628. AOriginal: TBGRALayerCustomOriginal; ASendDiff: boolean);
  629. begin
  630. InternalMove(AOriginal, FFromIndex, FToIndex, ASendDiff);
  631. end;
  632. procedure TVectorOriginalMoveShapeToIndexDiff.Unapply(
  633. AOriginal: TBGRALayerCustomOriginal);
  634. begin
  635. InternalMove(AOriginal, FToIndex, FFromIndex, False);
  636. end;
  637. function TVectorOriginalMoveShapeToIndexDiff.CanAppend(ADiff: TBGRAOriginalDiff): boolean;
  638. var
  639. other: TVectorOriginalMoveShapeToIndexDiff;
  640. i: Integer;
  641. begin
  642. if ADiff is TVectorOriginalMoveShapeToIndexDiff then
  643. begin
  644. other := TVectorOriginalMoveShapeToIndexDiff(ADiff);
  645. if other.FShapeCount <> FShapeCount then exit(false);
  646. for i := 0 to FShapeCount-1 do
  647. if other.FFromIndex[i] <> FToIndex[i] then exit(false);
  648. result := true;
  649. end else
  650. result := false;
  651. end;
  652. procedure TVectorOriginalMoveShapeToIndexDiff.Append(ADiff: TBGRAOriginalDiff);
  653. var
  654. other: TVectorOriginalMoveShapeToIndexDiff;
  655. i: Integer;
  656. begin
  657. if CanAppend(ADiff) then
  658. begin
  659. other := ADiff as TVectorOriginalMoveShapeToIndexDiff;
  660. for i := 0 to FShapeCount-1 do
  661. FToIndex[i] := other.FToIndex[i];
  662. end;
  663. end;
  664. function TVectorOriginalMoveShapeToIndexDiff.IsIdentity: boolean;
  665. var
  666. i: Integer;
  667. begin
  668. for i := 0 to FShapeCount-1 do
  669. if FFromIndex[i] <> FToIndex[i] then
  670. exit(false);
  671. result := true;
  672. end;
  673. { TVectorShapeDiff }
  674. function TVectorShapeDiff.CanAppend(ADiff: TVectorShapeDiff): boolean;
  675. begin
  676. result := (ADiff.ClassType = self.ClassType);
  677. end;
  678. { TVectorShapeCommonFillDiff }
  679. constructor TVectorShapeCommonFillDiff.Create(AStartShape: TVectorShape);
  680. begin
  681. with AStartShape do
  682. begin
  683. if Assigned(FPenFill) and (FPenFill.FillType <> vftNone) then
  684. FStartPenFill := FPenFill.Duplicate;
  685. if Assigned(FBackFill) and (FBackFill.FillType <> vftNone) then
  686. FStartBackFill := FBackFill.Duplicate;
  687. if Assigned(FOutlineFill) and (FOutlineFill.FillType <> vftNone) then
  688. FStartOutlineFill := FOutlineFill.Duplicate;
  689. end;
  690. end;
  691. destructor TVectorShapeCommonFillDiff.Destroy;
  692. begin
  693. FStartPenFill.Free;
  694. FStartBackFill.Free;
  695. FStartOutlineFill.Free;
  696. FEndPenFill.Free;
  697. FEndBackFill.Free;
  698. FEndOutlineFill.Free;
  699. inherited Destroy;
  700. end;
  701. procedure TVectorShapeCommonFillDiff.ComputeDiff(AEndShape: TVectorShape);
  702. begin
  703. with AEndShape do
  704. begin
  705. if Assigned(FPenFill) and (FPenFill.FillType <> vftNone) then
  706. FEndPenFill := FPenFill.Duplicate;
  707. if Assigned(FBackFill) and (FBackFill.FillType <> vftNone) then
  708. FEndBackFill := FBackFill.Duplicate;
  709. if Assigned(FOutlineFill) and (FOutlineFill.FillType <> vftNone) then
  710. FEndOutlineFill := FOutlineFill.Duplicate;
  711. end;
  712. end;
  713. procedure TVectorShapeCommonFillDiff.Apply(AStartShape: TVectorShape);
  714. begin
  715. with AStartShape do
  716. begin
  717. BeginUpdate;
  718. SetFill(FPenFill, FEndPenFill, False);
  719. SetFill(FBackFill, FEndBackFill, False);
  720. SetFill(FOutlineFill, FEndOutlineFill, False);
  721. EndUpdate;
  722. end;
  723. end;
  724. procedure TVectorShapeCommonFillDiff.Unapply(AEndShape: TVectorShape);
  725. begin
  726. with AEndShape do
  727. begin
  728. BeginUpdate;
  729. SetFill(FPenFill, FStartPenFill, False);
  730. SetFill(FBackFill, FStartBackFill, False);
  731. SetFill(FOutlineFill, FStartOutlineFill, False);
  732. EndUpdate;
  733. end;
  734. end;
  735. procedure TVectorShapeCommonFillDiff.Append(ADiff: TVectorShapeDiff);
  736. var
  737. next: TVectorShapeCommonFillDiff;
  738. begin
  739. next := ADiff as TVectorShapeCommonFillDiff;
  740. if Assigned(next.FEndPenFill) then
  741. begin
  742. if FEndPenFill = nil then FEndPenFill := TVectorialFill.Create;
  743. FEndPenFill.Assign(next.FEndPenFill);
  744. end else FreeAndNil(FEndPenFill);
  745. if Assigned(next.FEndBackFill) then
  746. begin
  747. if FEndBackFill = nil then FEndBackFill := TVectorialFill.Create;
  748. FEndBackFill.Assign(next.FEndBackFill);
  749. end else FreeAndNil(FEndBackFill);
  750. if Assigned(next.FEndOutlineFill) then
  751. begin
  752. if FEndOutlineFill = nil then FEndOutlineFill := TVectorialFill.Create;
  753. FEndOutlineFill.Assign(next.FEndOutlineFill);
  754. end else FreeAndNil(FEndOutlineFill);
  755. end;
  756. function TVectorShapeCommonFillDiff.IsIdentity: boolean;
  757. begin
  758. result := TVectorialFill.Equal(FStartPenFill, FEndPenFill) and
  759. TVectorialFill.Equal(FStartBackFill, FEndBackFill) and
  760. TVectorialFill.Equal(FStartOutlineFill, FEndOutlineFill);
  761. end;
  762. { TVectorOriginalShapeRangeDiff }
  763. constructor TVectorOriginalShapeRangeDiff.Create(ARangeStart: integer;
  764. AShapesBefore, AShapesAfter: TVectorShapes;
  765. ASelectedShapeBefore, ASelectedShapeAfter: integer);
  766. var
  767. i: Integer;
  768. begin
  769. FRangeStart := ARangeStart;
  770. FShapesBefore := TVectorShapes.Create;
  771. if Assigned(AShapesBefore) then
  772. for i := 0 to AShapesBefore.Count-1 do
  773. FShapesBefore.Add(AShapesBefore[i].Duplicate);
  774. FSelectedShapeBefore:= ASelectedShapeBefore;
  775. FShapesAfter := TVectorShapes.Create;
  776. if Assigned(AShapesAfter) then
  777. for i := 0 to AShapesAfter.Count-1 do
  778. FShapesAfter.Add(AShapesAfter[i].Duplicate);
  779. FSelectedShapeAfter:= ASelectedShapeAfter;
  780. end;
  781. destructor TVectorOriginalShapeRangeDiff.Destroy;
  782. var
  783. i: Integer;
  784. begin
  785. for i := 0 to FShapesBefore.Count-1 do FShapesBefore[i].Free;
  786. FShapesBefore.Free;
  787. for i := 0 to FShapesAfter.Count-1 do FShapesAfter[i].Free;
  788. FShapesAfter.Free;
  789. inherited Destroy;
  790. end;
  791. procedure TVectorOriginalShapeRangeDiff.Apply(
  792. AOriginal: TBGRALayerCustomOriginal);
  793. var
  794. i: Integer;
  795. rRemove, rInsert: TRectF;
  796. insCopy: TVectorShapes;
  797. begin
  798. with (AOriginal as TVectorOriginal) do
  799. begin
  800. rRemove := InternalDeleteShapeRange(FRangeStart, FShapesBefore.Count);
  801. insCopy := TVectorShapes.Create;
  802. for i := 0 to FShapesAfter.Count-1 do insCopy.Add(FShapesAfter[i].Duplicate);
  803. rInsert := InternalInsertShapeRange(insCopy, FRangeStart);
  804. insCopy.Free;
  805. NotifyChange(TRectF.Union(rRemove,rInsert,True));
  806. SelectShape(FSelectedShapeAfter);
  807. end;
  808. end;
  809. procedure TVectorOriginalShapeRangeDiff.Unapply(
  810. AOriginal: TBGRALayerCustomOriginal);
  811. var
  812. i: Integer;
  813. rRemove, rInsert: TRectF;
  814. insCopy: TVectorShapes;
  815. begin
  816. with (AOriginal as TVectorOriginal) do
  817. begin
  818. rRemove := InternalDeleteShapeRange(FRangeStart, FShapesAfter.Count);
  819. insCopy := TVectorShapes.Create;
  820. for i := 0 to FShapesBefore.Count-1 do insCopy.Add(FShapesBefore[i].Duplicate);
  821. rInsert := InternalInsertShapeRange(insCopy, FRangeStart);
  822. insCopy.Free;
  823. NotifyChange(TRectF.Union(rRemove,rInsert,True));
  824. SelectShape(FSelectedShapeBefore);
  825. end;
  826. end;
  827. function TVectorOriginalShapeRangeDiff.CanAppend(ADiff: TBGRAOriginalDiff): boolean;
  828. begin
  829. result := false;
  830. end;
  831. procedure TVectorOriginalShapeRangeDiff.Append(ADiff: TBGRAOriginalDiff);
  832. begin
  833. raise exception.Create(errMergeNotAllowed);
  834. end;
  835. function TVectorOriginalShapeRangeDiff.IsIdentity: boolean;
  836. begin
  837. result := false;
  838. end;
  839. { TVectorOriginalShapeDiff }
  840. function TVectorOriginalShapeDiff.GetShape(AOriginal: TBGRALayerCustomOriginal): TVectorShape;
  841. procedure UpdateMultiSelection(AOriginal: TVectorOriginal; AMultiDiff: TCustomMultiSelectionDiff);
  842. var
  843. i: Integer;
  844. containedShapes: TVectorShapes;
  845. s, s2: TVectorShape;
  846. begin
  847. containedShapes := TVectorShapes.Create;
  848. for i := 0 to AMultiDiff.ShapeCount-1 do
  849. begin
  850. s2 := AOriginal.FindShapeById(AMultiDiff.ShapeId[i]);
  851. if Assigned(s2) then containedShapes.Add(s2);
  852. end;
  853. AOriginal.SelectShapes(containedShapes);
  854. containedShapes.Free;
  855. end;
  856. var
  857. multiDiff: TCustomMultiSelectionDiff;
  858. orig: TVectorOriginal;
  859. begin
  860. orig := (AOriginal as TVectorOriginal);
  861. if FShapeIndex = -2 then
  862. begin
  863. result := orig.FMultiselection;
  864. if FShapeDiff is TCustomMultiSelectionDiff then
  865. UpdateMultiSelection(orig, TCustomMultiSelectionDiff(FShapeDiff)) else
  866. if FShapeDiff is TVectorShapeComposedDiff then
  867. begin
  868. multiDiff := TVectorShapeComposedDiff(FShapeDiff).GetMultiselection;
  869. if Assigned(multiDiff) then UpdateMultiSelection(orig, multiDiff);
  870. end;
  871. end else
  872. result := orig.Shape[FShapeIndex];
  873. end;
  874. constructor TVectorOriginalShapeDiff.Create(AShapeIndex: integer;
  875. AShapeDiff: TVectorShapeDiff);
  876. begin
  877. FShapeIndex := AShapeIndex;
  878. FShapeDiff := AShapeDiff;
  879. end;
  880. destructor TVectorOriginalShapeDiff.Destroy;
  881. begin
  882. FShapeDiff.Free;
  883. inherited Destroy;
  884. end;
  885. procedure TVectorOriginalShapeDiff.Apply(AOriginal: TBGRALayerCustomOriginal);
  886. begin
  887. FShapeDiff.Apply(GetShape(AOriginal));
  888. end;
  889. procedure TVectorOriginalShapeDiff.Unapply(AOriginal: TBGRALayerCustomOriginal);
  890. begin
  891. FShapeDiff.Unapply(GetShape(AOriginal));
  892. end;
  893. function TVectorOriginalShapeDiff.CanAppend(ADiff: TBGRAOriginalDiff): boolean;
  894. begin
  895. result := (ADiff is TVectorOriginalShapeDiff) and
  896. (TVectorOriginalShapeDiff(ADiff).FShapeIndex = FShapeIndex) and
  897. (FShapeDiff.CanAppend(TVectorOriginalShapeDiff(ADiff).FShapeDiff));
  898. end;
  899. procedure TVectorOriginalShapeDiff.Append(ADiff: TBGRAOriginalDiff);
  900. begin
  901. if CanAppend(ADiff) then
  902. FShapeDiff.Append(TVectorOriginalShapeDiff(ADiff).FShapeDiff)
  903. else
  904. raise exception.Create(errMergeNotAllowed);
  905. end;
  906. function TVectorOriginalShapeDiff.IsIdentity: boolean;
  907. begin
  908. result := FShapeDiff.IsIdentity;
  909. end;
  910. { TVectorShapeCommonDiff }
  911. constructor TVectorShapeCommonDiff.Create(AStartShape: TVectorShape);
  912. begin
  913. with AStartShape do
  914. begin
  915. FStartPenWidth:= PenWidth;
  916. FStartPenStyle:= DuplicatePenStyle(PenStyle);
  917. FStartOutlineWidth:= OutlineWidth;
  918. FStartJoinStyle:= JoinStyle;
  919. end;
  920. end;
  921. procedure TVectorShapeCommonDiff.ComputeDiff(AEndShape: TVectorShape);
  922. begin
  923. with AEndShape do
  924. begin
  925. FEndPenWidth:= PenWidth;
  926. FEndPenStyle:= DuplicatePenStyle(PenStyle);
  927. FEndOutlineWidth:= OutlineWidth;
  928. FEndJoinStyle:= JoinStyle;
  929. end;
  930. end;
  931. procedure TVectorShapeCommonDiff.Apply(AStartShape: TVectorShape);
  932. begin
  933. with AStartShape do
  934. begin
  935. BeginUpdate;
  936. FPenWidth := FEndPenWidth;
  937. Stroker.CustomPenStyle := DuplicatePenStyle(FEndPenStyle);
  938. FOutlineWidth := FEndOutlineWidth;
  939. Stroker.JoinStyle := FEndJoinStyle;
  940. EndUpdate;
  941. end;
  942. end;
  943. procedure TVectorShapeCommonDiff.Unapply(AEndShape: TVectorShape);
  944. begin
  945. with AEndShape do
  946. begin
  947. BeginUpdate;
  948. FPenWidth := FStartPenWidth;
  949. Stroker.CustomPenStyle := DuplicatePenStyle(FStartPenStyle);
  950. FOutlineWidth := FStartOutlineWidth;
  951. Stroker.JoinStyle := FStartJoinStyle;
  952. EndUpdate;
  953. end;
  954. end;
  955. procedure TVectorShapeCommonDiff.Append(ADiff: TVectorShapeDiff);
  956. var
  957. next: TVectorShapeCommonDiff;
  958. begin
  959. next := ADiff as TVectorShapeCommonDiff;
  960. FEndPenWidth:= next.FEndPenWidth;
  961. FEndPenStyle:= DuplicatePenStyle(next.FEndPenStyle);
  962. FEndOutlineWidth:= next.FEndOutlineWidth;
  963. FEndJoinStyle:= next.FEndJoinStyle;
  964. end;
  965. function TVectorShapeCommonDiff.IsIdentity: boolean;
  966. begin
  967. result := (FStartPenWidth = FEndPenWidth) and
  968. PenStyleEqual(FStartPenStyle, FEndPenStyle) and
  969. (FStartOutlineWidth = FEndOutlineWidth) and
  970. (FStartJoinStyle = FEndJoinStyle);
  971. end;
  972. { TVectorShapeEmbeddedFillDiff }
  973. constructor TVectorShapeEmbeddedFillDiff.Create(AField: TVectorShapeField;
  974. AFillDiff: TCustomVectorialFillDiff);
  975. begin
  976. FField := AField;
  977. FFillDiff := AFillDiff;
  978. end;
  979. constructor TVectorShapeEmbeddedFillDiff.Create(AStartShape: TVectorShape);
  980. begin
  981. raise exception.Create(errCannotBeComputedFromShape);
  982. end;
  983. destructor TVectorShapeEmbeddedFillDiff.Destroy;
  984. begin
  985. FFillDiff.Free;
  986. inherited Destroy;
  987. end;
  988. procedure TVectorShapeEmbeddedFillDiff.ComputeDiff(AEndShape: TVectorShape);
  989. begin
  990. raise exception.Create(errCannotBeComputedFromShape);
  991. end;
  992. procedure TVectorShapeEmbeddedFillDiff.Apply(AStartShape: TVectorShape);
  993. begin
  994. case FField of
  995. vsfPenFill: FFillDiff.Apply(AStartShape.PenFill);
  996. vsfBackFill: FFillDiff.Apply(AStartShape.BackFill);
  997. vsfOutlineFill: FFillDiff.Apply(AStartShape.OutlineFill);
  998. end;
  999. end;
  1000. procedure TVectorShapeEmbeddedFillDiff.Unapply(AEndShape: TVectorShape);
  1001. begin
  1002. case FField of
  1003. vsfPenFill: FFillDiff.Unapply(AEndShape.PenFill);
  1004. vsfBackFill: FFillDiff.Unapply(AEndShape.BackFill);
  1005. vsfOutlineFill: FFillDiff.Unapply(AEndShape.OutlineFill);
  1006. end;
  1007. end;
  1008. function TVectorShapeEmbeddedFillDiff.CanAppend(ADiff: TVectorShapeDiff): boolean;
  1009. begin
  1010. result := (ADiff is TVectorShapeEmbeddedFillDiff) and
  1011. (TVectorShapeEmbeddedFillDiff(ADiff).FField = FField) and
  1012. FFillDiff.CanAppend(TVectorShapeEmbeddedFillDiff(ADiff).FFillDiff);
  1013. end;
  1014. procedure TVectorShapeEmbeddedFillDiff.Append(ADiff: TVectorShapeDiff);
  1015. var
  1016. next: TVectorShapeEmbeddedFillDiff;
  1017. begin
  1018. next := ADiff as TVectorShapeEmbeddedFillDiff;
  1019. if next.FField <> FField then raise exception.Create(errFillFieldMismatch);
  1020. FFillDiff.Append(next.FFillDiff);
  1021. end;
  1022. function TVectorShapeEmbeddedFillDiff.IsIdentity: boolean;
  1023. begin
  1024. result := FFillDiff.IsIdentity;
  1025. end;
  1026. { TVectorShapeComposedDiff }
  1027. constructor TVectorShapeComposedDiff.Create(ADiffs: TVectorShapeDiffList);
  1028. var
  1029. i: Integer;
  1030. begin
  1031. setlength(FDiffs, ADiffs.Count);
  1032. for i := 0 to high(FDiffs) do
  1033. FDiffs[i] := ADiffs[i];
  1034. end;
  1035. constructor TVectorShapeComposedDiff.Create(ADiffs: array of TVectorShapeDiff);
  1036. var
  1037. i: Integer;
  1038. begin
  1039. setlength(FDiffs, length(ADiffs));
  1040. for i := 0 to high(FDiffs) do
  1041. FDiffs[i] := ADiffs[i];
  1042. end;
  1043. constructor TVectorShapeComposedDiff.Create(AStartShape: TVectorShape);
  1044. begin
  1045. raise exception.Create(errCannotBeComputedFromShape);
  1046. end;
  1047. destructor TVectorShapeComposedDiff.Destroy;
  1048. var
  1049. i: Integer;
  1050. begin
  1051. for i := 0 to high(FDiffs) do
  1052. FDiffs[i].Free;
  1053. FDiffs := nil;
  1054. inherited Destroy;
  1055. end;
  1056. procedure TVectorShapeComposedDiff.ComputeDiff(AEndShape: TVectorShape);
  1057. begin
  1058. raise exception.Create(errCannotBeComputedFromShape);
  1059. end;
  1060. procedure TVectorShapeComposedDiff.Apply(AStartShape: TVectorShape);
  1061. var
  1062. i: Integer;
  1063. begin
  1064. AStartShape.BeginUpdate;
  1065. for i := 0 to high(FDiffs) do
  1066. FDiffs[i].Apply(AStartShape);
  1067. AStartShape.EndUpdate;
  1068. end;
  1069. procedure TVectorShapeComposedDiff.Unapply(AEndShape: TVectorShape);
  1070. var
  1071. i: Integer;
  1072. begin
  1073. AEndShape.BeginUpdate;
  1074. for i := high(FDiffs) downto 0 do
  1075. FDiffs[i].Unapply(AEndShape);
  1076. AEndShape.EndUpdate;
  1077. end;
  1078. function TVectorShapeComposedDiff.CanAppend(ADiff: TVectorShapeDiff): boolean;
  1079. var
  1080. next: TVectorShapeComposedDiff;
  1081. i: Integer;
  1082. begin
  1083. if ADiff is TVectorShapeComposedDiff then
  1084. begin
  1085. next := TVectorShapeComposedDiff(ADiff);
  1086. for i := 0 to high(next.FDiffs) do
  1087. if not CanAppend(next.FDiffs[i]) then exit(false);
  1088. result := true;
  1089. end else
  1090. begin
  1091. for i := high(FDiffs) downto 0 do
  1092. if FDiffs[i].CanAppend(ADiff) then exit(true);
  1093. exit(false);
  1094. end;
  1095. end;
  1096. procedure TVectorShapeComposedDiff.Append(ADiff: TVectorShapeDiff);
  1097. var
  1098. next: TVectorShapeComposedDiff;
  1099. i: Integer;
  1100. begin
  1101. if ADiff is TVectorShapeComposedDiff then
  1102. begin
  1103. next := TVectorShapeComposedDiff(ADiff);
  1104. for i := 0 to high(next.FDiffs) do
  1105. Append(next.FDiffs[i]);
  1106. end else
  1107. begin
  1108. for i := high(FDiffs) downto 0 do
  1109. if FDiffs[i].CanAppend(ADiff) then
  1110. begin
  1111. FDiffs[i].Append(ADiff);
  1112. exit;
  1113. end;
  1114. end;
  1115. end;
  1116. function TVectorShapeComposedDiff.IsIdentity: boolean;
  1117. var
  1118. i: Integer;
  1119. begin
  1120. for i := 0 to high(FDiffs) do
  1121. if not FDiffs[i].IsIdentity then exit(false);
  1122. result := true;
  1123. end;
  1124. function TVectorShapeComposedDiff.GetMultiselection: TCustomMultiSelectionDiff;
  1125. var
  1126. i: Integer;
  1127. begin
  1128. for i := 0 to high(FDiffs) do
  1129. if FDiffs[i] is TCustomMultiSelectionDiff then
  1130. exit(TCustomMultiSelectionDiff(FDiffs[i]));
  1131. result := nil;
  1132. end;
  1133. { TVectorOriginalEditor }
  1134. constructor TVectorOriginalEditor.Create(AOriginal: TVectorOriginal);
  1135. begin
  1136. inherited Create;
  1137. FOriginal := AOriginal;
  1138. end;
  1139. procedure TVectorOriginalEditor.Clear;
  1140. begin
  1141. inherited Clear;
  1142. FLabels:= nil;
  1143. end;
  1144. function TVectorOriginalEditor.Render(ADest: TBGRABitmap;
  1145. const ALayoutRect: TRect): TRect;
  1146. var
  1147. i: Integer;
  1148. ptF: TPointF;
  1149. r: Classes.TRect;
  1150. begin
  1151. Result:=inherited Render(ADest, ALayoutRect);
  1152. for i := 0 to high(FLabels) do
  1153. if not isEmptyPointF(FLabels[i].Coord) then
  1154. begin
  1155. ptF := OriginalCoordToView(FLabels[i].Coord);
  1156. r := NiceText(ADest, round(ptF.x),round(ptF.y), ALayoutRect, FLabels[i].Text, FLabels[i].HorizAlign, FLabels[i].VertAlign, FLabels[i].Padding);
  1157. if not IsRectEmpty(r) then
  1158. begin
  1159. if IsRectEmpty(result) then result:= r
  1160. else UnionRect(result, result, r);
  1161. end;
  1162. end;
  1163. end;
  1164. function TVectorOriginalEditor.GetRenderBounds(const ALayoutRect: TRect): TRect;
  1165. var
  1166. i: Integer;
  1167. ptF: TPointF;
  1168. r: Classes.TRect;
  1169. begin
  1170. Result:=inherited GetRenderBounds(ALayoutRect);
  1171. for i := 0 to high(FLabels) do
  1172. if not isEmptyPointF(FLabels[i].Coord) then
  1173. begin
  1174. ptF := OriginalCoordToView(FLabels[i].Coord);
  1175. r := NiceText(nil, round(ptF.x),round(ptF.y), ALayoutRect, FLabels[i].Text, FLabels[i].HorizAlign, FLabels[i].VertAlign, FLabels[i].Padding);
  1176. if not IsRectEmpty(r) then
  1177. begin
  1178. if IsRectEmpty(result) then result:= r
  1179. else UnionRect(result, result, r);
  1180. end;
  1181. end;
  1182. end;
  1183. procedure TVectorOriginalEditor.AddLabel(const ACoord: TPointF; AText: string;
  1184. AHorizAlign: TAlignment; AVertAlign: TTextLayout);
  1185. begin
  1186. setlength(FLabels, length(FLabels)+1);
  1187. with FLabels[high(FLabels)] do
  1188. begin
  1189. Coord := ACoord;
  1190. Text:= AText;
  1191. HorizAlign:= AHorizAlign;
  1192. VertAlign:= AVertAlign;
  1193. Padding := 0;
  1194. end;
  1195. end;
  1196. procedure TVectorOriginalEditor.AddLabel(APointIndex: integer; AText: string;
  1197. AHorizAlign: TAlignment; AVertAlign: TTextLayout);
  1198. begin
  1199. setlength(FLabels, length(FLabels)+1);
  1200. with FLabels[high(FLabels)] do
  1201. begin
  1202. Coord := PointCoord[APointIndex];
  1203. Text:= AText;
  1204. HorizAlign:= AHorizAlign;
  1205. VertAlign:= AVertAlign;
  1206. Padding := round(PointSize);
  1207. end;
  1208. end;
  1209. function TVectorOriginalEditor.NiceText(ADest: TBGRABitmap; x, y: integer;
  1210. const ALayoutRect: TRect; AText: string; AHorizAlign: TAlignment;
  1211. AVertAlign: TTextLayout; APadding: integer): TRect;
  1212. var fx: TBGRATextEffect;
  1213. f: TFont;
  1214. previousClip: TRect;
  1215. shadowRadius: integer;
  1216. begin
  1217. f := TFont.Create;
  1218. f.Name := 'default';
  1219. f.Height := round(PointSize*2.5);
  1220. fx := TBGRATextEffect.Create(AText,f,true);
  1221. if (AVertAlign = tlTop) and (AHorizAlign = taCenter) and (y+APadding+fx.TextSize.cy > ALayoutRect.Bottom) then AVertAlign:= tlBottom;
  1222. if (AVertAlign = tlBottom) and (AHorizAlign = taCenter) and (y-APadding-fx.TextSize.cy < ALayoutRect.Top) then AVertAlign:= tlTop;
  1223. if (AHorizAlign = taLeftJustify) and (AVertAlign = tlCenter) and (x+APadding+fx.TextSize.cx > ALayoutRect.Right) then AHorizAlign:= taRightJustify;
  1224. if (AHorizAlign = taRightJustify) and (AVertAlign = tlCenter) and (x-APadding-fx.TextSize.cx < ALayoutRect.Left) then AHorizAlign:= taLeftJustify;
  1225. if AVertAlign = tlBottom then y := y-APadding-fx.TextSize.cy else
  1226. if AVertAlign = tlCenter then y := y-fx.TextSize.cy div 2 else inc(y,APadding);
  1227. if y+fx.TextSize.cy > ALayoutRect.Bottom then y := ALayoutRect.Bottom-fx.TextSize.cy;
  1228. if y < ALayoutRect.Top then y := ALayoutRect.Top;
  1229. if AHorizAlign = taRightJustify then x := x-APadding-fx.TextSize.cx else
  1230. if AHorizAlign = taCenter then x := x-fx.TextSize.cx div 2 else inc(x,APadding);
  1231. if x+fx.TextSize.cx > ALayoutRect.Right then x := ALayoutRect.Right-fx.TextSize.cx;
  1232. if x < ALayoutRect.Left then x := ALayoutRect.Left;
  1233. shadowRadius:= round(PointSize*0.5);
  1234. result := rect(x,y,x+fx.TextWidth+2*shadowRadius,y+fx.TextHeight+2*shadowRadius);
  1235. if Assigned(ADest) then
  1236. begin
  1237. previousClip := ADest.ClipRect;
  1238. ADest.ClipRect := result;
  1239. if shadowRadius <> 0 then
  1240. fx.DrawShadow(ADest,x+shadowRadius,y+shadowRadius,shadowRadius,BGRABlack);
  1241. fx.DrawOutline(ADest,x,y,BGRABlack);
  1242. fx.Draw(ADest,x,y,BGRAWhite);
  1243. ADest.ClipRect := previousClip;
  1244. end;
  1245. fx.Free;
  1246. f.Free;
  1247. end;
  1248. procedure TVectorOriginalEditor.MouseMove(Shift: TShiftState; ViewX, ViewY: single; out
  1249. ACursor: TOriginalEditorCursor; out AHandled: boolean);
  1250. var
  1251. ptF: TPointF;
  1252. begin
  1253. inherited MouseMove(Shift, ViewX, ViewY, ACursor, AHandled);
  1254. if not AHandled and Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1255. begin
  1256. ptF := ViewCoordToOriginal(PointF(ViewX,ViewY));
  1257. if GridActive then ptF := SnapToGrid(ptF, False);
  1258. with ptF do FOriginal.SelectedShape.MouseMove(Shift, X,Y, ACursor, AHandled);
  1259. end;
  1260. end;
  1261. procedure TVectorOriginalEditor.MouseDown(RightButton: boolean;
  1262. Shift: TShiftState; ViewX, ViewY: single; out ACursor: TOriginalEditorCursor; out
  1263. AHandled: boolean);
  1264. var
  1265. ptF: TPointF;
  1266. begin
  1267. inherited MouseDown(RightButton, Shift, ViewX, ViewY, ACursor, AHandled);
  1268. if not AHandled and Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1269. begin
  1270. ptF := ViewCoordToOriginal(PointF(ViewX,ViewY));
  1271. if GridActive then ptF := SnapToGrid(ptF, False);
  1272. with ptF do FOriginal.SelectedShape.MouseDown(RightButton,
  1273. ConsecutiveClickCount, Shift, X,Y, ACursor, AHandled);
  1274. end;
  1275. end;
  1276. procedure TVectorOriginalEditor.MouseUp(RightButton: boolean;
  1277. Shift: TShiftState; ViewX, ViewY: single; out ACursor: TOriginalEditorCursor; out
  1278. AHandled: boolean);
  1279. var
  1280. ptF: TPointF;
  1281. begin
  1282. inherited MouseUp(RightButton, Shift, ViewX, ViewY, ACursor, AHandled);
  1283. if not AHandled and Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1284. begin
  1285. ptF := ViewCoordToOriginal(PointF(ViewX,ViewY));
  1286. if GridActive then ptF := SnapToGrid(ptF, False);
  1287. with ptF do FOriginal.SelectedShape.MouseUp(RightButton, Shift, X,Y, ACursor, AHandled);
  1288. end;
  1289. end;
  1290. procedure TVectorOriginalEditor.KeyDown(Shift: TShiftState; Key: TSpecialKey; out
  1291. AHandled: boolean);
  1292. begin
  1293. if Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1294. begin
  1295. AHandled := false;
  1296. FOriginal.SelectedShape.KeyDown(Shift, Key, AHandled);
  1297. if AHandled then exit;
  1298. if (Key = skReturn) and ([ssShift,ssCtrl,ssAlt]*Shift = []) then
  1299. begin
  1300. FOriginal.DeselectShapes;
  1301. AHandled := true;
  1302. exit;
  1303. end else
  1304. if (Key = skEscape) and ([ssShift,ssCtrl,ssAlt]*Shift = []) and (FOriginal.SelectedShape.Usermode = vsuCreate) then
  1305. begin
  1306. FOriginal.SelectedShape.Remove;
  1307. AHandled:= true;
  1308. end;
  1309. end;
  1310. inherited KeyDown(Shift, Key, AHandled);
  1311. end;
  1312. procedure TVectorOriginalEditor.KeyUp(Shift: TShiftState; Key: TSpecialKey; out
  1313. AHandled: boolean);
  1314. begin
  1315. if Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1316. begin
  1317. AHandled := false;
  1318. FOriginal.SelectedShape.KeyUp(Shift, Key, AHandled);
  1319. if AHandled then exit;
  1320. end;
  1321. inherited KeyUp(Shift, Key, AHandled);
  1322. end;
  1323. procedure TVectorOriginalEditor.KeyPress(UTF8Key: string; out
  1324. AHandled: boolean);
  1325. begin
  1326. if Assigned(FOriginal) and Assigned(FOriginal.SelectedShape) then
  1327. begin
  1328. AHandled := false;
  1329. FOriginal.SelectedShape.KeyPress(UTF8Key, AHandled);
  1330. if AHandled then exit;
  1331. end;
  1332. inherited KeyPress(UTF8Key, AHandled);
  1333. end;
  1334. { TVectorShape }
  1335. function TVectorShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;
  1336. begin
  1337. result := false;
  1338. end;
  1339. function TVectorShape.GetGenericCost: integer;
  1340. begin
  1341. if vsfBackFill in Fields then
  1342. begin
  1343. case BackFill.FillType of
  1344. vftGradient: result := 25;
  1345. vftTexture: result := 10;
  1346. vftSolid: result := 4;
  1347. else {vftNone} result := 1;
  1348. end
  1349. end else
  1350. if vsfPenStyle in Fields then
  1351. begin
  1352. if PenStyleEqual(PenStyle, SolidPenStyle) or
  1353. PenStyleEqual(PenStyle, ClearPenStyle) then
  1354. result := 1
  1355. else
  1356. result := 2;
  1357. end else
  1358. result := 1;
  1359. end;
  1360. function TVectorShape.GetUsedTextures: ArrayOfBGRABitmap;
  1361. var
  1362. f: TVectorShapeFields;
  1363. nb: integer;
  1364. begin
  1365. f := Fields;
  1366. setlength(result, 3);
  1367. nb := 0;
  1368. if (vsfBackFill in f) and (BackFill.FillType = vftTexture) then
  1369. begin
  1370. result[nb] := BackFill.Texture;
  1371. inc(nb);
  1372. end;
  1373. if (vsfPenFill in f) and (PenFill.FillType = vftTexture) then
  1374. begin
  1375. result[nb] := PenFill.Texture;
  1376. inc(nb);
  1377. end;
  1378. if (vsfOutlineFill in f) and (OutlineFill.FillType = vftTexture) then
  1379. begin
  1380. result[nb] := OutlineFill.Texture;
  1381. inc(nb);
  1382. end;
  1383. setlength(result, nb);
  1384. end;
  1385. function TVectorShape.GetAsMultishape: IVectorMultishape;
  1386. begin
  1387. result := nil;
  1388. end;
  1389. procedure TVectorShape.Transform(const AMatrix: TAffineMatrix);
  1390. var
  1391. zoom: Single;
  1392. begin
  1393. if IsAffineMatrixIdentity(AMatrix) then exit;
  1394. BeginUpdate;
  1395. TransformFrame(AMatrix);
  1396. TransformFill(AMatrix, False);
  1397. zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
  1398. if vsfPenWidth in Fields then PenWidth := zoom*PenWidth;
  1399. if vsfOutlineWidth in Fields then OutlineWidth := zoom*OutlineWidth;
  1400. EndUpdate;
  1401. end;
  1402. class function TVectorShape.Fields: TVectorShapeFields;
  1403. begin
  1404. result := [];
  1405. end;
  1406. function TVectorShape.GetJoinStyle: TPenJoinStyle;
  1407. begin
  1408. result := Stroker.JoinStyle;
  1409. end;
  1410. procedure TVectorShape.SetJoinStyle(AValue: TPenJoinStyle);
  1411. begin
  1412. if Stroker.JoinStyle = AValue then exit;
  1413. BeginUpdate(TVectorShapeCommonDiff);
  1414. Stroker.JoinStyle := AValue;
  1415. EndUpdate;
  1416. end;
  1417. procedure TVectorShape.SetUsermode(AValue: TVectorShapeUsermode);
  1418. begin
  1419. if FUsermode=AValue then Exit;
  1420. BeginEditingUpdate;
  1421. FUsermode:=AValue;
  1422. EndEditingUpdate;
  1423. end;
  1424. function TVectorShape.LoadTexture(AStorage: TBGRACustomOriginalStorage;
  1425. AName: string): TBGRABitmap;
  1426. var
  1427. texId: Integer;
  1428. pointerData: RawByteString;
  1429. begin
  1430. if FStoreTexturePointer then
  1431. begin
  1432. result := nil;
  1433. pointerData := AStorage.RawString[AName+'-ptr'];
  1434. if length(pointerData)<>sizeof(result) then
  1435. raise exception.Create(errInvalidStoredPointer);
  1436. move(pointerData[1],result,sizeof(result));
  1437. end else
  1438. if Assigned(Container) then
  1439. begin
  1440. texId := AStorage.Int[AName+'-id'];
  1441. result := Container.GetTexture(texId);
  1442. end else
  1443. raise exception.Create(errUndefinedContainer);
  1444. end;
  1445. procedure TVectorShape.SaveTexture(AStorage: TBGRACustomOriginalStorage;
  1446. AName: string; AValue: TBGRABitmap);
  1447. var
  1448. texId: Integer;
  1449. pointerData: RawByteString;
  1450. begin
  1451. if FStoreTexturePointer then
  1452. begin
  1453. setlength(pointerData, sizeof(AValue));
  1454. move(AValue, pointerData[1], length(pointerData));
  1455. AStorage.RawString[AName+'-ptr'] := pointerData;
  1456. end else
  1457. if Assigned(Container) then
  1458. begin
  1459. texId := Container.GetTextureId(AValue);
  1460. AStorage.Int[AName+'-id'] := texId;
  1461. end else
  1462. raise exception.Create(errUndefinedContainer);
  1463. end;
  1464. procedure TVectorShape.LoadFill(AStorage: TBGRACustomOriginalStorage;
  1465. AObjectName: string; var AValue: TVectorialFill);
  1466. var
  1467. obj: TBGRACustomOriginalStorage;
  1468. tex: TBGRABitmap;
  1469. texOpacity: integer;
  1470. origin, xAxis, yAxis: TPointF;
  1471. grad: TBGRALayerGradientOriginal;
  1472. repetition: TTextureRepetition;
  1473. c: TBGRAPixel;
  1474. begin
  1475. if AValue = nil then
  1476. begin
  1477. AValue := TVectorialFill.Create;
  1478. AValue.OnChange := @FillChange;
  1479. end;
  1480. obj := AStorage.OpenObject(AObjectName+'-fill');
  1481. if obj = nil then
  1482. begin
  1483. c := AStorage.Color[AObjectName+'-color'];
  1484. if c.alpha <> 0 then
  1485. AValue.SetSolid(c);
  1486. exit;
  1487. end;
  1488. try
  1489. case obj.RawString['class'] of
  1490. 'solid': AValue.SetSolid(obj.Color['color']);
  1491. 'texture': begin
  1492. tex := LoadTexture(obj, 'tex');
  1493. origin := obj.PointF['origin'];
  1494. xAxis := obj.PointF['x-axis'];
  1495. yAxis := obj.PointF['y-axis'];
  1496. texOpacity := obj.IntDef['opacity',255];
  1497. if texOpacity < 0 then texOpacity:= 0;
  1498. if texOpacity > 255 then texOpacity:= 255;
  1499. case obj.RawString['repetition'] of
  1500. 'none': repetition := trNone;
  1501. 'repeat-x': repetition := trRepeatX;
  1502. 'repeat-y': repetition := trRepeatY;
  1503. else repetition := trRepeatBoth;
  1504. end;
  1505. AValue.SetTexture(tex, AffineMatrix(xAxis,yAxis,origin), texOpacity, repetition)
  1506. end;
  1507. 'gradient': begin
  1508. grad := TBGRALayerGradientOriginal.Create;
  1509. grad.LoadFromStorage(obj);
  1510. AValue.SetGradient(grad,true);
  1511. end;
  1512. else AValue.Clear;
  1513. end;
  1514. finally
  1515. obj.Free;
  1516. end;
  1517. end;
  1518. procedure TVectorShape.SaveFill(AStorage: TBGRACustomOriginalStorage;
  1519. AObjectName: string; AValue: TVectorialFill);
  1520. var
  1521. obj: TBGRACustomOriginalStorage;
  1522. m: TAffineMatrix;
  1523. ft: TVectorialFillType;
  1524. begin
  1525. AStorage.RemoveObject(AObjectName+'-fill');
  1526. AStorage.RemoveAttribute(AObjectName+'-color');
  1527. if Assigned(AValue) then
  1528. begin
  1529. ft := AValue.FillType;
  1530. if ft = vftSolid then
  1531. begin
  1532. AStorage.Color[AObjectName+'-color'] := AValue.SolidColor;
  1533. exit;
  1534. end else
  1535. if not (ft in [vftTexture,vftGradient]) then exit;
  1536. obj := AStorage.CreateObject(AObjectName+'-fill');
  1537. try
  1538. if ft = vftSolid then
  1539. begin
  1540. obj.RawString['class'] := 'solid';
  1541. obj.Color['color'] := AValue.SolidColor;
  1542. end
  1543. else
  1544. if ft = vftTexture then
  1545. begin
  1546. obj.RawString['class'] := 'texture';
  1547. SaveTexture(obj, 'tex', AValue.Texture);
  1548. m := AValue.TextureMatrix;
  1549. obj.PointF['origin'] := PointF(m[1,3],m[2,3]);
  1550. obj.PointF['x-axis'] := PointF(m[1,1],m[2,1]);
  1551. obj.PointF['y-axis'] := PointF(m[1,2],m[2,2]);
  1552. if AValue.TextureOpacity<>255 then
  1553. obj.Int['opacity'] := AValue.TextureOpacity;
  1554. case AValue.TextureRepetition of
  1555. trNone: obj.RawString['repetition'] := 'none';
  1556. trRepeatX: obj.RawString['repetition'] := 'repeat-x';
  1557. trRepeatY: obj.RawString['repetition'] := 'repeat-y';
  1558. trRepeatBoth: obj.RemoveAttribute('repetition');
  1559. end;
  1560. end else
  1561. if ft = vftGradient then
  1562. begin
  1563. obj.RawString['class'] := 'gradient';
  1564. AValue.Gradient.SaveToStorage(obj);
  1565. end else
  1566. obj.RawString['class'] := 'none';
  1567. finally
  1568. obj.Free;
  1569. end;
  1570. end;
  1571. end;
  1572. class function TVectorShape.Usermodes: TVectorShapeUsermodes;
  1573. begin
  1574. result := [vsuEdit];
  1575. if vsfBackFill in Fields then result += [vsuEditBackFill];
  1576. if vsfPenFill in Fields then result += [vsuEditPenFill];
  1577. if vsfOutlineFill in Fields then result += [vsuEditOutlineFill];
  1578. end;
  1579. function TVectorShape.MultiUsermodes: TVectorShapeUsermodes;
  1580. var
  1581. f: TVectorShapeFields;
  1582. begin
  1583. result := [vsuEdit];
  1584. f := MultiFields;
  1585. if vsfBackFill in f then result += [vsuEditBackFill];
  1586. if vsfPenFill in f then result += [vsuEditPenFill];
  1587. if vsfOutlineFill in f then result += [vsuEditOutlineFill];
  1588. end;
  1589. class function TVectorShape.PreferPixelCentered: boolean;
  1590. begin
  1591. result := true;
  1592. end;
  1593. class function TVectorShape.CreateEmpty: boolean;
  1594. begin
  1595. result := false;
  1596. end;
  1597. procedure TVectorShape.SetContainer(AValue: TVectorOriginal);
  1598. begin
  1599. if FContainer=AValue then Exit;
  1600. if Assigned(FContainer) then raise exception.Create(errContainerAlreadyAssigned);
  1601. FContainer:=AValue;
  1602. end;
  1603. function TVectorShape.GetIsUpdating: boolean;
  1604. begin
  1605. result := FUpdateCount > 0;
  1606. end;
  1607. function TVectorShape.GetOutlineWidth: single;
  1608. begin
  1609. result := FOutlineWidth;
  1610. end;
  1611. function TVectorShape.GetFill(var AFillVariable: TVectorialFill): TVectorialFill;
  1612. begin
  1613. if AFillVariable = nil then
  1614. begin
  1615. AFillVariable := TVectorialFill.Create;
  1616. AFillVariable.OnChange := @FillChange;
  1617. AFillVariable.OnBeforeChange := @FillBeforeChange;
  1618. end;
  1619. result := AFillVariable;
  1620. end;
  1621. procedure TVectorShape.SetFill(var AFillVariable: TVectorialFill;
  1622. AValue: TVectorialFill; AUpdate: boolean);
  1623. var
  1624. sharedTex: TBGRABitmap;
  1625. freeTex: Boolean;
  1626. begin
  1627. if Assigned(AFillVariable) then
  1628. begin
  1629. if AFillVariable.Equals(AValue) then exit;
  1630. end else
  1631. if AValue=nil then exit;
  1632. if not AUpdate then FFillChangeWithoutUpdate := true;
  1633. freeTex := Assigned(AFillVariable) and Assigned(AFillVariable.Texture) and
  1634. not (Assigned(AValue) and (AValue.FillType = vftTexture) and (AValue.Texture = AFillVariable.Texture));
  1635. if AValue = nil then
  1636. begin
  1637. AFillVariable.Clear; //trigger event
  1638. FreeAndNil(AFillVariable);
  1639. end else
  1640. if AValue.FillType = vftTexture then
  1641. begin
  1642. if Assigned(Container) then
  1643. sharedTex := Container.GetTexture(Container.AddTexture(AValue.Texture))
  1644. else
  1645. sharedTex := AValue.Texture;
  1646. GetFill(AFillVariable).SetTexture(sharedTex, AValue.TextureMatrix, AValue.TextureOpacity, AValue.TextureRepetition);
  1647. end else
  1648. GetFill(AFillVariable).Assign(AValue);
  1649. if Assigned(Container) and freeTex then Container.DiscardUnusedTextures;
  1650. if not AUpdate then FFillChangeWithoutUpdate := false;
  1651. end;
  1652. procedure TVectorShape.SetId(AValue: integer);
  1653. begin
  1654. if FId=AValue then Exit;
  1655. FId:=AValue;
  1656. end;
  1657. procedure TVectorShape.SetOutlineWidth(AValue: single);
  1658. begin
  1659. if AValue < 0 then AValue := 0;
  1660. if FOutlineWidth=AValue then Exit;
  1661. BeginUpdate(TVectorShapeCommonDiff);
  1662. FOutlineWidth:=AValue;
  1663. EndUpdate;
  1664. end;
  1665. procedure TVectorShape.SetOutlineFill(AValue: TVectorialFill);
  1666. begin
  1667. SetFill(FOutlineFill, AValue, True);
  1668. end;
  1669. function TVectorShape.GetIsBack: boolean;
  1670. begin
  1671. result := Assigned(Container) and (Container.IndexOfShape(self)=0);
  1672. end;
  1673. function TVectorShape.GetIsFollowingMouse: boolean;
  1674. begin
  1675. result := false;
  1676. end;
  1677. function TVectorShape.GetPenVisible(AAssumePenFill: boolean): boolean;
  1678. var
  1679. f: TVectorShapeFields;
  1680. begin
  1681. f := Fields;
  1682. result := (vsfPenFill in f) and (not PenFill.IsFullyTransparent or AAssumePenFill);
  1683. if result and (vsfPenWidth in f) then result := result and (PenWidth>0);
  1684. if result and (vsfPenStyle in f) then result := result and not IsClearPenStyle(PenStyle);
  1685. end;
  1686. function TVectorShape.GetPenVisibleNow: boolean;
  1687. begin
  1688. result := GetPenVisible(False);
  1689. end;
  1690. function TVectorShape.GetBackVisible: boolean;
  1691. begin
  1692. result := (vsfBackFill in Fields) and not BackFill.IsFullyTransparent;
  1693. end;
  1694. function TVectorShape.GetOutlineVisible: boolean;
  1695. begin
  1696. result := (vsfOutlineFill in Fields) and not OutlineFill.IsFullyTransparent and
  1697. (not (vsfOutlineWidth in Fields) or (OutlineWidth > 0));
  1698. end;
  1699. function TVectorShape.AppendVectorialFillToSVGDefs(AFill: TVectorialFill; const AMatrix: TAffineMatrix;
  1700. ADefs: TSVGDefine; ANamePrefix: string): string;
  1701. var
  1702. grad: TSVGGradient;
  1703. begin
  1704. if AFill.FillType = vftGradient then
  1705. begin
  1706. grad := AFill.Gradient.AddToSVGDefs(AMatrix, ADefs) as TSVGGradient;
  1707. if grad = nil then exit('');
  1708. grad.ID := ANamePrefix + 'grad' + inttostr(Id);
  1709. result := grad.ID;
  1710. end else
  1711. result := '';
  1712. end;
  1713. procedure TVectorShape.ApplyStrokeStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
  1714. var ps: array of single;
  1715. i: Integer;
  1716. fillId: String;
  1717. begin
  1718. if PenVisible then
  1719. begin
  1720. if IsAffineMatrixInversible(AElement.matrix[cuPixel]) then
  1721. fillId := AppendVectorialFillToSVGDefs(PenFill,
  1722. AffineMatrixInverse(AElement.matrix[cuPixel]), ADefs, 'stroke')
  1723. else fillId := '';
  1724. if fillId <> '' then
  1725. AElement.stroke:= 'url(#'+fillId+')'
  1726. else AElement.strokeColor := PenColor;
  1727. if IsSolidPenStyle(PenStyle) then
  1728. AElement.strokeDashArrayNone else
  1729. begin
  1730. setlength(ps, length(PenStyle));
  1731. for i := 0 to high(ps) do
  1732. ps[i] := PenStyle[i] * PenWidth;
  1733. AElement.strokeDashArrayF := ps;
  1734. end;
  1735. AElement.strokeLineJoinLCL := JoinStyle;
  1736. AElement.strokeWidth := FloatWithCSSUnit(PenWidth, cuCustom);
  1737. end else
  1738. AElement.strokeNone;
  1739. end;
  1740. procedure TVectorShape.ApplyFillStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
  1741. var
  1742. fillId: String;
  1743. begin
  1744. if BackVisible then
  1745. begin
  1746. if IsAffineMatrixInversible(AElement.matrix[cuPixel]) then
  1747. fillId := AppendVectorialFillToSVGDefs(BackFill,
  1748. AffineMatrixInverse(AElement.matrix[cuPixel]), ADefs, 'fill')
  1749. else fillId := '';
  1750. if fillId <> '' then
  1751. AElement.fill:= 'url(#'+fillId+')'
  1752. else AElement.fillColor := BackFill.AverageColor;
  1753. end
  1754. else AElement.fillNone;
  1755. end;
  1756. procedure TVectorShape.TransformFill(const AMatrix: TAffineMatrix; ABackOnly: boolean);
  1757. begin
  1758. BeginUpdate;
  1759. if vsfBackFill in Fields then BackFill.Transform(AMatrix);
  1760. if not ABackOnly then
  1761. begin
  1762. if vsfPenFill in Fields then PenFill.Transform(AMatrix);
  1763. if vsfOutlineFill in Fields then OutlineFill.Transform(AMatrix);
  1764. end;
  1765. EndUpdate;
  1766. end;
  1767. function TVectorShape.AllowShearTransform: boolean;
  1768. begin
  1769. result := true;
  1770. end;
  1771. function TVectorShape.MultiFields: TVectorShapeFields;
  1772. begin
  1773. result := Fields;
  1774. end;
  1775. function TVectorShape.GetIsFront: boolean;
  1776. begin
  1777. result := Assigned(Container) and (Container.IndexOfShape(self)=Container.ShapeCount-1);
  1778. end;
  1779. function TVectorShape.GetOutlineFill: TVectorialFill;
  1780. begin
  1781. result := GetFill(FOutlineFill);
  1782. end;
  1783. procedure TVectorShape.BeginUpdate(ADiffHandler: TVectorShapeDiffAny);
  1784. begin
  1785. if FUpdateCount = 0 then
  1786. begin
  1787. FBoundsBeforeUpdate := GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  1788. if isEmptyPointF(FBoundsBeforeUpdate.TopLeft) or isEmptyPointF(FBoundsBeforeUpdate.BottomRight) then
  1789. raise exception.Create('Unexpected empty point');
  1790. Inc(FRenderIteration);
  1791. end;
  1792. inc(FUpdateCount);
  1793. if ADiffHandler<>nil then AddDiffHandler(ADiffHandler);
  1794. end;
  1795. procedure TVectorShape.EndUpdate;
  1796. var
  1797. i: Integer;
  1798. comp: TVectorShapeComposedDiff;
  1799. begin
  1800. if FUpdateCount > 0 then
  1801. begin
  1802. dec(FUpdateCount);
  1803. if FUpdateCount = 0 then
  1804. begin
  1805. if Assigned(FDiffs) and (FDiffs.Count > 0) then
  1806. begin
  1807. for i := 0 to FDiffs.Count-1 do
  1808. FDiffs[i].ComputeDiff(self);
  1809. if FDiffs.Count = 1 then
  1810. DoOnChange(FBoundsBeforeUpdate, FDiffs[0])
  1811. else
  1812. begin
  1813. comp := TVectorShapeComposedDiff.Create(FDiffs);
  1814. DoOnChange(FBoundsBeforeUpdate, comp);
  1815. end;
  1816. FDiffs.Clear;
  1817. end else
  1818. DoOnChange(FBoundsBeforeUpdate, nil);
  1819. end;
  1820. end;
  1821. end;
  1822. procedure TVectorShape.FillFit;
  1823. var
  1824. box: TAffineBox;
  1825. begin
  1826. BeginUpdate;
  1827. box := SuggestGradientBox(AffineMatrixIdentity);
  1828. if vsfPenFill in Fields then PenFill.FitGeometry(box);
  1829. if vsfBackFill in Fields then BackFill.FitGeometry(box);
  1830. if vsfOutlineFill in Fields then OutlineFill.FitGeometry(box);
  1831. EndUpdate;
  1832. end;
  1833. procedure TVectorShape.BeginEditingUpdate;
  1834. begin
  1835. inc(FUpdateEditingCount);
  1836. end;
  1837. procedure TVectorShape.EndEditingUpdate;
  1838. begin
  1839. if FUpdateEditingCount > 0 then
  1840. begin
  1841. dec(FUpdateEditingCount);
  1842. if FUpdateEditingCount = 0 then
  1843. begin
  1844. if Assigned(FOnEditingChange) then
  1845. FOnEditingChange(self);
  1846. end;
  1847. end;
  1848. end;
  1849. procedure TVectorShape.DoOnChange(ABoundsBefore: TRectF; ADiff: TVectorShapeDiff);
  1850. var
  1851. boundsAfter: TRectF;
  1852. begin
  1853. if Assigned(FOnChange) then
  1854. begin
  1855. boundsAfter := GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  1856. FOnChange(self, boundsAfter.Union(ABoundsBefore, true), ADiff);
  1857. end else
  1858. ADiff.Free;
  1859. end;
  1860. function TVectorShape.GetPenColor: TBGRAPixel;
  1861. begin
  1862. if Assigned(FPenFill) then
  1863. result := FPenFill.SolidColor
  1864. else
  1865. result := BGRAPixelTransparent;
  1866. end;
  1867. function TVectorShape.GetPenWidth: single;
  1868. begin
  1869. result := FPenWidth;
  1870. end;
  1871. function TVectorShape.GetPenStyle: TBGRAPenStyle;
  1872. begin
  1873. result := Stroker.CustomPenStyle;
  1874. end;
  1875. function TVectorShape.GetBackFill: TVectorialFill;
  1876. begin
  1877. result := GetFill(FBackFill);
  1878. end;
  1879. function TVectorShape.GetPenFill: TVectorialFill;
  1880. begin
  1881. result := GetFill(FPenFill);
  1882. end;
  1883. function TVectorShape.ComputeStroke(APoints: ArrayOfTPointF; AClosed: boolean; AStrokeMatrix: TAffineMatrix): ArrayOfTPointF;
  1884. begin
  1885. Stroker.StrokeMatrix := AStrokeMatrix;
  1886. if AClosed then
  1887. result := Stroker.ComputePolygon(APoints, PenWidth)
  1888. else
  1889. result := Stroker.ComputePolyline(APoints, PenWidth, PenColor);
  1890. end;
  1891. function TVectorShape.ComputeStrokeEnvelope(APoints: ArrayOfTPointF;
  1892. AClosed: boolean; AWidth: single): ArrayOfTPointF;
  1893. var
  1894. opt: TBGRAPolyLineOptions;
  1895. begin
  1896. opt := [];
  1897. if AClosed then include(opt, plCycle);
  1898. result := ComputeWidePolyPolylinePoints(APoints, AWidth, BGRABlack, pecRound, pjsMiter, SolidPenStyle, opt);
  1899. end;
  1900. function TVectorShape.GetStroker: TBGRAPenStroker;
  1901. begin
  1902. if FStroker = nil then
  1903. begin
  1904. FStroker := TBGRAPenStroker.Create;
  1905. FStroker.MiterLimit:= 2;
  1906. end;
  1907. result := FStroker;
  1908. end;
  1909. procedure TVectorShape.FillChange(ASender: TObject; var ADiff: TCustomVectorialFillDiff);
  1910. var
  1911. field: TVectorShapeField;
  1912. r: TRectF;
  1913. begin
  1914. r := FFillBeforeChangeBounds;
  1915. FFillBeforeChangeBounds := EmptyRectF;
  1916. if FFillChangeWithoutUpdate then exit;
  1917. //if shape is not being updated, send the fill diff as such
  1918. if not IsUpdating then
  1919. begin
  1920. inc(FRenderIteration);
  1921. if ASender = FPenFill then field := vsfPenFill
  1922. else if ASender = FBackFill then field := vsfBackFill
  1923. else if ASender = FOutlineFill then field := vsfOutlineFill
  1924. else
  1925. begin
  1926. ADiff.Free;
  1927. DoOnChange(r, nil);
  1928. exit;
  1929. end;
  1930. if Assigned(ADiff) then
  1931. begin
  1932. DoOnChange(r, TVectorShapeEmbeddedFillDiff.Create(field, ADiff));
  1933. ADiff := nil;
  1934. end else
  1935. DoOnChange(r, nil);
  1936. end else
  1937. AddFillDiffHandler(ASender as TVectorialFill, ADiff);
  1938. end;
  1939. procedure TVectorShape.FillBeforeChange(ASender: TObject);
  1940. begin
  1941. FFillBeforeChangeBounds := GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  1942. end;
  1943. function TVectorShape.OpenRenderStorage(ACreateIfNecessary: boolean): TShapeRenderStorage;
  1944. begin
  1945. if ACreateIfNecessary then
  1946. result := TShapeRenderStorage.OpenOrCreate(Container.RenderStorage, Id)
  1947. else
  1948. result := TShapeRenderStorage.Open(Container.RenderStorage, Id);
  1949. end;
  1950. procedure TVectorShape.UpdateRenderStorage(ARenderBounds: TRect; AImage: TBGRACustomBitmap);
  1951. var
  1952. imgStream: TMemoryStream;
  1953. shapeStorage: TShapeRenderStorage;
  1954. begin
  1955. if CanHaveRenderStorage then
  1956. begin
  1957. shapeStorage := OpenRenderStorage(true);
  1958. shapeStorage.persistent.Int['iteration'] := FRenderIteration;
  1959. shapeStorage.persistent.Rectangle['bounds'] := ARenderBounds;
  1960. if Assigned(AImage) then
  1961. begin
  1962. imgStream := TMemoryStream.Create;
  1963. AImage.Serialize(imgStream);
  1964. shapeStorage.persistent.WriteFile('image.data', imgStream, false, true);
  1965. //will be compressed when saving
  1966. end else
  1967. shapeStorage.persistent.RemoveFile('image.data');
  1968. shapeStorage.Close;
  1969. end;
  1970. end;
  1971. procedure TVectorShape.DiscardRenderStorage;
  1972. begin
  1973. if CanHaveRenderStorage then
  1974. TShapeRenderStorage.Discard(Container.RenderStorage, Id);
  1975. end;
  1976. procedure TVectorShape.RetrieveRenderStorage(AMatrix: TAffineMatrix; out
  1977. ARenderBounds: TRect; out AImage: TBGRABitmap);
  1978. var
  1979. stream: TStream;
  1980. shapeStorage: TShapeRenderStorage;
  1981. begin
  1982. ARenderBounds := EmptyRect;
  1983. AImage := nil;
  1984. if Assigned(Container) and Assigned(Container.RenderStorage) and (Container.RenderStorage.AffineMatrix['last-matrix']=AMatrix) then
  1985. begin
  1986. shapeStorage := TShapeRenderStorage.Open(Container.RenderStorage, Id);
  1987. if Assigned(shapeStorage.persistent) then
  1988. begin
  1989. if shapeStorage.persistent.Int['iteration'] = FRenderIteration then
  1990. begin
  1991. ARenderBounds := shapeStorage.persistent.Rectangle['bounds'];
  1992. stream := shapeStorage.persistent.GetFileStream('image.data') ;
  1993. if Assigned(stream) and (stream.Size > 0) then
  1994. begin
  1995. stream.Position:= 0;
  1996. AImage := TBGRABitmap.Create;
  1997. AImage.Deserialize(stream);
  1998. end;
  1999. end;
  2000. end;
  2001. shapeStorage.Close;
  2002. end;
  2003. end;
  2004. function TVectorShape.CanHaveRenderStorage: boolean;
  2005. begin
  2006. result := (Id <> 0) and Assigned(Container) and Assigned(Container.RenderStorage);
  2007. end;
  2008. function TVectorShape.AddDiffHandler(AClass: TVectorShapeDiffAny): TVectorShapeDiff;
  2009. var
  2010. i: Integer;
  2011. begin
  2012. result := nil;
  2013. if not IsUpdating then
  2014. raise exception.Create(errDiffHandlerOnlyDuringUpdate);
  2015. if Assigned(FOnChange) then
  2016. begin
  2017. if FDiffs = nil then FDiffs := TVectorShapeDiffList.Create;
  2018. for i := 0 to FDiffs.Count-1 do
  2019. if FDiffs[i] is AClass then exit(FDiffs[i]);
  2020. result := AClass.Create(self);
  2021. FDiffs.Add(result);
  2022. end;
  2023. end;
  2024. procedure TVectorShape.AddFillDiffHandler(AFill: TVectorialFill; ADiff: TCustomVectorialFillDiff);
  2025. var
  2026. h: TVectorShapeCommonFillDiff;
  2027. begin
  2028. if Assigned(AFill) and Assigned(ADiff) then
  2029. begin
  2030. //make sure there is a handler for fill diff
  2031. if GetDiffHandler(TVectorShapeCommonFillDiff)=nil then
  2032. begin
  2033. h := AddDiffHandler(TVectorShapeCommonFillDiff) as TVectorShapeCommonFillDiff;
  2034. if Assigned(h) then
  2035. begin
  2036. //handler is initialized with current fill that is already changed
  2037. //so we need to fix the start value using diff
  2038. if AFill = FPenFill then
  2039. begin
  2040. if h.FStartPenFill=nil then h.FStartPenFill := TVectorialFill.Create;
  2041. ADiff.Unapply(h.FStartPenFill)
  2042. end
  2043. else if AFill = FBackFill then
  2044. begin
  2045. if h.FStartBackFill=nil then h.FStartBackFill := TVectorialFill.Create;
  2046. ADiff.Unapply(h.FStartBackFill);
  2047. end
  2048. else if AFill = FOutlineFill then
  2049. begin
  2050. if h.FStartOutlineFill=nil then h.FStartOutlineFill := TVectorialFill.Create;
  2051. ADiff.Unapply(h.FStartOutlineFill);
  2052. end;
  2053. end;
  2054. end;
  2055. end;
  2056. end;
  2057. function TVectorShape.GetDiffHandler(AClass: TVectorShapeDiffAny): TVectorShapeDiff;
  2058. var
  2059. i: Integer;
  2060. begin
  2061. if Assigned(FDiffs) then
  2062. begin
  2063. for i := 0 to FDiffs.Count-1 do
  2064. if FDiffs[i] is AClass then exit(FDiffs[i]);
  2065. end;
  2066. result := nil;
  2067. end;
  2068. procedure TVectorShape.SetPenColor(AValue: TBGRAPixel);
  2069. var
  2070. vf: TVectorialFill;
  2071. begin
  2072. vf := TVectorialFill.CreateAsSolid(AValue);
  2073. PenFill := vf;
  2074. vf.Free;
  2075. end;
  2076. procedure TVectorShape.SetPenWidth(AValue: single);
  2077. begin
  2078. if AValue < 0 then AValue := 0;
  2079. if FPenWidth = AValue then exit;
  2080. BeginUpdate(TVectorShapeCommonDiff);
  2081. FPenWidth := AValue;
  2082. EndUpdate;
  2083. end;
  2084. procedure TVectorShape.SetPenStyle(AValue: TBGRAPenStyle);
  2085. begin
  2086. if PenStyleEqual(AValue, PenStyle) then exit;
  2087. BeginUpdate(TVectorShapeCommonDiff);
  2088. Stroker.CustomPenStyle := AValue;
  2089. EndUpdate;
  2090. end;
  2091. procedure TVectorShape.SetBackFill(AValue: TVectorialFill);
  2092. begin
  2093. SetFill(FBackFill, AValue, True);
  2094. end;
  2095. procedure TVectorShape.SetPenFill(AValue: TVectorialFill);
  2096. begin
  2097. SetFill(FPenFill, AValue, True);
  2098. end;
  2099. constructor TVectorShape.Create(AContainer: TVectorOriginal);
  2100. begin
  2101. FContainer := AContainer;
  2102. FPenFill := nil;
  2103. FPenWidth := 1;
  2104. FOutlineWidth := DefaultShapeOutlineWidth;
  2105. FStroker := nil;
  2106. FOnChange := nil;
  2107. FOnEditingChange := nil;
  2108. FBackFill := nil;
  2109. FOutlineFill := nil;
  2110. FUsermode:= vsuEdit;
  2111. FRemoving:= false;
  2112. FId := 0;
  2113. FRenderIteration:= 0;
  2114. FFillBeforeChangeBounds := EmptyRectF;
  2115. end;
  2116. class function TVectorShape.CreateFromStorage(
  2117. AStorage: TBGRACustomOriginalStorage; AContainer: TVectorOriginal): TVectorShape;
  2118. var
  2119. objClassName: RawByteString;
  2120. shapeClass: TVectorShapeAny;
  2121. begin
  2122. objClassName := AStorage.RawString['class'];
  2123. if objClassName = '' then raise exception.Create(rsShapeClassNotSpecified);
  2124. shapeClass:= GetVectorShapeByStorageClassName(objClassName);
  2125. if shapeClass = nil then raise exception.Create(StringReplace(rsUnknownShapeClass, '%1', objClassName, []));
  2126. result := shapeClass.Create(AContainer);
  2127. result.LoadFromStorage(AStorage);
  2128. end;
  2129. destructor TVectorShape.Destroy;
  2130. var
  2131. i: Integer;
  2132. begin
  2133. FreeAndNil(FStroker);
  2134. FreeAndNil(FPenFill);
  2135. FreeAndNil(FBackFill);
  2136. FreeAndNil(FOutlineFill);
  2137. if Assigned(FDiffs) then
  2138. for i := 0 to FDiffs.Count-1 do
  2139. FDiffs[i].Free;
  2140. FreeAndNil(FDiffs);
  2141. inherited Destroy;
  2142. end;
  2143. procedure TVectorShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
  2144. ADraft: boolean);
  2145. begin
  2146. Render(ADest, Point(0,0), AMatrix, ADraft);
  2147. end;
  2148. procedure TVectorShape.Render(ADest: TBGRABitmap; ARenderOffset: TPoint;
  2149. AMatrix: TAffineMatrix; ADraft: boolean);
  2150. begin
  2151. Render(ADest, AffineMatrixTranslation(ARenderOffset.X,ARenderOffset.Y)*AMatrix, ADraft);
  2152. end;
  2153. function TVectorShape.SuggestGradientBox(AMatrix: TAffineMatrix): TAffineBox;
  2154. var
  2155. rF: TRectF;
  2156. begin
  2157. rF := GetRenderBounds(InfiniteRect, AMatrix, [rboAssumeBackFill]);
  2158. result := TAffineBox.AffineBox(rF);
  2159. end;
  2160. function TVectorShape.PointInBack(APoint: TPointF): boolean;
  2161. begin
  2162. result := false;
  2163. end;
  2164. function TVectorShape.PointInPen(APoint: TPointF): boolean;
  2165. begin
  2166. result := false;
  2167. end;
  2168. procedure TVectorShape.ConfigureEditor(AEditor: TBGRAOriginalEditor);
  2169. begin
  2170. if (Usermode = vsuEditBackFill) and BackFill.IsEditable then
  2171. BackFill.ConfigureEditor(AEditor)
  2172. else
  2173. if (Usermode = vsuEditPenFill) and PenFill.IsEditable then
  2174. PenFill.ConfigureEditor(AEditor)
  2175. else
  2176. if (Usermode = vsuEditOutlineFill) and OutlineFill.IsEditable then
  2177. OutlineFill.ConfigureEditor(AEditor)
  2178. else
  2179. ConfigureCustomEditor(AEditor);
  2180. end;
  2181. procedure TVectorShape.LoadFromStorage(AStorage: TBGRACustomOriginalStorage);
  2182. var
  2183. f: TVectorShapeFields;
  2184. begin
  2185. f := Fields;
  2186. if f <> [] then
  2187. begin
  2188. BeginUpdate;
  2189. Id := AStorage.Int['id'];
  2190. FRenderIteration := AStorage.Int['iteration'];
  2191. if vsfPenFill in f then LoadFill(AStorage, 'pen', FPenFill);
  2192. if vsfPenWidth in f then PenWidth := AStorage.FloatDef['pen-width', 0];
  2193. if vsfPenStyle in f then PenStyle := AStorage.FloatArray['pen-style'];
  2194. if vsfJoinStyle in f then
  2195. case AStorage.RawString['join-style'] of
  2196. 'round': JoinStyle := pjsRound;
  2197. 'bevel': JoinStyle := pjsBevel;
  2198. else JoinStyle := pjsMiter;
  2199. end;
  2200. if vsfBackFill in f then LoadFill(AStorage, 'back', FBackFill);
  2201. if vsfOutlineFill in f then LoadFill(AStorage, 'outline', FOutlineFill);
  2202. if vsfOutlineWidth in f then OutlineWidth := AStorage.FloatDef['outline-width', DefaultShapeOutlineWidth];
  2203. EndUpdate;
  2204. end;
  2205. end;
  2206. procedure TVectorShape.SaveToStorage(AStorage: TBGRACustomOriginalStorage);
  2207. var
  2208. f: TVectorShapeFields;
  2209. begin
  2210. AStorage.Int['id'] := Id;
  2211. AStorage.Int['iteration'] := FRenderIteration;
  2212. f := Fields;
  2213. if vsfPenFill in f then SaveFill(AStorage, 'pen', FPenFill);
  2214. if vsfPenWidth in f then AStorage.Float['pen-width'] := PenWidth;
  2215. if vsfPenStyle in f then AStorage.FloatArray['pen-style'] := PenStyle;
  2216. if vsfJoinStyle in f then
  2217. case JoinStyle of
  2218. pjsRound: AStorage.RawString['join-style'] := 'round';
  2219. pjsBevel: AStorage.RawString['join-style'] := 'bevel';
  2220. else AStorage.RawString['join-style'] := 'miter';
  2221. end;
  2222. if vsfBackFill in f then SaveFill(AStorage, 'back', FBackFill);
  2223. if OutlineVisible then
  2224. begin
  2225. if vsfOutlineFill in f then SaveFill(AStorage, 'outline', FOutlineFill);
  2226. if vsfOutlineWidth in f then AStorage.Float['outline-width'] := FOutlineWidth
  2227. else AStorage.RemoveAttribute('outline-width');
  2228. end else
  2229. begin
  2230. AStorage.RemoveObject('outline-fill');
  2231. AStorage.RemoveAttribute('outline-color');
  2232. AStorage.RemoveAttribute('outline-width');
  2233. end;
  2234. end;
  2235. procedure TVectorShape.MouseMove(Shift: TShiftState; X, Y: single; var
  2236. ACursor: TOriginalEditorCursor; var AHandled: boolean);
  2237. begin
  2238. //nothing
  2239. end;
  2240. procedure TVectorShape.MouseDown(RightButton: boolean; ClickCount: integer; Shift: TShiftState; X,
  2241. Y: single; var ACursor: TOriginalEditorCursor; var AHandled: boolean);
  2242. begin
  2243. //nothing
  2244. end;
  2245. procedure TVectorShape.MouseUp(RightButton: boolean; Shift: TShiftState; X,
  2246. Y: single; var ACursor: TOriginalEditorCursor; var AHandled: boolean);
  2247. begin
  2248. //nothing
  2249. end;
  2250. procedure TVectorShape.KeyDown(Shift: TShiftState; Key: TSpecialKey;
  2251. var AHandled: boolean);
  2252. begin
  2253. //nothing
  2254. end;
  2255. procedure TVectorShape.KeyUp(Shift: TShiftState; Key: TSpecialKey;
  2256. var AHandled: boolean);
  2257. begin
  2258. //nothing
  2259. end;
  2260. procedure TVectorShape.KeyPress(UTF8Key: string; var AHandled: boolean);
  2261. begin
  2262. //nothing
  2263. end;
  2264. procedure TVectorShape.BringToFront;
  2265. begin
  2266. if Assigned(Container) then
  2267. Container.MoveShapeToIndex(Container.IndexOfShape(self),Container.ShapeCount-1);
  2268. end;
  2269. procedure TVectorShape.SendToBack;
  2270. begin
  2271. if Assigned(Container) then
  2272. Container.MoveShapeToIndex(Container.IndexOfShape(self),0);
  2273. end;
  2274. procedure TVectorShape.MoveUp(APassNonIntersectingShapes: boolean);
  2275. var
  2276. movedShapeBounds, otherShapeBounds: TRectF;
  2277. sourceIdx,idx: integer;
  2278. begin
  2279. if not Assigned(Container) then exit;
  2280. sourceIdx := Container.IndexOfShape(self);
  2281. if sourceIdx = Container.ShapeCount-1 then exit;
  2282. idx := sourceIdx;
  2283. if APassNonIntersectingShapes then
  2284. begin
  2285. movedShapeBounds := self.GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
  2286. while idx < Container.ShapeCount-2 do
  2287. begin
  2288. otherShapeBounds := Container.Shape[idx+1].GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
  2289. if movedShapeBounds.IntersectsWith(otherShapeBounds) then break;
  2290. inc(idx);
  2291. end;
  2292. end;
  2293. inc(idx);
  2294. Container.MoveShapeToIndex(sourceIdx, idx);
  2295. end;
  2296. procedure TVectorShape.MoveDown(APassNonIntersectingShapes: boolean);
  2297. var
  2298. movedShapeBounds, otherShapeBounds: TRectF;
  2299. sourceIdx,idx: integer;
  2300. begin
  2301. if not Assigned(Container) then exit;
  2302. sourceIdx := Container.IndexOfShape(self);
  2303. if sourceIdx = 0 then exit;
  2304. idx := sourceIdx;
  2305. if APassNonIntersectingShapes then
  2306. begin
  2307. movedShapeBounds := self.GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
  2308. while idx > 1 do
  2309. begin
  2310. otherShapeBounds := Container.Shape[idx-1].GetAlignBounds(InfiniteRect, AffineMatrixIdentity);
  2311. if movedShapeBounds.IntersectsWith(otherShapeBounds) then break;
  2312. dec(idx);
  2313. end;
  2314. end;
  2315. dec(idx);
  2316. Container.MoveShapeToIndex(sourceIdx, idx);
  2317. end;
  2318. procedure TVectorShape.Remove;
  2319. var handled: boolean;
  2320. begin
  2321. if Assigned(OnRemoveQuery) then
  2322. begin
  2323. handled := false;
  2324. OnRemoveQuery(self, handled);
  2325. if handled then exit;
  2326. end;
  2327. if Assigned(Container) then Container.RemoveShape(self)
  2328. else raise exception.Create(errUndefinedContainer);
  2329. end;
  2330. procedure TVectorShape.AlignHorizontally(AAlign: TAlignment;
  2331. const AMatrix: TAffineMatrix; const ABounds: TRect);
  2332. var
  2333. sb: TRectF;
  2334. m: TAffineMatrix;
  2335. begin
  2336. if not IsAffineMatrixInversible(AMatrix) then exit;
  2337. sb := GetAlignBounds(ABounds, AMatrix);
  2338. case AAlign of
  2339. taRightJustify: m := AffineMatrixTranslation(ABounds.Right-sb.Right,0);
  2340. taCenter: m := AffineMatrixTranslation((ABounds.Left+ABounds.Right-sb.Left-sb.Right)/2,0);
  2341. else m := AffineMatrixTranslation(ABounds.Left-sb.Left,0);
  2342. end;
  2343. AlignTransform(AffineMatrixInverse(AMatrix)*m*AMatrix);
  2344. end;
  2345. procedure TVectorShape.AlignVertically(AAlign: TTextLayout;
  2346. const AMatrix: TAffineMatrix; const ABounds: TRect);
  2347. var
  2348. sb: TRectF;
  2349. m: TAffineMatrix;
  2350. begin
  2351. if not IsAffineMatrixInversible(AMatrix) then exit;
  2352. sb := GetAlignBounds(ABounds, AMatrix);
  2353. case AAlign of
  2354. tlBottom: m := AffineMatrixTranslation(0,ABounds.Bottom-sb.Bottom);
  2355. tlCenter: m := AffineMatrixTranslation(0,(ABounds.Top+ABounds.Bottom-sb.Top-sb.Bottom)/2);
  2356. else m := AffineMatrixTranslation(0,ABounds.Top-sb.Top);
  2357. end;
  2358. AlignTransform(AffineMatrixInverse(AMatrix)*m*AMatrix);
  2359. end;
  2360. function TVectorShape.GetAlignBounds(const ALayoutRect: TRect;
  2361. const AMatrix: TAffineMatrix): TRectF;
  2362. begin
  2363. result := GetRenderBounds(ALayoutRect, AMatrix, []);
  2364. end;
  2365. procedure TVectorShape.AlignTransform(const AMatrix: TAffineMatrix);
  2366. begin
  2367. Transform(AMatrix);
  2368. end;
  2369. function TVectorShape.Duplicate: TVectorShape;
  2370. var temp: TBGRAMemOriginalStorage;
  2371. shapeClass: TVectorShapeAny;
  2372. begin
  2373. shapeClass:= GetVectorShapeByStorageClassName(StorageClassName);
  2374. if shapeClass = nil then raise exception.Create(StringReplace(rsUnknownShapeClass, '%1', StorageClassName, []));
  2375. result := nil;
  2376. temp := TBGRAMemOriginalStorage.Create;
  2377. FStoreTexturePointer:= true;
  2378. try
  2379. SaveToStorage(temp);
  2380. result := shapeClass.Create(nil);
  2381. result.FStoreTexturePointer := true;
  2382. result.LoadFromStorage(temp);
  2383. finally
  2384. temp.Free;
  2385. FStoreTexturePointer:= false;
  2386. if assigned(result) then
  2387. result.FStoreTexturePointer := false;
  2388. end;
  2389. end;
  2390. { TVectorOriginal }
  2391. function TVectorOriginal.GetShapeCount: integer;
  2392. begin
  2393. result := FShapes.Count;
  2394. end;
  2395. function TVectorOriginal.OpenShapeRenderStorage(AShapeIndex: integer; ACreate: boolean): TBGRACustomOriginalStorage;
  2396. var
  2397. shapeId: Integer;
  2398. begin
  2399. if Assigned(RenderStorage) then
  2400. begin
  2401. shapeId := Shape[AShapeIndex].Id;
  2402. if ACreate then
  2403. result := RenderStorage.CreateObject(inttostr(shapeId))
  2404. else
  2405. result := RenderStorage.OpenObject(inttostr(shapeId));
  2406. end
  2407. else
  2408. result := nil;
  2409. end;
  2410. function TVectorOriginal.FindShapeById(AId: integer): TVectorShape;
  2411. var
  2412. i: Integer;
  2413. begin
  2414. for i := 0 to FShapes.Count-1 do
  2415. if FShapes[i].Id = AId then exit(FShapes[i]);
  2416. exit(nil);
  2417. end;
  2418. procedure TVectorOriginal.DiscardUnusedRenderStorage;
  2419. var
  2420. objs: TStringList;
  2421. shapeId, errPos, i: integer;
  2422. begin
  2423. if Assigned(RenderStorage) then
  2424. begin
  2425. objs := TStringList.Create;
  2426. RenderStorage.EnumerateObjects(objs);
  2427. for i := 0 to objs.Count-1 do
  2428. begin
  2429. val(objs[i], shapeId, errPos);
  2430. if errPos = 0 then
  2431. begin
  2432. if FindShapeById(shapeId) = nil then
  2433. RenderStorage.RemoveObject(objs[i]);
  2434. end;
  2435. end;
  2436. objs.Free;
  2437. end;
  2438. end;
  2439. function TVectorOriginal.InternalInsertShape(AShape: TVectorShape;
  2440. AIndex: integer): TRectF;
  2441. var
  2442. texs: ArrayOfBGRABitmap;
  2443. i: Integer;
  2444. begin
  2445. if AShape = nil then raise exception.Create(errUnexpectedNil);
  2446. if AShape.Container <> self then
  2447. begin
  2448. if AShape.Container = nil then
  2449. AShape.Container := self
  2450. else
  2451. raise exception.Create(errContainerMismatch);
  2452. end;
  2453. if (AIndex < 0) or (AIndex > FShapes.Count) then
  2454. raise exception.Create(rsIndexOutOfBounds);
  2455. FShapes.Insert(AIndex, AShape);
  2456. texs := AShape.GetUsedTextures;
  2457. for i := 0 to high(texs) do AddTexture(texs[i]);
  2458. AShape.OnChange := @OnShapeChange;
  2459. AShape.OnEditingChange := @OnShapeEditingChange;
  2460. DiscardFrozenShapes;
  2461. result := AShape.GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  2462. end;
  2463. function TVectorOriginal.InternalInsertShapeRange(AShapes: TVectorShapes;
  2464. AIndex: integer): TRectF;
  2465. var
  2466. i: Integer;
  2467. r: TRectF;
  2468. begin
  2469. result := EmptyRectF;
  2470. if Assigned(AShapes) then
  2471. for i := 0 to AShapes.Count-1 do
  2472. begin
  2473. r := InternalInsertShape(AShapes[i], AIndex+i);
  2474. if not r.IsEmpty then
  2475. begin
  2476. if result.IsEmpty then result := r
  2477. else result := result.Union(r);
  2478. end;
  2479. end;
  2480. end;
  2481. function TVectorOriginal.InternalDeleteShapeRange(AStartIndex, ACount: integer): TRectF;
  2482. var
  2483. r: TRectF;
  2484. s: TVectorShape;
  2485. i: Integer;
  2486. begin
  2487. result := EmptyRectF;
  2488. if (AStartIndex < 0) or (AStartIndex+ACount > ShapeCount) then
  2489. raise exception.Create(rsIndexOutOfBounds);
  2490. for i := AStartIndex to AStartIndex+ACount-1 do
  2491. if Shape[i].FRemoving then
  2492. raise exception.Create(errAlreadyRemovingShape);
  2493. for i := AStartIndex to AStartIndex+ACount-1 do Shape[i].FRemoving := true;
  2494. for i := AStartIndex to AStartIndex+ACount-1 do DeselectShape(i);
  2495. for i := AStartIndex+ACount-1 downto AStartIndex do
  2496. begin
  2497. s := Shape[i];
  2498. s.OnChange := nil;
  2499. s.OnEditingChange := nil;
  2500. r := s.GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  2501. result := TRectF.Union(result,r,True);
  2502. FShapes.Delete(i);
  2503. FDeletedShapes.Add(s);
  2504. s.FRemoving:= false;
  2505. end;
  2506. DiscardFrozenShapes;
  2507. end;
  2508. function TVectorOriginal.GetNewShapeId: integer;
  2509. begin
  2510. inc(FLastShapeId);
  2511. result := FLastShapeId;
  2512. end;
  2513. function TVectorOriginal.GetShape(AIndex: integer): TVectorShape;
  2514. begin
  2515. result := FShapes[AIndex];
  2516. end;
  2517. procedure TVectorOriginal.MultiSelection_SelectionChange(Sender: TObject);
  2518. begin
  2519. if FMultiselection = FSelectedShape then
  2520. begin
  2521. DiscardFrozenShapes;
  2522. NotifyEditorChange;
  2523. end;
  2524. end;
  2525. procedure TVectorOriginal.FreeDeletedShapes;
  2526. var
  2527. i: Integer;
  2528. begin
  2529. for i := 0 to FDeletedShapes.Count-1 do
  2530. FDeletedShapes[i].Free;
  2531. FDeletedShapes.Clear
  2532. end;
  2533. procedure TVectorOriginal.OnShapeChange(ASender: TObject; ABounds: TRectF; ADiff: TVectorShapeDiff);
  2534. var
  2535. embed: TVectorOriginalShapeDiff;
  2536. idxShape: Integer;
  2537. begin
  2538. if ASender <> FSelectedShape then DiscardFrozenShapes;
  2539. if DiffExpected and Assigned(ADiff) then
  2540. begin
  2541. if ASender = FMultiselection then
  2542. idxShape := -2
  2543. else idxShape := IndexOfShape(ASender as TVectorShape);
  2544. embed := TVectorOriginalShapeDiff.Create(idxShape, ADiff);
  2545. ADiff := nil;
  2546. NotifyChange(ABounds, embed);
  2547. end else
  2548. NotifyChange(ABounds);
  2549. ADiff.Free;
  2550. end;
  2551. procedure TVectorOriginal.OnShapeEditingChange(ASender: TObject);
  2552. begin
  2553. if ASender = FSelectedShape then
  2554. NotifyEditorChange;
  2555. end;
  2556. procedure TVectorOriginal.DiscardFrozenShapes;
  2557. begin
  2558. FFrozenShapesComputed:= false;
  2559. FreeAndNil(FFrozenShapesUnderSelection);
  2560. FreeAndNil(FFrozenShapesOverSelection);
  2561. end;
  2562. function TVectorOriginal.GetTextureId(ABitmap: TBGRABitmap): integer;
  2563. var
  2564. i: Integer;
  2565. begin
  2566. if (ABitmap = nil) or (ABitmap.NbPixels = 0) then exit(EmptyTextureId);
  2567. for i := 0 to FTextureCount-1 do
  2568. if FTextures[i].Bitmap = ABitmap then exit(FTextures[i].Id);
  2569. for i := 0 to FTextureCount-1 do
  2570. if FTextures[i].Bitmap.Equals(ABitmap) then exit(FTextures[i].Id);
  2571. exit(-1);
  2572. end;
  2573. function TVectorOriginal.IndexOfTexture(AId: integer): integer;
  2574. var
  2575. i: Integer;
  2576. begin
  2577. if AId = EmptyTextureId then exit(-1);
  2578. for i := 0 to FTextureCount-1 do
  2579. if FTextures[i].Id = AId then exit(i);
  2580. exit(-1);
  2581. end;
  2582. procedure TVectorOriginal.AddTextureWithId(ATexture: TBGRABitmap; AId: integer);
  2583. begin
  2584. if FTextureCount >= length(FTextures) then
  2585. setlength(FTextures, FTextureCount*2+2);
  2586. if AId > FLastTextureId then FLastTextureId:= AId;
  2587. FTextures[FTextureCount].Bitmap := ATexture.NewReference as TBGRABitmap;
  2588. FTextures[FTextureCount].Id := AId;
  2589. inc(FTextureCount);
  2590. end;
  2591. procedure TVectorOriginal.ClearTextures;
  2592. var
  2593. i: Integer;
  2594. begin
  2595. //note that there are still shapes that could use textures
  2596. for i := 0 to FTextureCount-1 do
  2597. begin
  2598. FTextures[i].Bitmap.FreeReference;
  2599. FTextures[i].Bitmap := nil;
  2600. end;
  2601. FTextureCount := 0;
  2602. FTextures := nil;
  2603. FLastTextureId:= EmptyTextureId;
  2604. end;
  2605. constructor TVectorOriginal.Create;
  2606. begin
  2607. inherited Create;
  2608. FShapes := TVectorShapes.Create;
  2609. FDeletedShapes := TVectorShapes.Create;
  2610. FSelectedShape := nil;
  2611. FFrozenShapesUnderSelection := nil;
  2612. FFrozenShapesOverSelection := nil;
  2613. FFrozenShapesComputed:= false;
  2614. FLastTextureId:= EmptyTextureId;
  2615. FLastShapeId:= 0;
  2616. if VectorMultiselectionFactory <> nil then
  2617. begin
  2618. FMultiselection := VectorMultiselectionFactory.Create(self);
  2619. FMultiselection.Id := -2;
  2620. FMultiselection.OnChange := @OnShapeChange;
  2621. FMultiselection.OnEditingChange := @OnShapeEditingChange;
  2622. FMultiselection.GetAsMultishape.SetOnSelectionChange(@MultiSelection_SelectionChange);
  2623. end
  2624. else FMultiselection := nil;
  2625. end;
  2626. destructor TVectorOriginal.Destroy;
  2627. var
  2628. i: Integer;
  2629. begin
  2630. FMultiselection.Free;
  2631. FSelectedShape := nil;
  2632. for i := 0 to FShapes.Count-1 do
  2633. FShapes[i].Free;
  2634. FreeAndNil(FShapes);
  2635. FreeDeletedShapes;
  2636. FreeAndNil(FDeletedShapes);
  2637. FreeAndNil(FFrozenShapesUnderSelection);
  2638. FreeAndNil(FFrozenShapesOverSelection);
  2639. ClearTextures;
  2640. inherited Destroy;
  2641. end;
  2642. procedure TVectorOriginal.Clear;
  2643. var
  2644. i: Integer;
  2645. begin
  2646. if FShapes.Count > 0 then
  2647. begin
  2648. DeselectShapes;
  2649. for i := 0 to FShapes.Count-1 do
  2650. FDeletedShapes.Add(FShapes[i]);
  2651. FShapes.Clear;
  2652. FLastShapeId:= 0;
  2653. ClearTextures;
  2654. NotifyChange;
  2655. end;
  2656. end;
  2657. function TVectorOriginal.ConvertToSVG(const AMatrix: TAffineMatrix; out AOffset: TPoint): TObject;
  2658. var
  2659. svg: TBGRASVG;
  2660. rb: TRect;
  2661. vb: TSVGViewBox;
  2662. i: Integer;
  2663. sCopy: TVectorShape;
  2664. m: TAffineMatrix;
  2665. defs: TSVGDefine;
  2666. begin
  2667. m := AffineMatrixTranslation(0.5, 0.5) * AMatrix;
  2668. svg := TBGRASVG.Create;
  2669. defs := svg.Content.AppendDefine;
  2670. result := svg;
  2671. rb := GetRenderBounds(InfiniteRect, AffineMatrixIdentity);
  2672. svg.WidthAsPixel:= rb.Width;
  2673. svg.HeightAsPixel := rb.Height;
  2674. AOffset := rb.TopLeft;
  2675. vb.min := PointF(rb.Left, rb.Top);
  2676. vb.size := PointF(rb.Width, rb.Height);
  2677. svg.ViewBox := vb;
  2678. for i := 0 to ShapeCount-1 do
  2679. begin
  2680. if not IsAffineMatrixIdentity(m) then
  2681. begin
  2682. sCopy := Shape[i].Duplicate;
  2683. try
  2684. sCopy.Transform(m);
  2685. sCopy.AppendToSVG(svg.Content, defs);
  2686. finally
  2687. sCopy.Free;
  2688. end;
  2689. end else
  2690. Shape[i].AppendToSVG(svg.Content, defs);
  2691. end;
  2692. if defs.Content.ElementCount = 0 then
  2693. svg.Content.RemoveElement(defs);
  2694. end;
  2695. function TVectorOriginal.AddTexture(ATexture: TBGRABitmap): integer;
  2696. begin
  2697. result := GetTextureId(ATexture);
  2698. if result <> -1 then exit;
  2699. result:= FLastTextureId+1;
  2700. AddTextureWithId(ATexture, result);
  2701. end;
  2702. function TVectorOriginal.GetTexture(AId: integer): TBGRABitmap;
  2703. var
  2704. index: Integer;
  2705. begin
  2706. index := IndexOfTexture(AId);
  2707. if index = -1 then
  2708. result := nil
  2709. else
  2710. result := FTextures[index].Bitmap;
  2711. end;
  2712. procedure TVectorOriginal.DiscardUnusedTextures;
  2713. var
  2714. i, j: Integer;
  2715. texs: array Of TBGRABitmap;
  2716. begin
  2717. for i := 0 to FTextureCount-1 do
  2718. FTextures[i].Counter:= 0;
  2719. for i := 0 to FShapes.Count-1 do
  2720. begin
  2721. texs := FShapes[i].GetUsedTextures;
  2722. for j := 0 to high(texs) do
  2723. inc(FTextures[IndexOfTexture(GetTextureId(texs[j]))].Counter);
  2724. end;
  2725. for i := FTextureCount-1 downto 0 do
  2726. if FTextures[i].Counter = 0 then
  2727. begin
  2728. FTextures[i].Bitmap.FreeReference;
  2729. FTextures[i].Bitmap := nil;
  2730. for j := i to FTextureCount-2 do
  2731. FTextures[j] := FTextures[j+1];
  2732. dec(FTextureCount);
  2733. end;
  2734. if FTextureCount < length(FTextures) div 2 then
  2735. setlength(FTextures, FTextureCount);
  2736. end;
  2737. function TVectorOriginal.AddShape(AShape: TVectorShape): integer;
  2738. begin
  2739. result := ShapeCount;
  2740. InsertShape(AShape, result);
  2741. end;
  2742. function TVectorOriginal.AddShape(AShape: TVectorShape;
  2743. AUsermode: TVectorShapeUsermode): integer;
  2744. begin
  2745. result := AddShape(AShape);
  2746. AShape.Usermode:= AUsermode;
  2747. SelectShape(result);
  2748. end;
  2749. function TVectorOriginal.AddShapes(AShapes: TVectorShapes): integer;
  2750. begin
  2751. result := ShapeCount;
  2752. InsertShapes(AShapes, result);
  2753. end;
  2754. procedure TVectorOriginal.InsertShape(AShape: TVectorShape; AIndex: integer);
  2755. var
  2756. newShapes: TVectorShapes;
  2757. begin
  2758. newShapes := TVectorShapes.Create;
  2759. newShapes.Add(AShape);
  2760. ReplaceShapeRange(AIndex,0,newShapes);
  2761. newShapes.Free;
  2762. end;
  2763. procedure TVectorOriginal.InsertShapes(AShapes: TVectorShapes;
  2764. AIndex: integer);
  2765. begin
  2766. ReplaceShapeRange(AIndex, 0, AShapes);
  2767. end;
  2768. function TVectorOriginal.RemoveShape(AShape: TVectorShape): boolean;
  2769. var
  2770. idx: LongInt;
  2771. multiSel: IVectorMultishape;
  2772. startIndex, endIndex, nextIndex, i, selCount: Integer;
  2773. begin
  2774. if AShape.FRemoving then exit(false);
  2775. if (AShape = FMultiselection) and Assigned(FMultiselection) then
  2776. begin
  2777. multiSel := FMultiselection.GetAsMultishape;
  2778. selCount := multiSel.ShapeCount;
  2779. if selCount = 0 then exit;
  2780. endIndex := IndexOfShape(multiSel.GetShape(selCount-1));
  2781. startIndex := endIndex;
  2782. i := selCount-2;
  2783. while i >= 0 do
  2784. begin
  2785. nextIndex := IndexOfShape(multiSel.GetShape(i));
  2786. if nextIndex < startIndex-1 then
  2787. begin
  2788. DeleteShapeRange(startIndex, endIndex-startIndex+1);
  2789. endIndex := nextIndex;
  2790. startIndex := endIndex;
  2791. end else
  2792. startIndex := nextIndex;
  2793. dec(i);
  2794. end;
  2795. DeleteShapeRange(startIndex, endIndex-startIndex+1);
  2796. end else
  2797. begin
  2798. idx := FShapes.IndexOf(AShape);
  2799. if idx = -1 then exit(false);
  2800. DeleteShapeRange(idx, 1);
  2801. result := true;
  2802. end;
  2803. end;
  2804. procedure TVectorOriginal.DeleteShape(AIndex: integer);
  2805. begin
  2806. DeleteShapeRange(AIndex, 1);
  2807. end;
  2808. procedure TVectorOriginal.DeleteShapeRange(AStartIndex, ACount: integer);
  2809. begin
  2810. ReplaceShapeRange(AStartIndex, ACount, nil);
  2811. end;
  2812. procedure TVectorOriginal.ReplaceShape(AIndex: integer; ANewShape: TVectorShape);
  2813. var newShapes: TVectorShapes;
  2814. begin
  2815. if ANewShape = nil then raise exception.Create(errUnexpectedNil);
  2816. newShapes:= TVectorShapes.Create;
  2817. newShapes.Add(ANewShape);
  2818. ReplaceShapeRange(AIndex, 1, newShapes);
  2819. newShapes.Free;
  2820. end;
  2821. procedure TVectorOriginal.ReplaceShapeRange(AStartIndex: integer;
  2822. ACountBefore: integer; ANewShapes: TVectorShapes);
  2823. var
  2824. rDelete, rInsert: TRectF;
  2825. removed: TVectorShapes;
  2826. diff: TVectorOriginalShapeRangeDiff;
  2827. i: Integer;
  2828. begin
  2829. if (AStartIndex < 0) or (AStartIndex+ACountBefore > ShapeCount) then
  2830. raise exception.Create(rsIndexOutOfBounds);
  2831. if Assigned(ANewShapes) then
  2832. for i := 0 to ANewShapes.Count-1 do
  2833. if ANewShapes[i] is VectorMultiselectionFactory then
  2834. raise exception.Create('Cannot add a multiselection as a shape');
  2835. if Assigned(ANewShapes) then
  2836. for i := 0 to ANewShapes.Count-1 do
  2837. ANewShapes[i].Id := GetNewShapeId;
  2838. if DiffExpected then
  2839. begin
  2840. if ACountBefore > 0 then
  2841. begin
  2842. removed := TVectorShapes.Create;
  2843. for i := 0 to ACountBefore-1 do removed.Add(Shape[AStartIndex+i]);
  2844. end else removed := nil;
  2845. diff := TVectorOriginalShapeRangeDiff.Create(AStartIndex, removed, ANewShapes,
  2846. -1,-1);
  2847. removed.Free;
  2848. end else diff := nil;
  2849. rDelete := InternalDeleteShapeRange(AStartIndex, ACountBefore);
  2850. rInsert := InternalInsertShapeRange(ANewShapes, AStartIndex);
  2851. NotifyChange(TRectF.Union(rDelete,rInsert,True), diff);
  2852. end;
  2853. function TVectorOriginal.SelectShapes(AShapes: TVectorShapes): boolean;
  2854. begin
  2855. if AShapes.Count = 0 then result := DeselectShapes
  2856. else if AShapes.Count = 1 then result := SelectShape(AShapes[0])
  2857. else
  2858. begin
  2859. FSelectedShape := FMultiselection;
  2860. if FMultiselection.GetAsMultishape.SetShapes(AShapes) then
  2861. NotifyEditorChange;
  2862. end;
  2863. end;
  2864. function TVectorOriginal.SelectShape(AIndex: integer; AToggle: boolean): boolean;
  2865. begin
  2866. if AIndex=-1 then result := SelectShape(nil, AToggle)
  2867. else
  2868. begin
  2869. if (AIndex < 0) or (AIndex >= FShapes.Count) then
  2870. raise ERangeError.Create(rsIndexOutOfBounds);
  2871. result := SelectShape(FShapes[AIndex], AToggle);
  2872. end;
  2873. end;
  2874. function TVectorOriginal.SelectShape(AShape: TVectorShape; AToggle: boolean): boolean;
  2875. var
  2876. prevSel, newSel: TVectorShape;
  2877. prevMode: TVectorShapeUsermode;
  2878. multiSel: IVectorMultishape;
  2879. begin
  2880. result := false;
  2881. //when selecting nothing
  2882. if AShape = nil then
  2883. begin
  2884. if not AToggle then
  2885. result := DeselectShapes;
  2886. exit;
  2887. end;
  2888. //selecting current selection
  2889. if AShape = FSelectedShape then
  2890. begin
  2891. if AToggle then
  2892. result := DeselectShapes;
  2893. exit;
  2894. end;
  2895. //check selected shape exists
  2896. if AShape <> nil then
  2897. if FShapes.IndexOf(AShape)=-1 then
  2898. raise exception.Create(rsShapeNotFound);
  2899. //case of modifying multiselection
  2900. if (FSelectedShape = FMultiselection) and Assigned(FMultiselection) and AToggle then
  2901. begin
  2902. multiSel := FSelectedShape.GetAsMultishape;
  2903. if multiSel.ContainsShape(AShape) then
  2904. begin
  2905. multiSel.RemoveShape(AShape);
  2906. if multiSel.ShapeCount = 0 then
  2907. begin
  2908. FSelectedShape := nil;
  2909. exit(true);
  2910. end else
  2911. if multiSel.ShapeCount > 1 then
  2912. exit(true) else
  2913. begin
  2914. SelectShape(multiSel.GetShape(0));
  2915. exit(true);
  2916. end;
  2917. end else
  2918. begin
  2919. multiSel.AddShape(AShape);
  2920. exit(true);
  2921. end;
  2922. end;
  2923. //changing selection completely
  2924. prevSel := FSelectedShape;
  2925. if Assigned(prevSel) then
  2926. begin
  2927. prevMode := prevSel.Usermode;
  2928. prevSel.Usermode := vsuEdit;
  2929. end else
  2930. prevMode := vsuEdit;
  2931. //becomes a multiselection
  2932. if AToggle and (prevSel <> nil) and Assigned(FMultiselection) then
  2933. begin
  2934. multiSel := FMultiselection.GetAsMultishape;
  2935. multiSel.ClearShapes;
  2936. multiSel.AddShape(prevSel);
  2937. multiSel.AddShape(AShape);
  2938. newSel := FMultiselection;
  2939. end else
  2940. begin
  2941. //otherwise simple selection
  2942. newSel := AShape;
  2943. end;
  2944. //transfering user mode
  2945. if (prevMode = vsuEditBackFill) and (prevMode in newSel.Usermodes) and
  2946. newSel.BackFill.IsEditable then newSel.Usermode:= prevMode;
  2947. if (prevMode = vsuEditPenFill) and (prevMode in newSel.Usermodes) and
  2948. newSel.PenFill.IsEditable then newSel.Usermode:= prevMode;
  2949. if (prevMode = vsuEditOutlineFill) and (prevMode in newSel.Usermodes) and
  2950. newSel.OutlineFill.IsEditable then newSel.Usermode:= prevMode;
  2951. if (prevMode = vsuEditText) and (prevMode in newSel.Usermodes) then
  2952. newSel.Usermode := prevMode;
  2953. FSelectedShape := newSel;
  2954. DiscardFrozenShapes;
  2955. NotifyEditorChange;
  2956. if Assigned(FOnSelectShape) then
  2957. FOnSelectShape(self, FSelectedShape, prevSel);
  2958. if (prevSel = FMultiselection) and Assigned(FMultiselection) then
  2959. FMultiselection.GetAsMultishape.ClearShapes;
  2960. end;
  2961. function TVectorOriginal.DeselectShapes: boolean;
  2962. var
  2963. prev: TVectorShape;
  2964. begin
  2965. if SelectedShape = nil then exit(false);
  2966. prev := SelectedShape;
  2967. SelectedShape.Usermode := vsuEdit;
  2968. FSelectedShape := nil;
  2969. if (prev = FMultiselection) and Assigned(FMultiselection) then
  2970. FMultiselection.GetAsMultishape.ClearShapes;
  2971. DiscardFrozenShapes;
  2972. NotifyEditorChange;
  2973. if Assigned(FOnSelectShape) then
  2974. FOnSelectShape(self, nil, prev);
  2975. result := true;
  2976. end;
  2977. procedure TVectorOriginal.DeselectShape(AIndex: integer);
  2978. begin
  2979. if (AIndex >= 0) and (AIndex < ShapeCount) then
  2980. DeselectShape(Shape[AIndex]);
  2981. end;
  2982. procedure TVectorOriginal.DeselectShape(AShape: TVectorShape);
  2983. var
  2984. multiSel: IVectorMultishape;
  2985. begin
  2986. if AShape = SelectedShape then DeselectShapes else
  2987. begin
  2988. if (SelectedShape = FMultiselection) and Assigned(FMultiselection) then
  2989. begin
  2990. multiSel := SelectedShape.GetAsMultishape;
  2991. if multiSel.ContainsShape(AShape) then
  2992. multiSel.RemoveShape(AShape);
  2993. if multiSel.ShapeCount = 1 then
  2994. SelectShape(multiSel.GetShape(0));
  2995. end;
  2996. end;
  2997. end;
  2998. function TVectorOriginal.GetShapesCost: integer;
  2999. var
  3000. i: Integer;
  3001. begin
  3002. result := 0;
  3003. for i := 0 to ShapeCount-1 do
  3004. inc(result, Shape[i].GetGenericCost);
  3005. end;
  3006. function TVectorOriginal.PreferDraftMode(AEditor: TBGRAOriginalEditor; const AMatrix: TAffineMatrix): boolean;
  3007. begin
  3008. if Assigned(SelectedShape) and Assigned(AEditor) then
  3009. begin
  3010. result := (AEditor.IsMovingPoint or SelectedShape.IsFollowingMouse) and
  3011. SelectedShape.GetIsSlow(AMatrix);
  3012. end else
  3013. result := false;
  3014. end;
  3015. function TVectorOriginal.MouseClick(APoint: TPointF; ARadius: single; AToggle: boolean): boolean;
  3016. var
  3017. i: LongInt;
  3018. begin
  3019. for i:= FShapes.Count-1 downto 0 do
  3020. if FShapes[i].PointInShape(APoint) then
  3021. begin
  3022. if SelectedShape <> FShapes[i] then
  3023. begin
  3024. SelectShape(i, AToggle);
  3025. exit(true);
  3026. end else
  3027. exit(false);
  3028. end;
  3029. for i:= FShapes.Count-1 downto 0 do
  3030. if FShapes[i].PointInShape(APoint, ARadius) then
  3031. begin
  3032. if SelectedShape <> FShapes[i] then
  3033. begin
  3034. SelectShape(i, AToggle);
  3035. exit(true);
  3036. end else
  3037. exit(false);
  3038. end;
  3039. if (SelectedShape <> nil) and not AToggle then
  3040. begin
  3041. DeselectShapes;
  3042. exit(true);
  3043. end else
  3044. exit(false);
  3045. end;
  3046. procedure TVectorOriginal.Render(ADest: TBGRABitmap; ARenderOffset: TPoint; AMatrix: TAffineMatrix;
  3047. ADraft: boolean);
  3048. var
  3049. i: Integer;
  3050. idxSelected, newUnfrozenRangeStart, newUnfrozenRangeEnd: LongInt;
  3051. shapeRectF, clipRectF, allRectF: TRectF;
  3052. mOfs: TAffineMatrix;
  3053. multiSel: IVectorMultishape;
  3054. ofsRange: TPoint;
  3055. oldClip: TRect;
  3056. begin
  3057. if FSelectedShape <> FMultiselection then
  3058. begin
  3059. idxSelected := FShapes.IndexOf(FSelectedShape);
  3060. if idxSelected = -1 then
  3061. begin
  3062. FSelectedShape := nil;
  3063. newUnfrozenRangeStart := 0;
  3064. newUnfrozenRangeEnd := ShapeCount;
  3065. end else
  3066. begin
  3067. newUnfrozenRangeStart := idxSelected;
  3068. newUnfrozenRangeEnd := idxSelected+1;
  3069. end;
  3070. end else
  3071. if FMultiselection = nil then
  3072. begin
  3073. newUnfrozenRangeStart := 0;
  3074. newUnfrozenRangeEnd := ShapeCount;
  3075. end else
  3076. begin
  3077. multiSel := FMultiselection.GetAsMultishape;
  3078. if multiSel.ShapeCount = 0 then
  3079. begin
  3080. FSelectedShape := nil;
  3081. newUnfrozenRangeStart := 0;
  3082. newUnfrozenRangeEnd := ShapeCount;
  3083. end;
  3084. newUnfrozenRangeStart := IndexOfShape(multiSel.BackShape);
  3085. newUnfrozenRangeEnd := IndexOfShape(multiSel.FrontShape)+1;
  3086. end;
  3087. if (newUnfrozenRangeStart <> FUnfrozenRangeStart) or
  3088. (newUnfrozenRangeEnd <> FUnfrozenRangeEnd) or
  3089. (AMatrix <> FFrozenShapeMatrix) then
  3090. DiscardFrozenShapes;
  3091. with ADest.ClipRect do
  3092. clipRectF := RectF(Left,Top,Right,Bottom);
  3093. mOfs := AffineMatrixTranslation(ARenderOffset.X,ARenderOffset.Y)*AMatrix;
  3094. if FFrozenShapesComputed then
  3095. begin
  3096. if Assigned(FFrozenShapesUnderSelection) then
  3097. ADest.PutImage(ARenderOffset.X-FFrozenShapesRenderOffset.X+FFrozenShapesUnderBounds.Left,
  3098. ARenderOffset.Y-FFrozenShapesRenderOffset.Y+FFrozenShapesUnderBounds.Top,
  3099. FFrozenShapesUnderSelection, dmSet);
  3100. for i := FUnfrozenRangeStart to FUnfrozenRangeEnd-1 do
  3101. begin
  3102. shapeRectF := FShapes[i].GetRenderBounds(ADest.ClipRect, mOfs, []);
  3103. if shapeRectF.IntersectsWith(clipRectF) then
  3104. begin
  3105. with shapeRectF do
  3106. oldClip := ADest.IntersectClip(rect(floor(Left), floor(Top), ceil(Right), ceil(Bottom)));
  3107. FShapes[i].Render(ADest, ARenderOffset, AMatrix, ADraft);
  3108. ADest.ClipRect := oldClip;
  3109. end;
  3110. end;
  3111. if Assigned(FFrozenShapesOverSelection) then
  3112. ADest.PutImage(ARenderOffset.X-FFrozenShapesRenderOffset.X+FFrozenShapesOverBounds.Left,
  3113. ARenderOffset.Y-FFrozenShapesRenderOffset.Y+FFrozenShapesOverBounds.Top,
  3114. FFrozenShapesOverSelection, dmDrawWithTransparency);
  3115. end else
  3116. begin
  3117. if (newUnfrozenRangeStart > 0) or (newUnfrozenRangeEnd < ShapeCount) then
  3118. begin
  3119. allRectF := rectF(0,0,ADest.Width,ADest.Height);
  3120. FUnfrozenRangeStart := newUnfrozenRangeStart;
  3121. FUnfrozenRangeEnd := newUnfrozenRangeEnd;
  3122. FreeAndNil(FFrozenShapesUnderSelection);
  3123. if FUnfrozenRangeStart > 0 then
  3124. begin
  3125. FFrozenShapesUnderBounds := GetRenderBounds(rect(0,0,ADest.Width,ADest.Height), mOfs,
  3126. 0, FUnfrozenRangeStart-1);
  3127. FFrozenShapesUnderBounds.Intersect(rect(0,0,ADest.Width,ADest.Height));
  3128. FFrozenShapesUnderSelection := TBGRABitmap.Create(FFrozenShapesUnderBounds.Width, FFrozenShapesUnderBounds.Height);
  3129. ofsRange := Point(ARenderOffset.X - FFrozenShapesUnderBounds.Left,
  3130. ARenderOffset.Y - FFrozenShapesUnderBounds.Top);
  3131. for i:= 0 to FUnfrozenRangeStart-1 do
  3132. begin
  3133. shapeRectF := FShapes[i].GetRenderBounds(rect(0,0,ADest.Width,ADest.Height), mOfs, []);
  3134. if shapeRectF.IntersectsWith(allRectF) then
  3135. begin
  3136. shapeRectF.Offset(-FFrozenShapesUnderBounds.Left, -FFrozenShapesUnderBounds.Top);
  3137. with shapeRectF do
  3138. oldClip := FFrozenShapesUnderSelection.IntersectClip(rect(floor(Left), floor(Top), ceil(Right), ceil(Bottom)));
  3139. FShapes[i].Render(FFrozenShapesUnderSelection, ofsRange, AMatrix, false);
  3140. FFrozenShapesUnderSelection.ClipRect := oldClip;
  3141. end;
  3142. end;
  3143. ADest.PutImage(FFrozenShapesUnderBounds.Left, FFrozenShapesUnderBounds.Top,
  3144. FFrozenShapesUnderSelection, dmSet);
  3145. end;
  3146. for i := FUnfrozenRangeStart to FUnfrozenRangeEnd-1 do
  3147. if FShapes[i].GetRenderBounds(ADest.ClipRect, mOfs, []).IntersectsWith(clipRectF) then
  3148. FShapes[i].Render(ADest, ARenderOffset, AMatrix, ADraft);
  3149. FreeAndNil(FFrozenShapesOverSelection);
  3150. if FUnfrozenRangeEnd < FShapes.Count then
  3151. begin
  3152. FFrozenShapesOverBounds := GetRenderBounds(rect(0,0,ADest.Width,ADest.Height), mOfs,
  3153. FUnfrozenRangeEnd, FShapes.Count-1);
  3154. FFrozenShapesOverBounds.Intersect(rect(0,0,ADest.Width,ADest.Height));
  3155. FFrozenShapesOverSelection := TBGRABitmap.Create(FFrozenShapesOverBounds.Width, FFrozenShapesOverBounds.Height);
  3156. ofsRange := Point(ARenderOffset.X - FFrozenShapesOverBounds.Left,
  3157. ARenderOffset.Y - FFrozenShapesOverBounds.Top);
  3158. for i:= FUnfrozenRangeEnd to FShapes.Count-1 do
  3159. begin
  3160. shapeRectF := FShapes[i].GetRenderBounds(rect(0,0,ADest.Width,ADest.Height), mOfs, []);
  3161. if shapeRectF.IntersectsWith(allRectF) then
  3162. begin
  3163. shapeRectF.Offset(-FFrozenShapesOverBounds.Left, -FFrozenShapesOverBounds.Top);
  3164. with shapeRectF do
  3165. oldClip := FFrozenShapesOverSelection.IntersectClip(rect(floor(Left), floor(Top), ceil(Right), ceil(Bottom)));
  3166. FShapes[i].Render(FFrozenShapesOverSelection, ofsRange, AMatrix, false);
  3167. FFrozenShapesOverSelection.ClipRect := oldClip;
  3168. end;
  3169. end;
  3170. ADest.PutImage(FFrozenShapesOverBounds.Left, FFrozenShapesOverBounds.Top,
  3171. FFrozenShapesOverSelection, dmDrawWithTransparency);
  3172. end;
  3173. FFrozenShapesRenderOffset := ARenderOffset;
  3174. FFrozenShapesComputed := true;
  3175. FFrozenShapeMatrix := AMatrix;
  3176. end else
  3177. begin
  3178. for i:= 0 to FShapes.Count-1 do
  3179. if FShapes[i].GetRenderBounds(ADest.ClipRect, mOfs, []).IntersectsWith(clipRectF) then
  3180. FShapes[i].Render(ADest, ARenderOffset, AMatrix, ADraft);
  3181. end;
  3182. end;
  3183. DiscardUnusedRenderStorage;
  3184. end;
  3185. procedure TVectorOriginal.ConfigureEditor(AEditor: TBGRAOriginalEditor);
  3186. begin
  3187. inherited ConfigureEditor(AEditor);
  3188. if Assigned(FSelectedShape) then
  3189. begin
  3190. if (FShapes.IndexOf(FSelectedShape)=-1) and
  3191. (FSelectedShape <> FMultiselection) then
  3192. begin
  3193. FSelectedShape := nil;
  3194. DiscardFrozenShapes;
  3195. end
  3196. else
  3197. FSelectedShape.ConfigureEditor(AEditor);
  3198. end;
  3199. //no more reference to event handlers
  3200. FreeDeletedShapes;
  3201. end;
  3202. function TVectorOriginal.CreateEditor: TBGRAOriginalEditor;
  3203. begin
  3204. Result:= TVectorOriginalEditor.Create(self);
  3205. end;
  3206. function TVectorOriginal.GetRenderBounds(ADestRect: TRect;
  3207. AMatrix: TAffineMatrix): TRect;
  3208. begin
  3209. result := GetRenderBounds(ADestRect, AMatrix, 0, ShapeCount-1);
  3210. end;
  3211. function TVectorOriginal.GetRenderBounds(ADestRect: TRect;
  3212. AMatrix: TAffineMatrix; AStartIndex, AEndIndex: integer): TRect;
  3213. var
  3214. area, shapeArea: TRectF;
  3215. i: Integer;
  3216. shapeDir: TBGRACustomOriginalStorage;
  3217. useStorage: Boolean;
  3218. iteration: LongInt;
  3219. begin
  3220. area:= EmptyRectF;
  3221. useStorage := Assigned(RenderStorage) and (RenderStorage.AffineMatrix['last-matrix']=AMatrix);
  3222. for i:= AStartIndex to AEndIndex do
  3223. begin
  3224. if useStorage then
  3225. begin
  3226. shapeDir := OpenShapeRenderStorage(i, false);
  3227. if Assigned(shapeDir) then
  3228. begin
  3229. iteration := shapeDir.Int['iteration'];
  3230. if iteration = FShapes[i].FRenderIteration then
  3231. begin
  3232. shapeArea := shapeDir.RectangleF['bounds'];
  3233. area := area.Union(shapeArea, true);
  3234. shapeDir.Free;
  3235. continue;
  3236. end;
  3237. end;
  3238. end;
  3239. shapeArea := FShapes[i].GetRenderBounds(ADestRect, AMatrix);
  3240. area := area.Union(shapeArea, true);
  3241. end;
  3242. if IsEmptyRectF(area) then
  3243. result := EmptyRect
  3244. else
  3245. result := rect(floor(area.Left),floor(area.Top),ceil(area.Right),ceil(area.Bottom));
  3246. end;
  3247. function TVectorOriginal.GetAlignBounds(ADestRect: TRect; AMatrix: TAffineMatrix): TRect;
  3248. var
  3249. area, shapeArea: TRectF;
  3250. i: Integer;
  3251. begin
  3252. area:= EmptyRectF;
  3253. for i:= 0 to FShapes.Count-1 do
  3254. begin
  3255. shapeArea := FShapes[i].GetAlignBounds(ADestRect, AMatrix);
  3256. area := area.Union(shapeArea, true);
  3257. end;
  3258. if IsEmptyRectF(area) then
  3259. result := EmptyRect
  3260. else
  3261. result := rect(floor(area.Left),floor(area.Top),ceil(area.Right),ceil(area.Bottom));
  3262. end;
  3263. procedure TVectorOriginal.LoadFromStorage(AStorage: TBGRACustomOriginalStorage);
  3264. var
  3265. nb: LongInt;
  3266. i: Integer;
  3267. shapeObj, texObj: TBGRACustomOriginalStorage;
  3268. texName: String;
  3269. loadedShape: TVectorShape;
  3270. idList: array of single;
  3271. texId: integer;
  3272. bmp: TBGRABitmap;
  3273. strErrors: string;
  3274. begin
  3275. Clear;
  3276. texObj := AStorage.OpenObject('textures');
  3277. if Assigned(texObj) then
  3278. begin
  3279. try
  3280. idList := texObj.FloatArray['id'];
  3281. for i := 0 to high(idList) do
  3282. begin
  3283. texId:= round(idList[i]);
  3284. texName:= 'tex'+inttostr(texId);
  3285. try
  3286. bmp := TBGRABitmap.Create;
  3287. if not texObj.ReadBitmap(texName+'.png', bmp) and
  3288. not texObj.ReadBitmap(texName+'.jpg', bmp) then
  3289. raise exception.Create(errUnableToFindTexture);
  3290. AddTextureWithId(bmp, texId);
  3291. finally
  3292. bmp.FreeReference;
  3293. end;
  3294. end;
  3295. finally
  3296. texObj.Free;
  3297. end;
  3298. end;
  3299. strErrors := '';
  3300. nb := AStorage.Int['count'];
  3301. for i:= 0 to nb-1 do
  3302. begin
  3303. shapeObj := AStorage.OpenObject('shape'+inttostr(i+1));
  3304. if shapeObj <> nil then
  3305. try
  3306. loadedShape := TVectorShape.CreateFromStorage(shapeObj, self);
  3307. loadedShape.OnChange := @OnShapeChange;
  3308. loadedShape.OnEditingChange := @OnShapeEditingChange;
  3309. if loadedShape.Id > FLastShapeId then FLastShapeId := loadedShape.Id;
  3310. FShapes.Add(loadedShape);
  3311. except
  3312. on ex: exception do
  3313. AppendStr(strErrors, ex.Message + ' ');
  3314. end;
  3315. shapeObj.Free;
  3316. end;
  3317. for i := 0 to ShapeCount-1 do
  3318. if Shape[i].Id = 0 then
  3319. Shape[i].Id := GetNewShapeId;
  3320. NotifyChange;
  3321. if strErrors <> '' then
  3322. raise exception.Create(errErrorLoadingShape + ': ' + Trim(strErrors));
  3323. end;
  3324. procedure TVectorOriginal.SaveToStorage(AStorage: TBGRACustomOriginalStorage);
  3325. var
  3326. nb: LongInt;
  3327. i, texIndex: Integer;
  3328. shapeObj, texObj: TBGRACustomOriginalStorage;
  3329. idList: array of single;
  3330. texName: String;
  3331. mem: TMemoryStream;
  3332. texId: integer;
  3333. begin
  3334. nb := AStorage.Int['count'];
  3335. for i := 0 to nb-1 do AStorage.RemoveObject('shape'+inttostr(i+1));
  3336. AStorage.Int['count'] := 0;
  3337. for i := 0 to FShapes.Count-1 do
  3338. begin
  3339. shapeObj := AStorage.CreateObject('shape'+inttostr(i+1));
  3340. shapeObj.RawString['class'] := FShapes[i].StorageClassName;
  3341. try
  3342. FShapes[i].SaveToStorage(shapeObj);
  3343. AStorage.Int['count'] := i+1;
  3344. finally
  3345. shapeObj.Free;
  3346. end;
  3347. end;
  3348. if FTextureCount = 0 then
  3349. AStorage.RemoveObject('textures')
  3350. else
  3351. begin
  3352. texObj := nil;
  3353. try
  3354. texObj := AStorage.OpenObject('textures');
  3355. if texObj = nil then
  3356. texObj := AStorage.CreateObject('textures');
  3357. for i := 0 to FTextureCount-1 do
  3358. FTextures[i].Counter:= 0;
  3359. idList := texObj.FloatArray['id'];
  3360. for i := 0 to high(idList) do
  3361. begin
  3362. texId := round(idList[i]);
  3363. texIndex:= IndexOfTexture(texId);
  3364. if texIndex=-1 then
  3365. begin
  3366. texName := 'tex'+inttostr(texId);
  3367. texObj.RemoveFile(texName+'.png');
  3368. texObj.RemoveFile(texName+'.jpg');
  3369. end else
  3370. inc(FTextures[texIndex].Counter);
  3371. end;
  3372. setlength(idList, FTextureCount);
  3373. for i := 0 to FTextureCount-1 do
  3374. begin
  3375. if FTextures[i].Counter = 0 then
  3376. begin
  3377. texName := 'tex'+inttostr(FTextures[i].Id);
  3378. mem := TMemoryStream.Create;
  3379. try
  3380. FTextures[i].Bitmap.SaveToStreamAsPng(mem);
  3381. texObj.WriteFile(texName+'.png', mem, false);
  3382. finally
  3383. mem.Free;
  3384. end;
  3385. end;
  3386. idList[i] := FTextures[i].Id;
  3387. end;
  3388. texObj.FloatArray['id'] := idList;
  3389. finally
  3390. texObj.Free;
  3391. end;
  3392. end;
  3393. end;
  3394. function TVectorOriginal.IndexOfShape(AShape: TVectorShape): integer;
  3395. begin
  3396. result := FShapes.IndexOf(AShape);
  3397. end;
  3398. procedure TVectorOriginal.MoveShapeToIndex(AFromIndex, AToIndex: integer);
  3399. begin
  3400. MoveShapeToIndex([AFromIndex], [AToIndex]);
  3401. end;
  3402. procedure TVectorOriginal.MoveShapeToIndex(AFromIndex,
  3403. AToIndex: array of integer);
  3404. var
  3405. diff: TVectorOriginalMoveShapeToIndexDiff;
  3406. begin
  3407. diff := TVectorOriginalMoveShapeToIndexDiff.Create(AFromIndex, AToIndex);
  3408. if diff.IsIdentity then
  3409. begin
  3410. diff.Free;
  3411. exit;
  3412. end;
  3413. diff.Apply(self, true);
  3414. end;
  3415. class function TVectorOriginal.StorageClassName: RawByteString;
  3416. begin
  3417. result := 'vector';
  3418. end;
  3419. class function TVectorOriginal.CanConvertToSVG: boolean;
  3420. begin
  3421. result := true;
  3422. end;
  3423. initialization
  3424. RegisterLayerOriginal(TVectorOriginal);
  3425. end.