123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067 |
- /*
- * Copyright (C) =USTC= Fu Li
- *
- * Author : Fu Li
- * Create : 2003-4-8
- * Home : http://www.crazy-bit.com/
- * Mail : crazybit@263.net
- * History :
- */
- #ifndef __FOO_COMMAND__2003_04_08__H__
- #define __FOO_COMMAND__2003_04_08__H__
- #include "../ObjCanvas.h"
- // base class of normal image effect command
- class FCCmdImgEffect ;
- class FCCmdImgPixelProcessor ; // receive a FCSinglePixelProcessBase object
- class FCCmdImgSetAlpha ; // set image's alpha
- class FCCmdImgAddShadow ; // add shadow
- class FCCmdImageMask ; // create image to mask
- class FCCmdMaskColor ; // mask color on layer
- class FCCmdMaskGradientBase ; // base class of mask gradient on layer
- class FCCmdMaskGradientLine ; // mask linear gradient on layer
- class FCCmdMaskGradientBiLine ; // mask bilinear gradient on layer
- class FCCmdMaskGradientConicalSym ; // mask symmetric conical gradient on layer
- class FCCmdMaskGradientConicalASym ; // mask anti-symmetric conical gradient on layer
- class FCCmdMaskGradientRect ; // mask rectangle gradient on layer
- class FCCmdMaskGradientRadial ; // mask radial gradient on layer
- class FCCmdMaskLineBase ; // base class of mask line on layer
- // auto enlarge layer to fill up canvas
- class FCCmdAutoEnlargeLayer ;
- // selection operation
- class FCCmdSelectionSetBase ; // base class to set canvas's region
- class FCCmdSelectionInvert ; // invert current region
- class FCCmdSelectionCanvasAll ; // select all canvas
- class FCCmdSelectionClear ; // clear selection
- class FCCmdSelectionSmooth ; // smooth selection
- class FCCmdSelectionBlendHaloBase ;
- class FCCmdSelectionExpand ; // expand selection
- class FCCmdSelectionShrink ; // shrink selection
- class FCCmdSelectionBorder ; // border selection
- class FCCmdSelectionCreateBase ;
- class FCCmdSelectionCreateRect ; // rectangle region
- class FCCmdSelectionCreateEllipse ; // ellipse region
- class FCCmdSelectionCreatePolygonBase ; // polygon region
- class FCCmdSelectionCreateMagicWand ; // magic wand
- // Layer's operation
- class FCCmdLayerOperation ;
- class FCCmdLayerStretch ; // stretch layer
- class FCCmdLayerRotate ; // rotate layer
- class FCCmdLayerRotate90 ; // clockwise rotate 90'
- class FCCmdLayerRotate270 ; // clockwise rotate 270'
- class FCCmdLayerSkew ; // skew transform
- class FCCmdLayerLens ; // lens transform
- class FCCmdLayerCrop ; // crop layer
- class FCCmdLayerMove ; // move layer
- class FCCmdLayerAdd ; // add new layer to canvas
- class FCCmdLayerRemove ; // remove layer from canvas
- class FCCmdLayerSaveProperty ; // save layer's property
- class FCCmdLayerExchange ; // change layer's sequence in canvas
- // 组合命令,可以把频繁使用的cmd(如:layer move组合成为一个cmd)
- // class FCCmdComposite ;
- class FCCmdLayerMerge ; // merge layers
- class FCCmdLayerListRemove ; // delete layers from canvas
- class FCCmdCanvasOperation ;
- class FCCmdCanvasResize ; // resize canvas
- class FCCmdCanvasRotate90 ; // canvas rotate 90'
- class FCCmdCanvasRotate270 ; // canvas rotate 270'
- class FCCmdCanvasRotate ; // rotate canvas
- class FCCmdCanvasStretch ; // stretch canvas
- class FCCmdCanvasCrop ; // crop canvas
- class FCCmdCanvasAutoCrop ; // 自动裁减画布/auto crop canvas
- //=============================================================================
- /**
- * Base class of image effect command.
- */
- class FCCmdImgEffect : public FCCmdArtPrider
- {
- public:
- FCCmdImgEffect() : m_pLayer(0) {}
- protected:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_pLayer = canvas.GetCurrentLayer() ;
- if (!m_pLayer || !m_pLayer->IsValidImage())
- return ;
- // start
- if (pProgress)
- pProgress->ResetProgress() ;
- if (!canvas.HasSelected())
- {
- // save whole layer
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- this->Implement (*m_pLayer, pProgress) ;
- // don't change alpha channel
- if (IsLayerLimited(*m_pLayer))
- for (int y=0 ; y < m_Undo.Height() ; y++)
- for (int x=0 ; x < m_Undo.Width() ; x++)
- PCL_A(m_pLayer->GetBits(x,y)) = PCL_A(m_Undo.GetBits(x,y)) ;
- }
- else
- {
- RECT rcOnSel ;
- {
- RECT rcOnLayer = {0, 0, canvas.GetSelection().Width(), canvas.GetSelection().Height()} ;
- canvas.GetSelection().Layer_to_Canvas (rcOnLayer) ;
- m_pLayer->Canvas_to_Layer (rcOnLayer) ;
- m_pLayer->BoundRect (rcOnLayer) ;
- if (IsRectEmpty (&rcOnLayer))
- return ;
- m_pRectOnLayer = std::auto_ptr<RECT>(new RECT) ;
- rcOnSel = *m_pRectOnLayer = rcOnLayer ;
- m_pLayer->Layer_to_Canvas (rcOnSel) ;
- canvas.GetSelection().Canvas_to_Layer (rcOnSel) ;
- }
- // save region
- m_pLayer->GetSubBlock (&m_Undo, *m_pRectOnLayer) ;
- m_Undo.SetGraphObjPos (m_pLayer->GetGraphObjPos().x + m_pRectOnLayer->left,
- m_pLayer->GetGraphObjPos().y + m_pRectOnLayer->top) ;
- // set alpha == 0 out of selection, some effect need (such as box blur)
- FCObjImage block(m_Undo) ;
- {
- for (int y=0 ; y < block.Height() ; y++)
- for (int x=0 ; x < block.Width() ; x++)
- if (*canvas.GetSelection().GetBits (x+rcOnSel.left, y+rcOnSel.top) == 0)
- *(RGBQUAD*)block.GetBits(x,y) = PCL_RGBA(0xFF,0xFF,0xFF,0) ;
- }
- // process
- this->Implement (block, pProgress) ;
- // put back
- for (int y=0 ; y < block.Height() ; y++)
- for (int x=0 ; x < block.Width() ; x++)
- if (*canvas.GetSelection().GetBits (x+rcOnSel.left, y+rcOnSel.top))
- FCColor::CopyPixel (m_pLayer->GetBits (x+m_pRectOnLayer->left, y+m_pRectOnLayer->top),
- block.GetBits(x,y),
- IsLayerLimited(*m_pLayer) ? 3 : 4) ;
- }
- if (pProgress)
- pProgress->SetProgress (100) ; // set 100%
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- if (!m_Undo.IsValidImage() || !m_pLayer)
- {assert(false); return;}
- if (!m_pRectOnLayer.get())
- {
- // whole image
- m_Redo = *static_cast<FCObjImage*>(m_pLayer) ;
- *static_cast<FCObjImage*>(m_pLayer) = m_Undo ;
- }
- else
- {
- m_pLayer->GetSubBlock (&m_Redo, *m_pRectOnLayer) ;
- m_pLayer->CoverBlock (m_Undo, m_pRectOnLayer->left, m_pRectOnLayer->top) ;
- }
- m_Undo.Destroy() ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- if (!m_Redo.IsValidImage() || !m_pLayer)
- {assert(false); return;}
- if (!m_pRectOnLayer.get())
- {
- // whole image
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- *static_cast<FCObjImage*>(m_pLayer) = m_Redo ;
- }
- else
- {
- m_pLayer->GetSubBlock (&m_Undo, *m_pRectOnLayer) ;
- m_pLayer->CoverBlock (m_Redo, m_pRectOnLayer->left, m_pRectOnLayer->top) ;
- }
- m_Redo.Destroy() ;
- }
- /// Process image, don't change img's size & position.
- virtual void Implement (FCObjImage& img, FCObjProgress* pProgress) {}
- virtual bool IsLayerLimited (const FCObjLayer& rLayer) const
- {
- return rLayer.IsLayerLimited() ? true : false ;
- }
- FCObjLayer * m_pLayer ;
- FCObjImage m_Undo ;
- FCObjImage m_Redo ;
- std::auto_ptr<RECT> m_pRectOnLayer ;
- };
- //=============================================================================
- /**
- * Process image use a FCSinglePixelProcessBase command.
- */
- class FCCmdImgPixelProcessor : public FCCmdImgEffect
- {
- public:
- /// Constructor (pProcessor must use <B>new</B> to create).
- FCCmdImgPixelProcessor (FCSinglePixelProcessBase* pProcessor) : m_pProcessor(pProcessor) {}
- virtual void Implement (FCObjImage& img, FCObjProgress* pProgress)
- {
- if (m_pProcessor.get())
- img.SinglePixelProcessProc (*m_pProcessor, pProgress) ;
- }
- private:
- std::auto_ptr<FCInterface_PixelProcess> m_pProcessor ;
- };
- //=============================================================================
- /**
- * Set layer's alpha, ignore layer's limited.
- */
- class FCCmdImgSetAlpha : public FCCmdImgEffect
- {
- public:
- /// Constructor.
- FCCmdImgSetAlpha (int nAlpha) : m_nAlpha(FClamp0255(nAlpha)) {}
- private:
- virtual void Implement (FCObjImage& img, FCObjProgress* pProgress)
- {
- if (img.IsValidImage() && (img.ColorBits() == 32))
- img.SetAlphaChannelValue (m_nAlpha) ;
- }
- virtual bool IsLayerLimited (const FCObjLayer& rLayer) const
- {
- return false ;
- }
- private:
- int m_nAlpha ;
- };
- //=============================================================================
- /**
- * Add shadow.
- */
- class FCCmdImgAddShadow : public FCCmdImgEffect
- {
- public:
- /// Constructor.
- FCCmdImgAddShadow (SHADOWDATA ShData)
- {
- m_ShadowData = ShData ;
- m_ShadowData.nSmooth = FMax (2, (int)m_ShadowData.nSmooth) ;
- m_ShadowData.nAlpha = FClamp ((int)m_ShadowData.nAlpha, 1, 100) ;
- }
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_pLayer = canvas.GetCurrentLayer() ;
- if (!m_pLayer || !m_pLayer->IsValidImage())
- return ;
- // start
- if (pProgress)
- pProgress->ResetProgress() ;
- if (!canvas.HasSelected())
- {
- // save whole layer
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- this->Implement (*m_pLayer, pProgress) ;
- }
- else
- {
- RECT rcOnSel ;
- {
- RECT rcOnLayer = {0, 0, canvas.GetSelection().Width(), canvas.GetSelection().Height()} ;
- canvas.GetSelection().Layer_to_Canvas (rcOnLayer) ;
- m_pLayer->Canvas_to_Layer (rcOnLayer) ;
- m_pLayer->BoundRect (rcOnLayer) ;
- if (IsRectEmpty (&rcOnLayer))
- return ;
- m_pRectOnLayer = std::auto_ptr<RECT>(new RECT) ;
- rcOnSel = *m_pRectOnLayer = rcOnLayer ;
- m_pLayer->Layer_to_Canvas (rcOnSel) ;
- canvas.GetSelection().Canvas_to_Layer (rcOnSel) ;
- }
- // set alpha == 0 out of selection
- FCObjImage imgBlock ;
- m_pLayer->GetSubBlock (&imgBlock, *m_pRectOnLayer) ;
- {
- for (int y=0 ; y < imgBlock.Height() ; y++)
- for (int x=0 ; x < imgBlock.Width() ; x++)
- if (*canvas.GetSelection().GetBits (x+rcOnSel.left, y+rcOnSel.top) == 0)
- *(RGBQUAD*)imgBlock.GetBits(x,y) = PCL_RGBA(0xFF,0xFF,0xFF,0) ;
- }
- // calculate shadowed image size
- RECT rcShadow = *m_pRectOnLayer ;
- ::OffsetRect (&rcShadow, m_ShadowData.nOffsetX, m_ShadowData.nOffsetY) ;
- ::InflateRect (&rcShadow, m_ShadowData.nSmooth, m_ShadowData.nSmooth) ;
- ::UnionRect (&rcShadow, m_pRectOnLayer.get(), &rcShadow) ;
- // calculate the expand size
- const RECT rcLayer = {0, 0, m_pLayer->Width(), m_pLayer->Height()} ;
- if (IsRectInRect (rcLayer, rcShadow))
- {
- *m_pRectOnLayer = rcShadow ;
- m_pLayer->GetSubBlock (&m_Undo, rcShadow) ;
- }
- else
- {
- m_pRectOnLayer = std::auto_ptr<RECT>() ;
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- int nExpL = (rcShadow.left >= 0) ? 0 : -rcShadow.left,
- nExpT = (rcShadow.top >= 0) ? 0 : -rcShadow.top,
- nExpR = (rcShadow.right > rcLayer.right) ? (rcShadow.right-rcLayer.right) : 0,
- nExpB = (rcShadow.bottom > rcLayer.bottom) ? (rcShadow.bottom-rcLayer.bottom) : 0 ;
- m_pLayer->ExpandFrame (false, nExpL, nExpT, nExpR, nExpB) ;
- OffsetRect (&rcShadow, nExpL, nExpT) ;
- }
- // make shadow image
- FCCmdImgSetAlpha cmdClear(0) ;
- static_cast<FCCmdArtPrider&>(cmdClear).Execute (canvas, NULL) ; // clear region and combine later
- this->Implement (imgBlock, pProgress) ;
- m_pLayer->CombineImage (imgBlock, rcShadow.left, rcShadow.top) ;
- }
- if (pProgress)
- pProgress->SetProgress (100) ; // set 100%
- }
- virtual void Implement (FCObjImage& img, FCObjProgress* pProgress)
- {
- FCPixelAddShadow aCmd(m_ShadowData) ;
- img.SinglePixelProcessProc(aCmd, pProgress) ;
- }
- private:
- SHADOWDATA m_ShadowData ;
- };
- //=============================================================================
- /**
- * Create image to mask.
- */
- class FCCmdImageMask : public FCCmdImgEffect
- {
- virtual void Implement (FCObjImage& img, FCObjProgress* pProgress)
- {
- FCObjImage imgMask ;
- CreateMaskImage (img, imgMask, pProgress) ;
- img.CombineImage (imgMask) ;
- }
- protected:
- /// Create 32bpp mask image as imgMask.
- virtual void CreateMaskImage (const FCObjImage& img, FCObjImage& imgMask, FCObjProgress* pProgress) =0 ;
- };
- //=============================================================================
- /**
- * Mask color on layer.
- */
- class FCCmdMaskColor : public FCCmdImageMask
- {
- virtual void CreateMaskImage (const FCObjImage& img, FCObjImage& imgMask, FCObjProgress* pProgress)
- {
- imgMask.Create (img.Width(), img.Height(), 32) ;
-
- FCPixelCombineColor aCmd(m_crFill) ;
- imgMask.SinglePixelProcessProc (aCmd, pProgress) ;
- }
- RGBQUAD m_crFill ;
- public:
- /// Constructor (combine base on alpha of crFill).
- FCCmdMaskColor (RGBQUAD crFill) : m_crFill(crFill) {}
- };
- //=============================================================================
- /**
- * Base class of mask gradient on layer.
- */
- class FCCmdMaskGradientBase : public FCCmdImageMask
- {
- virtual void CreateMaskImage (const FCObjImage& img, FCObjImage& imgMask, FCObjProgress* pProgress)
- {
- imgMask.Create (img.Width(), img.Height(), 32) ;
- std::auto_ptr<FCPixelGradientBase> m_pCmd (CreateGradientCommand (img, m_cr1, m_cr2, m_nRepeat)) ;
- imgMask.SinglePixelProcessProc (*m_pCmd, pProgress) ;
- imgMask.SetAlphaChannelValue (m_nAlpha) ;
- }
- RGBQUAD m_cr1, m_cr2 ;
- REPEAT_MODE m_nRepeat ;
- int m_nAlpha ;
- public:
- /// Constructor.
- FCCmdMaskGradientBase (int nAlpha, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : m_nAlpha(nAlpha), m_cr1(cr1), m_cr2(cr2), m_nRepeat(nRepeat) {}
- /// New a gradient fill command.
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) =0 ;
- };
- //=============================================================================
- /**
- * Mask linear gradient on layer.
- */
- class FCCmdMaskGradientLine : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- POINT pt1=m_pt1, pt2=m_pt2 ;
- img.Canvas_to_Layer (pt1) ;
- img.Canvas_to_Layer (pt2) ;
- return new FCPixelGradientLine (pt1, pt2, cr1, cr2, nRepeat) ;
- }
- POINT m_pt1, m_pt2 ; // on canvas
- public:
- /// Constructor.
- FCCmdMaskGradientLine (int nAlpha, POINT pt1, POINT pt2, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_pt1=pt1 ; m_pt2=pt2 ;
- }
- };
- //=============================================================================
- /**
- * Mask bilinear gradient on layer.
- */
- class FCCmdMaskGradientBiLine : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- POINT pt1=m_pt1, pt2=m_pt2 ;
- img.Canvas_to_Layer (pt1) ;
- img.Canvas_to_Layer (pt2) ;
- return new FCPixelGradientBiLine (pt1, pt2, cr1, cr2, nRepeat) ;
- }
- POINT m_pt1, m_pt2 ; // on canvas
- public:
- /// Constructor.
- FCCmdMaskGradientBiLine (int nAlpha, POINT pt1, POINT pt2, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_pt1=pt1 ; m_pt2=pt2 ;
- }
- };
- //=============================================================================
- /**
- * Mask symmetric conical gradient on layer.
- */
- class FCCmdMaskGradientConicalSym : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- POINT pt1=m_pt1, pt2=m_pt2 ;
- img.Canvas_to_Layer (pt1) ;
- img.Canvas_to_Layer (pt2) ;
- return new FCPixelGradientConicalSym (pt1, pt2, cr1, cr2, nRepeat) ;
- }
- POINT m_pt1, m_pt2 ; // on canvas
- public:
- /// Constructor.
- FCCmdMaskGradientConicalSym (int nAlpha, POINT pt1, POINT pt2, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_pt1=pt1 ; m_pt2=pt2 ;
- }
- };
- //=============================================================================
- /**
- * Mask anti-symmetric conical gradient on layer.
- */
- class FCCmdMaskGradientConicalASym : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- POINT pt1=m_pt1, pt2=m_pt2 ;
- img.Canvas_to_Layer (pt1) ;
- img.Canvas_to_Layer (pt2) ;
- return new FCPixelGradientConicalASym (pt1, pt2, cr1, cr2, nRepeat) ;
- }
- POINT m_pt1, m_pt2 ; // on canvas
- public:
- /// Constructor.
- FCCmdMaskGradientConicalASym (int nAlpha, POINT pt1, POINT pt2, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_pt1=pt1 ; m_pt2=pt2 ;
- }
- };
- //=============================================================================
- /**
- * Mask rectangle gradient on layer.
- */
- class FCCmdMaskGradientRect : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- RECT rc = m_rcOnCanvas ;
- img.Canvas_to_Layer (rc) ;
- return new FCPixelGradientRect (rc, cr1, cr2, nRepeat) ;
- }
- RECT m_rcOnCanvas ;
- public:
- /// Constructor.
- FCCmdMaskGradientRect (int nAlpha, RECT rcOnCanvas, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_rcOnCanvas = rcOnCanvas ;
- }
- };
- //=============================================================================
- /**
- * Mask radial gradient on layer.
- */
- class FCCmdMaskGradientRadial : public FCCmdMaskGradientBase
- {
- virtual FCPixelGradientBase* CreateGradientCommand (const FCObjImage& img, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat)
- {
- RECT rc = m_rcOnCanvas ;
- img.Canvas_to_Layer (rc) ;
- return new FCPixelGradientRadial (rc, cr1, cr2, nRepeat) ;
- }
- RECT m_rcOnCanvas ;
- public:
- /// Constructor.
- FCCmdMaskGradientRadial (int nAlpha, RECT rcOnCanvas, RGBQUAD cr1, RGBQUAD cr2, REPEAT_MODE nRepeat) : FCCmdMaskGradientBase(nAlpha, cr1, cr2, nRepeat)
- {
- m_rcOnCanvas = rcOnCanvas ;
- }
- };
- //=============================================================================
- /**
- * Base class of mask line on layer.
- */
- class FCCmdMaskLineBase : public FCCmdImageMask
- {
- virtual void CreateMaskImage (const FCObjImage& img, FCObjImage& imgMask, FCObjProgress* pProgress)
- {
- FCObjImage imgLine ;
- imgLine.Create (img.Width(), img.Height(), 24) ;
- MaskDrawLine (img, imgLine, m_nPenWidth, m_LineStyle) ;
- FCPixelConvertTo8BitGray aCmd ;
- imgLine.SinglePixelProcessProc (aCmd) ;
- imgMask.Create (img.Width(), img.Height(), 32) ;
- for (int y=0 ; y < img.Height() ; y++)
- for (int x=0 ; x < img.Width() ; x++)
- {
- RGBQUAD cr = m_cr ;
- PCL_A(&cr) = PCL_B(imgLine.GetBits(x,y)) * m_nAlpha / 0xFF ;
- *(RGBQUAD*)imgMask.GetBits(x,y) = cr ;
- }
- }
- int m_nAlpha ;
- RGBQUAD m_cr ;
- int m_nPenWidth ;
- LINE_STYLE m_LineStyle ;
- public:
- /// Constructor.
- FCCmdMaskLineBase (int nAlpha, RGBQUAD cr, int nPenWidth, LINE_STYLE LineStyle) : m_nAlpha(nAlpha), m_cr(cr), m_nPenWidth(nPenWidth), m_LineStyle(LineStyle) {}
- /// Draw line on imgLine.
- virtual void MaskDrawLine (const FCObjImage& img, FCObjImage& imgLine, int nPenWidth, LINE_STYLE LineStyle) =0 ;
- };
- //=============================================================================
- /**
- * Auto enlarge layer to fill up canvas.
- */
- class FCCmdAutoEnlargeLayer : public FCCmdArtPrider
- {
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_pLayer = canvas.GetCurrentLayer() ;
- if (!m_pLayer || !m_pLayer->IsValidImage())
- return ;
- // not handle when limited
- if (m_pLayer->IsLayerLimited())
- return ;
- // enlarge to full up canvas
- RECT rcLayer = {0, 0, m_pLayer->Width(), m_pLayer->Height()} ;
- m_pLayer->Layer_to_Canvas (rcLayer) ;
- SIZE sizeCanvas = canvas.GetCanvasDimension() ;
- int nExpL = (rcLayer.left <= 0) ? 0 : rcLayer.left,
- nExpT = (rcLayer.top <= 0) ? 0 : rcLayer.top,
- nExpR = (rcLayer.right < sizeCanvas.cx) ? (sizeCanvas.cx-rcLayer.right) : 0,
- nExpB = (rcLayer.bottom < sizeCanvas.cy) ? (sizeCanvas.cy-rcLayer.bottom) : 0 ;
- if (nExpL || nExpT || nExpR || nExpB)
- {
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- m_pLayer->ExpandFrame (false, nExpL, nExpT, nExpR, nExpB) ;
- }
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- if (m_pLayer && m_Undo.IsValidImage())
- {
- m_Redo = *static_cast<FCObjImage*>(m_pLayer) ;
- *static_cast<FCObjImage*>(m_pLayer) = m_Undo ;
- m_Undo.Destroy() ;
- }
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- if (m_pLayer && m_Redo.IsValidImage())
- {
- m_Undo = *static_cast<FCObjImage*>(m_pLayer) ;
- *static_cast<FCObjImage*>(m_pLayer) = m_Redo ;
- m_Redo.Destroy() ;
- }
- }
- FCObjLayer * m_pLayer ;
- FCObjImage m_Undo ;
- FCObjImage m_Redo ;
- public:
- FCCmdAutoEnlargeLayer() : m_pLayer(0) {}
- };
- //=============================================================================
- /**
- * Base class to set canvas's region.
- */
- class FCCmdSelectionSetBase : public FCCmdArtPrider
- {
- protected:
- /// Derived class put new selection into newSelect.
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect) =0 ;
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- this->OnCalculateNewSelection (canvas, m_Select) ;
- m_Select.SelectionOptimize() ;
- m_Select.RecalculateEdge (canvas.GetZoomScale(), true) ;
- this->Redo (canvas) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- this->Redo (canvas) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- FSwap (canvas.m_CurrSel, m_Select) ;
- }
- private:
- FCObjSelect m_Select ;
- };
- //=============================================================================
- /**
- * Invert current region.
- */
- class FCCmdSelectionInvert : public FCCmdSelectionSetBase
- {
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- const SIZE sizeCanvas = canvas.GetCanvasDimension() ;
- if (!canvas.HasSelected() || (sizeCanvas.cx <= 0) || (sizeCanvas.cy <= 0))
- {
- assert(false); return;
- }
- // create selection & combine with old selection
- newSelect.Create (sizeCanvas.cx, sizeCanvas.cy, 8) ;
- const POINT ptPos = canvas.GetSelection().GetGraphObjPos() ;
- newSelect.CoverBlock (canvas.GetSelection(), ptPos.x, ptPos.y) ;
- // start invert operation
- for (int y=0 ; y < newSelect.Height() ; y++)
- for (int x=0 ; x < newSelect.Width() ; x++)
- {
- BYTE * p = newSelect.GetBits (x,y) ;
- *p = ~*p ;
- }
- // position
- newSelect.SetGraphObjPos (0, 0) ;
- }
- };
- //=============================================================================
- /**
- * Select all canvas.
- */
- class FCCmdSelectionCanvasAll : public FCCmdSelectionSetBase
- {
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- const SIZE sizeCanvas = canvas.GetCanvasDimension() ;
- if ((sizeCanvas.cx <= 0) || (sizeCanvas.cy <= 0))
- {
- assert(false); return;
- }
- // create selection
- newSelect.Create (sizeCanvas.cx, sizeCanvas.cy, 8) ;
- memset (newSelect.GetMemStart(), 0xFF, newSelect.GetPitch()*newSelect.Height()) ;
- newSelect.SetGraphObjPos (0, 0) ;
- }
- };
- //=============================================================================
- /**
- * Clear selection.
- */
- class FCCmdSelectionClear : public FCCmdSelectionSetBase
- {
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- newSelect = FCObjSelect() ;
- }
- };
- //=============================================================================
- /**
- * Smooth selection.
- */
- class FCCmdSelectionSmooth : public FCCmdSelectionSetBase
- {
- public:
- /// Constructor.
- FCCmdSelectionSmooth (int nStep) : m_nStep(nStep) {}
- private:
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- newSelect = canvas.GetSelection() ;
- if (!newSelect.HasSelected())
- {
- assert(false); return;
- }
- // smooth
- newSelect.ConvertTo24Bit() ;
- FCPixelBlur_Box cmdSmooth (m_nStep, false) ;
- newSelect.SinglePixelProcessProc (cmdSmooth) ;
- FCPixelConvertTo8BitGray aCmd ;
- newSelect.SinglePixelProcessProc(aCmd) ;
- // convert to 2-state
- for (int y=0 ; y < newSelect.Height() ; y++)
- for (int x=0 ; x < newSelect.Width() ; x++)
- {
- BYTE * p = newSelect.GetBits (x,y) ;
- *p = ((*p < 128) ? 0 : 0xFF) ;
- }
- }
- private:
- int m_nStep ;
- };
- //=============================================================================
- /**
- * Base class of blend halo.
- */
- class FCCmdSelectionBlendHaloBase : public FCCmdSelectionSetBase
- {
- protected:
- /// Constructor.
- FCCmdSelectionBlendHaloBase (int nPixel) : m_nPixel(nPixel) {}
- void BlendEdgeHalo (FCObjSelect& newSelect, LOGICAL_OP logOp, int nHaloValue, bool bClear)
- {
- if (!newSelect.HasSelected() || (m_nPixel <= 0))
- {
- assert(false) ; return ;
- }
- newSelect.ExpandFrame (false, m_nPixel, m_nPixel, m_nPixel, m_nPixel) ;
- // find edge point
- std::deque<POINT> ptList ;
- GetEdgePointList (newSelect, ptList) ;
- // clear image
- if (bClear)
- memset (newSelect.GetMemStart(), 0, newSelect.GetPitch()*newSelect.Height()) ;
- // create RECT halo (round halo better ?)
- FCObjImage imgMask (2*m_nPixel+1, 2*m_nPixel+1, 8) ;
- memset (imgMask.GetMemStart(), nHaloValue, imgMask.GetPitch()*imgMask.Height()) ;
- // blend halo
- for (size_t i=0 ; i < ptList.size() ; i++)
- {
- newSelect.LogicalBlend (imgMask, logOp, ptList[i].x-m_nPixel, ptList[i].y-m_nPixel) ;
- }
- }
- private:
- // find the points of edge
- static void GetEdgePointList (const FCObjSelect& sel, std::deque<POINT>& ptList)
- {
- ptList.clear() ;
- // is edge point : current is selected around is non-selected
- // brim point must be edge point
- for (int y=0 ; y < sel.Height() ; y++)
- for (int x=0 ; x < sel.Width() ; x++)
- if (*sel.GetBits(x,y) == 0xFF)
- if ((y == 0) || (*sel.GetBits(x,y-1) == 0) || // up
- (y == sel.Height()-1) || (*sel.GetBits(x,y+1) == 0) || // down
- (x == 0) || (*sel.GetBits(x-1,y) == 0) || // left
- (x == sel.Width()-1) || (*sel.GetBits(x+1,y) == 0) || // right
- (*sel.GetBits(x+1,y-1) == 0) || // right-up
- (*sel.GetBits(x+1,y+1) == 0) || // right-down
- (*sel.GetBits(x-1,y+1) == 0) || // left-down
- (*sel.GetBits(x-1,y-1) == 0)) // left-up
- {
- POINT pt = {x,y} ;
- ptList.push_back (pt) ;
- }
- }
- private:
- int m_nPixel ;
- };
- //=============================================================================
- /**
- * Expand selection.
- */
- class FCCmdSelectionExpand : public FCCmdSelectionBlendHaloBase
- {
- public:
- /// Constructor.
- FCCmdSelectionExpand (int nPixel) : FCCmdSelectionBlendHaloBase(nPixel) {}
- private:
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- newSelect = canvas.GetSelection() ;
- BlendEdgeHalo (newSelect, LOGI_OR, 0xFF, false) ;
- }
- };
- //=============================================================================
- /**
- * Shrink selection.
- */
- class FCCmdSelectionShrink : public FCCmdSelectionBlendHaloBase
- {
- public:
- /// Constructor.
- FCCmdSelectionShrink (int nPixel) : FCCmdSelectionBlendHaloBase(nPixel) {}
- private:
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- newSelect = canvas.GetSelection() ;
- BlendEdgeHalo (newSelect, LOGI_AND, 0, false) ;
- }
- };
- //=============================================================================
- /**
- * Border selection.
- */
- class FCCmdSelectionBorder : public FCCmdSelectionBlendHaloBase
- {
- public:
- /// Constructor.
- FCCmdSelectionBorder (int nPixel) : FCCmdSelectionBlendHaloBase(nPixel) {}
- private:
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- newSelect = canvas.GetSelection() ;
- BlendEdgeHalo (newSelect, LOGI_OR, 0xFF, true) ;
- }
- };
- //=============================================================================
- /**
- * Base class to handle selection.
- */
- class FCCmdSelectionCreateBase : public FCCmdSelectionSetBase
- {
- protected:
- /// Constructor.
- FCCmdSelectionCreateBase (FCObjSelect::RGN_TYPE nType) : m_nType(nType) {}
- virtual void CreateSelection (FCObjCanvas& canvas, FCObjSelect& selCreate) =0 ;
- private:
- FCObjSelect::RGN_TYPE m_nType ;
- private:
- virtual void OnCalculateNewSelection (FCObjCanvas& canvas, FCObjSelect& newSelect)
- {
- if (!canvas.HasSelected() || (m_nType == FCObjSelect::RGN_CREATE))
- {
- // create new create
- CreateSelection (canvas, newSelect) ;
- }
- else
- {
- FCObjSelect selCreate ;
- CreateSelection (canvas, selCreate) ;
- newSelect = canvas.GetSelection() ;
- if (m_nType == FCObjSelect::RGN_ADD)
- AddSelection (newSelect, selCreate) ;
- else if (m_nType == FCObjSelect::RGN_SUB)
- SubSelection (newSelect, selCreate) ;
- }
- }
- void AddSelection (FCObjSelect& selCurr, const FCObjSelect& sel)
- {
- if (!selCurr.HasSelected() || !sel.HasSelected())
- {assert(false); return;}
- // selection's canvas position
- RECT rcSel = {0, 0, sel.Width(), sel.Height()},
- rcCurr = {0, 0, selCurr.Width(), selCurr.Height()} ;
- selCurr.Layer_to_Canvas (rcCurr) ;
- sel.Layer_to_Canvas (rcSel) ;
- // merge
- if (!::IsRectInRect (rcCurr, rcSel))
- {
- // we need create new bitmap
- RECT rcDest ;
- ::UnionRect (&rcDest, &rcSel, &rcCurr) ;
- if (IsRectEmpty(&rcDest))
- {assert(false); return;}
- FCObjImage imgOld (selCurr) ;
- selCurr.Create (RECTWIDTH(rcDest), RECTHEIGHT(rcDest), 8) ;
- selCurr.CoverBlock (imgOld, rcCurr.left-rcDest.left, rcCurr.top-rcDest.top) ; // 覆盖原图
- selCurr.SetGraphObjPos (rcDest.left, rcDest.top) ;
- rcCurr = rcDest ; // rcCurr now put rect of new selection on canvas
- }
- // cover sel
- selCurr.LogicalBlend (sel, LOGI_SEL_ADD, rcSel.left - rcCurr.left,
- rcSel.top - rcCurr.top) ;
- }
- void SubSelection (FCObjSelect& selCurr, const FCObjSelect& sel)
- {
- if ((&selCurr == &sel) || !selCurr.HasSelected() || !sel.HasSelected())
- {assert(false); return;}
- // selection's canvas position
- RECT rcSel = {0, 0, sel.Width(), sel.Height()} ,
- rcCurr = {0, 0, selCurr.Width(), selCurr.Height()} ;
- selCurr.Layer_to_Canvas (rcCurr) ;
- sel.Layer_to_Canvas (rcSel) ;
- // cover sel
- selCurr.LogicalBlend (sel, LOGI_SEL_SUB, rcSel.left - rcCurr.left,
- rcSel.top - rcCurr.top) ;
- }
- };
- //=============================================================================
- /**
- * Rectangle region.
- */
- class FCCmdSelectionCreateRect : public FCCmdSelectionCreateBase
- {
- public:
- /// Constructor.
- /// @param rcRect : rect on canvas.
- FCCmdSelectionCreateRect (RECT rcRect, FCObjSelect::RGN_TYPE nType) : m_rcRect(rcRect), FCCmdSelectionCreateBase(nType) {}
- private:
- virtual void CreateSelection (FCObjCanvas& canvas, FCObjSelect& selCreate)
- {
- // ::NormalizeRect (m_rcRect) ;
- if (::IsRectEmpty(&m_rcRect))
- return ;
- // create new rect region
- selCreate.Create (RECTWIDTH(m_rcRect), RECTHEIGHT(m_rcRect), 8) ;
- memset (selCreate.GetMemStart(), 0xFF, selCreate.GetPitch()*selCreate.Height()) ;
- selCreate.SetGraphObjPos (m_rcRect.left, m_rcRect.top) ;
- }
- private:
- RECT m_rcRect ;
- };
- //=============================================================================
- /**
- * Ellipse region.
- */
- class FCCmdSelectionCreateEllipse : public FCCmdSelectionCreateBase
- {
- public:
- /// Constructor.
- /// @param rcRect : rect on canvas.
- FCCmdSelectionCreateEllipse (RECT rcEllipse, FCObjSelect::RGN_TYPE nType) : m_rcEllipse(rcEllipse), FCCmdSelectionCreateBase(nType) {}
- private:
- virtual void CreateSelection (FCObjCanvas& canvas, FCObjSelect& selCreate)
- {
- // ::NormalizeRect (m_rcEllipse) ;
- if (::IsRectEmpty(&m_rcEllipse))
- return ;
- // create new elliptic region
- selCreate.Create (RECTWIDTH(m_rcEllipse), RECTHEIGHT(m_rcEllipse), 8) ;
- double fCenX = selCreate.Width() / 2.0,
- fCenY = selCreate.Height() / 2.0 ;
- for (int y=0 ; y < selCreate.Height() ; y++)
- for (int x=0 ; x < selCreate.Width() ; x++)
- {
- double fX = (x+0.5-fCenX) / fCenX,
- fY = (y+0.5-fCenY) / fCenY ;
- *selCreate.GetBits(x,y) = (FHypot(fX, fY) > 1.0) ? 0 : 0xFF ;
- }
- selCreate.SetGraphObjPos (m_rcEllipse.left, m_rcEllipse.top) ;
- }
- private:
- RECT m_rcEllipse ;
- };
- //=============================================================================
- /**
- * Polygon region.
- */
- class FCCmdSelectionCreatePolygonBase : public FCCmdSelectionCreateBase
- {
- public:
- /// Constructor.
- /// @param PointList : point on canvas.
- FCCmdSelectionCreatePolygonBase (std::deque<POINT> PointList, FCObjSelect::RGN_TYPE nType) : FCCmdSelectionCreateBase(nType), m_PointList(PointList) {}
- protected:
- /// @param ppt : point on img.
- virtual void ImplementDrawPolygon (FCObjImage& img, const POINT* ppt, size_t cNum) =0 ;
- private:
- RECT FindPolygonBoundRect() const
- {
- RECT rc ;
- rc.left = rc.top = 0x7FFFFFFF ;
- rc.right = rc.bottom = -0x7FFFFFFF ;
- for (size_t i=0 ; i < m_PointList.size() ; i++)
- {
- if (m_PointList[i].x < rc.left) rc.left = m_PointList[i].x ;
- if (m_PointList[i].x > rc.right) rc.right = m_PointList[i].x ;
- if (m_PointList[i].y < rc.top) rc.top = m_PointList[i].y ;
- if (m_PointList[i].y > rc.bottom) rc.bottom = m_PointList[i].y ;
- }
- return rc ;
- }
- virtual void CreateSelection (FCObjCanvas& canvas, FCObjSelect& selCreate)
- {
- PCL_array<POINT> ppt (m_PointList.size()) ;
- if (m_PointList.size())
- for (size_t i=0 ; i < m_PointList.size() ; i++)
- ppt[i] = m_PointList[i] ;
- RECT rcBound = FindPolygonBoundRect() ;
- if (::IsRectEmpty(&rcBound))
- return ;
- // create new polygon region
- FCObjImage img ;
- img.Create (RECTWIDTH(rcBound), RECTHEIGHT(rcBound), 24) ;
- // draw polygon
- for (size_t i=0 ; i < m_PointList.size() ; i++)
- {
- ppt[i].x = ppt[i].x - rcBound.left ;
- ppt[i].y = ppt[i].y - rcBound.top ;
- }
- ImplementDrawPolygon (img, ppt.get(), m_PointList.size()) ;
- selCreate.Create (img.Width(), img.Height(), 8) ;
- for (int y=0 ; y < img.Height() ; y++)
- for (int x=0 ; x < img.Width() ; x++)
- *selCreate.GetBits(x,y) = PCL_B(img.GetBits(x,y)) ;
- selCreate.SetGraphObjPos (rcBound.left, rcBound.top) ;
- }
- private:
- std::deque<POINT> m_PointList ;
- };
- //=============================================================================
- /**
- * Magic wand selection.
- */
- class FCCmdSelectionCreateMagicWand : public FCCmdSelectionCreateBase
- {
- public:
- /// Constructor.
- FCCmdSelectionCreateMagicWand (POINT ptCanvas, int nTolerance, bool bContinuous, FCObjSelect::RGN_TYPE nType) : FCCmdSelectionCreateBase(nType)
- {
- m_ptCanvas = ptCanvas ;
- m_nTolerance = nTolerance ;
- m_bContinuous = bContinuous ;
- }
- private:
- virtual void CreateSelection (FCObjCanvas& canvas, FCObjSelect& selCreate)
- {
- FCObjLayer * pLayer = canvas.GetCurrentLayer() ;
- if (!pLayer)
- {assert(false); return;}
- POINT ptLayer = m_ptCanvas ;
- pLayer->Canvas_to_Layer (ptLayer) ;
- if (!pLayer->IsInside (ptLayer.x, ptLayer.y)) // click point out of current layer
- {
- // select region that alpha==0
- const SIZE sizeCanvas = canvas.GetCanvasDimension() ;
- // create selection
- selCreate.Create (sizeCanvas.cx, sizeCanvas.cy, 8) ;
- selCreate.SetGraphObjPos (0, 0) ;
- for (int y=0 ; y < selCreate.Height() ; y++)
- for (int x=0 ; x < selCreate.Width() ; x++)
- {
- POINT ptCur = {x, y} ;
- pLayer->Canvas_to_Layer (ptCur) ;
- if (!pLayer->IsInside (ptCur.x,ptCur.y) || !PCL_A(pLayer->GetBits(ptCur.x,ptCur.y)))
- *selCreate.GetBits(x,y) = 0xFF ;
- }
- }
- else
- if (m_bContinuous)
- {
- SeedFillMask (ptLayer, m_nTolerance, *pLayer, selCreate) ;
- }
- else
- {
- selCreate.Create (pLayer->Width(), pLayer->Height(), 8) ;
- selCreate.SetGraphObjPos (pLayer->GetGraphObjPos()) ;
- const RGBQUAD crClick = *(RGBQUAD*)pLayer->GetBits (ptLayer.x, ptLayer.y) ; // color of click point
- for (int y=0 ; y < pLayer->Height() ; y++)
- for (int x=0 ; x < pLayer->Width() ; x++)
- if (IsInTolerance (pLayer->GetBits(x,y), crClick, m_nTolerance))
- *selCreate.GetBits(x,y) = 0xFF ;
- }
- }
- static bool IsInTolerance (const void* pCurr, RGBQUAD crOrigin, int nTolerance)
- {
- return (abs(PCL_B(pCurr) - PCL_B(&crOrigin)) <= nTolerance) &&
- (abs(PCL_G(pCurr) - PCL_G(&crOrigin)) <= nTolerance) &&
- (abs(PCL_R(pCurr) - PCL_R(&crOrigin)) <= nTolerance) &&
- (PCL_A(pCurr) == PCL_A(&crOrigin)) ;
- }
- static void SeedFillMask (POINT ptImg, int nTolerance, const FCObjImage& img, FCObjSelect& sel)
- {
- if (!img.IsInside (ptImg.x, ptImg.y))
- return ;
- // color of click
- const RGBQUAD crOrigin = *(RGBQUAD*)img.GetBits (ptImg.x, ptImg.y) ;
- sel.Create (img.Width(), img.Height(), 8) ; // same size
- sel.SetGraphObjPos (img.GetGraphObjPos()) ; // canvas's coordinate
- std::deque<POINT> ptUnfilled ;
- POINT ptCurr = {ptImg.x, ptImg.y} ;
- ptUnfilled.push_back (ptCurr) ;
- while (!ptUnfilled.empty())
- {
- ptCurr = ptUnfilled.back() ; ptUnfilled.pop_back() ;
- *sel.GetBits (ptCurr.x, ptCurr.y) = 0xFF ; // set filled
- // up
- if ((ptCurr.y > 0) && (*sel.GetBits (ptCurr.x, ptCurr.y-1) == 0) &&
- IsInTolerance (img.GetBits (ptCurr.x, ptCurr.y-1), crOrigin, nTolerance))
- {
- POINT pt = {ptCurr.x, ptCurr.y-1} ;
- ptUnfilled.push_back (pt) ;
- }
- // right
- if ((ptCurr.x < img.Width()-1) && (*sel.GetBits (ptCurr.x+1, ptCurr.y) == 0) &&
- IsInTolerance (img.GetBits (ptCurr.x+1, ptCurr.y), crOrigin, nTolerance))
- {
- POINT pt = {ptCurr.x+1, ptCurr.y} ;
- ptUnfilled.push_back (pt) ;
- }
- // bottom
- if ((ptCurr.y < img.Height()-1) && (*sel.GetBits (ptCurr.x, ptCurr.y+1) == 0) &&
- IsInTolerance (img.GetBits (ptCurr.x, ptCurr.y+1), crOrigin, nTolerance))
- {
- POINT pt = {ptCurr.x, ptCurr.y+1} ;
- ptUnfilled.push_back (pt) ;
- }
- // left
- if ((ptCurr.x > 0) && (*sel.GetBits (ptCurr.x-1, ptCurr.y) == 0) &&
- IsInTolerance (img.GetBits (ptCurr.x-1, ptCurr.y), crOrigin, nTolerance))
- {
- POINT pt = {ptCurr.x-1, ptCurr.y} ;
- ptUnfilled.push_back (pt) ;
- }
- }
- }
- private:
- POINT m_ptCanvas ;
- int m_nTolerance ;
- bool m_bContinuous ;
- };
- //=============================================================================
- /**
- * Handle layer.
- */
- class FCCmdLayerOperation : public FCCmdArtPrider
- {
- protected:
- /// Constructor.
- FCCmdLayerOperation (FCObjLayer* pLayer) : m_pLayer(pLayer) {}
- /// Process layer.
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress) =0 ;
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- if (!m_pLayer)
- {assert(false); return;}
- m_UndoLayer = *m_pLayer ;
- m_pUndoMemo = std::auto_ptr<FCMemoLayer>(m_pLayer->CreateMemoObj()) ;
- this->ProcessLayer (canvas, *m_pLayer, pProgress) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- if (!m_pLayer)
- {assert(false); return;}
- m_RedoLayer = *m_pLayer ;
- m_pRedoMemo = std::auto_ptr<FCMemoLayer>(m_pLayer->CreateMemoObj()) ;
- *m_pLayer = m_UndoLayer ;
- m_pLayer->SetMemoObj (m_pUndoMemo.get()) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- if (!m_pLayer)
- {assert(false); return;}
- m_UndoLayer = *m_pLayer ;
- m_pUndoMemo = std::auto_ptr<FCMemoLayer>(m_pLayer->CreateMemoObj()) ;
- *m_pLayer = m_RedoLayer ;
- m_pLayer->SetMemoObj (m_pRedoMemo.get()) ;
- }
- private:
- FCObjLayer * m_pLayer ;
- FCObjLayer m_UndoLayer, m_RedoLayer ;
- std::auto_ptr<FCMemoLayer> m_pUndoMemo, m_pRedoMemo ;
- };
- //=============================================================================
- /**
- * Stretch layer.
- */
- class FCCmdLayerStretch : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- FCCmdLayerStretch (FCObjLayer* pLayer, int nNewW, int nNewH, INTERPOLATION_TYPE InterplType) : FCCmdLayerOperation(pLayer)
- {
- m_nNewWidth = nNewW ;
- m_nNewHeight = nNewH ;
- m_InterplType = InterplType ;
- }
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- // don't change layer's position
- const POINT ptLayer = rLayer.GetGraphObjPos() ;
- switch (m_InterplType)
- {
- case INTERPOLATION_NONE : rLayer.Stretch (m_nNewWidth, m_nNewHeight) ; break ;
- case INTERPOLATION_BILINEAR : rLayer.Stretch_Smooth (m_nNewWidth, m_nNewHeight, pProgress) ; break ;
- default : assert(false) ;
- }
- rLayer.SetGraphObjPos (ptLayer) ;
- }
- private:
- int m_nNewWidth ;
- int m_nNewHeight ;
- INTERPOLATION_TYPE m_InterplType ;
- };
- //=============================================================================
- /**
- * Rotate layer.
- */
- class FCCmdLayerRotate : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- /// @param nAngle : 0 -- 360
- FCCmdLayerRotate (FCObjLayer* pLayer, int nAngle) : FCCmdLayerOperation(pLayer)
- {
- m_nAngle = nAngle ;
- }
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- // the central point is fixed in rotate
- POINT ptCenter = rLayer.GetGraphObjPos() ;
- ptCenter.x += rLayer.Width()/2 ; ptCenter.y += rLayer.Height()/2 ;
- // sawtooth :-(
- FCPixelRotate aCmd(m_nAngle) ;
- rLayer.SinglePixelProcessProc (aCmd, pProgress) ;
- // calculate the position of rotated layer
- ptCenter.x -= rLayer.Width()/2 ; ptCenter.y -= rLayer.Height()/2 ;
- rLayer.SetGraphObjPos (ptCenter) ;
- }
- private:
- int m_nAngle ;
- };
- //=============================================================================
- /**
- * Clockwise rotate 90'.
- */
- class FCCmdLayerRotate90 : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- FCCmdLayerRotate90 (FCObjLayer* pLayer) : FCCmdLayerOperation(pLayer) {}
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- // the central point is fixed in rotate
- POINT ptCenter = rLayer.GetGraphObjPos() ;
- ptCenter.x += rLayer.Width()/2 ; ptCenter.y += rLayer.Height()/2 ;
- FCPixelRotate90 cmdRotateImg ;
- rLayer.SinglePixelProcessProc (cmdRotateImg, pProgress) ;
- // calculate the position of rotated layer
- ptCenter.x -= rLayer.Width()/2 ; ptCenter.y -= rLayer.Height()/2 ;
- rLayer.SetGraphObjPos (ptCenter) ;
- }
- };
- //=============================================================================
- /**
- * Clockwise rotate 270'.
- */
- class FCCmdLayerRotate270 : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- FCCmdLayerRotate270 (FCObjLayer* pLayer) : FCCmdLayerOperation(pLayer) {}
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- // the central point is fixed in rotate
- POINT ptCenter = rLayer.GetGraphObjPos() ;
- ptCenter.x += rLayer.Width()/2 ; ptCenter.y += rLayer.Height()/2 ;
- FCPixelRotate270 cmdRotateImg ;
- rLayer.SinglePixelProcessProc (cmdRotateImg, pProgress) ;
- // calculate the position of rotated layer
- ptCenter.x -= rLayer.Width()/2 ; ptCenter.y -= rLayer.Height()/2 ;
- rLayer.SetGraphObjPos (ptCenter) ;
- }
- };
- //=============================================================================
- /**
- * Skew transform.
- */
- class FCCmdLayerSkew : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- /// @param ptPos : new position of left-up, right-up, right-down, left-down point.
- FCCmdLayerSkew (FCObjLayer* pLayer, const POINT ptPos[4]) : FCCmdLayerOperation(pLayer)
- {
- memcpy (m_ptNewPos, ptPos, sizeof(POINT) * 4) ;
- }
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- FCPixelSkew aCmd (m_ptNewPos) ;
- rLayer.SinglePixelProcessProc (aCmd, pProgress) ;
- }
- private:
- POINT m_ptNewPos[4] ; // left-up, right-up, right-down, left-down
- };
- //=============================================================================
- /**
- * Lens transform.
- */
- class FCCmdLayerLens : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- /// @param ptPos : new position of left-up, right-up, right-down, left-down point.
- FCCmdLayerLens (FCObjLayer* pLayer, const POINT ptPos[4]) : FCCmdLayerOperation(pLayer)
- {
- memcpy (m_ptNewPos, ptPos, sizeof(POINT) * 4) ;
- }
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- FCPixelPerspective aCmd (m_ptNewPos) ;
- rLayer.SinglePixelProcessProc (aCmd, pProgress) ;
- }
- private:
- POINT m_ptNewPos[4] ; // left-up, right-up, right-down, left-down
- };
- //=============================================================================
- /**
- * Crop layer.
- */
- class FCCmdLayerCrop : public FCCmdLayerOperation
- {
- public:
- /// Constructor.
- FCCmdLayerCrop (FCObjLayer* pLayer, FCObjImage* pImgMask, RECT rcLayer, int nPercent) : FCCmdLayerOperation(pLayer), m_pImgMask(pImgMask)
- {
- m_rcLayer = rcLayer ;
- m_nPercent = nPercent ;
- }
- private:
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- if (!m_pImgMask.get() || (m_pImgMask->ColorBits() != 24))
- {assert(false); return;}
- const POINT ptOldImg = rLayer.GetGraphObjPos() ;
- // get selected region
- FCObjImage imgBlock ;
- rLayer.GetSubBlock (&imgBlock, m_rcLayer) ;
- if (!rLayer.IsValidImage())
- {assert(false); return;}
- m_pImgMask->Stretch_Smooth (imgBlock.Width(), imgBlock.Height()) ;
- // process
- for (int y=0 ; y < imgBlock.Height() ; y++)
- for (int x=0 ; x < imgBlock.Width() ; x++)
- {
- int nGray = 0xFF - FCColor::GetGrayscale (m_pImgMask->GetBits(x,y)) ;
- BYTE * p = imgBlock.GetBits(x,y) ;
- PCL_A(p) = PCL_A(p) * nGray * (100-m_nPercent) / 0xFF / 100 ;
- }
- static_cast<FCObjImage&>(rLayer) = imgBlock ;
- rLayer.SetGraphObjPos (ptOldImg.x + m_rcLayer.left, ptOldImg.y + m_rcLayer.top) ;
- }
- private:
- std::auto_ptr<FCObjImage> m_pImgMask ; // 24-bit mask image
- RECT m_rcLayer ; // RECT on layer
- int m_nPercent ;
- };
- //=============================================================================
- /**
- * Move graph object.
- */
- class FCCmdLayerMove : public FCCmdArtPrider
- {
- public:
- /// Constructor.
- FCCmdLayerMove (FCObjGraph* pGraph, POINT NewPoint) : m_pGraph(pGraph), m_ptOld(NewPoint) {}
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- this->Redo(canvas) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- this->Redo(canvas) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- if (!m_pGraph)
- {assert(false); return;}
- const POINT pt = m_pGraph->GetGraphObjPos() ;
- m_pGraph->SetGraphObjPos (m_ptOld) ;
- m_ptOld = pt ;
- }
- private:
- POINT m_ptOld ;
- FCObjGraph * m_pGraph ;
- };
- //=============================================================================
- /**
- * Insert a new layer into canvas.
- */
- class FCCmdLayerAdd : public FCCmdArtPrider
- {
- public:
- /**
- * Insert a new layer into canvas (<B>after be added, you can't delete the layer any more</B>).
- * @param nPos : the pAddLayer's 0-base index in canvas.
- */
- FCCmdLayerAdd (FCObjLayer* pAddLayer, int nPos)
- {
- m_pAddLayer = pAddLayer ; assert(pAddLayer);
- m_nPos = nPos ;
- m_pCanvas = 0 ;
- // why we need this flag : think about this scene
- // 1)undo level set(2) 2)add a layer 3)merge layer include it 4)add a layer 5)undo
- // the step 2, first layer will be removed, but the step 3 hold its pointer
- m_bRemoved = false ;
- }
- virtual ~FCCmdLayerAdd()
- {
- // 其实图层remove时就该被删除,只是为了节省内存,才暂时放到remove列表中
- if (m_bRemoved)
- m_pCanvas->DeleteLayerFromRemoveList (m_pAddLayer) ;
- }
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_pCanvas = &canvas ;
- this->Redo(canvas) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- m_bRemoved = true ;
- canvas.RemoveLayer (m_pAddLayer) ; // not delete
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- m_bRemoved = false ;
- canvas.AddLayer (m_pAddLayer, m_nPos) ;
- }
- private:
- int m_nPos ;
- FCObjLayer * m_pAddLayer ;
- FCObjCanvas * m_pCanvas ;
- bool m_bRemoved ;
- };
- //=============================================================================
- /**
- * Remove a layer from canvas.
- */
- class FCCmdLayerRemove : public FCCmdArtPrider
- {
- public:
- /// Remove pRemoveLayer from canvas.
- FCCmdLayerRemove (FCObjLayer* pRemoveLayer)
- {
- m_pRemoveLayer = pRemoveLayer; assert(pRemoveLayer);
- m_pCanvas = 0 ;
- m_bRemoved = true ;
- }
- virtual ~FCCmdLayerRemove()
- {
- // 其实图层remove时就该被删除,只是为了节省内存,才暂时放到remove列表中
- if (m_bRemoved)
- m_pCanvas->DeleteLayerFromRemoveList (m_pRemoveLayer) ;
- }
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_pCanvas = &canvas ;
- this->Redo(canvas) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- m_bRemoved = false ;
- canvas.AddLayer (m_pRemoveLayer, m_nPos) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- m_bRemoved = true ;
- m_nPos = canvas.FindLayer(m_pRemoveLayer) ;
- canvas.RemoveLayer (m_pRemoveLayer) ; // not delete
- }
- private:
- int m_nPos ;
- FCObjLayer * m_pRemoveLayer ;
- FCObjCanvas * m_pCanvas ;
- bool m_bRemoved ;
- };
- //=============================================================================
- /**
- * Save layer's current property.
- */
- class FCCmdLayerSaveProperty : public FCCmdArtPrider
- {
- public:
- /// Constructor (save layer's current property when constructor).
- FCCmdLayerSaveProperty (FCObjLayer* pLayer)
- {
- m_pLayer = pLayer ;
- m_pMemo = m_pLayer ? m_pLayer->CreateMemoObj() : 0 ;
- }
- virtual ~FCCmdLayerSaveProperty() {if(m_pMemo) delete m_pMemo;}
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress) {}
- virtual void Undo (FCObjCanvas& canvas)
- {
- this->Redo(canvas) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- if (m_pLayer && m_pMemo)
- {
- FCMemoLayer * pCurr = m_pLayer->CreateMemoObj() ;
- m_pLayer->SetMemoObj (m_pMemo) ;
- delete m_pMemo ;
- m_pMemo = pCurr ;
- }
- else
- {assert(false);}
- }
- private:
- FCMemoLayer * m_pMemo ;
- FCObjLayer * m_pLayer ;
- };
- //=============================================================================
- /**
- * Change layer's sequence in canvas.
- */
- class FCCmdLayerExchange : public FCCmdArtPrider
- {
- public:
- FCCmdLayerExchange (std::deque<FCObjLayer*> NewList) : m_LayerList(NewList) {}
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- this->Redo(canvas) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- this->Redo(canvas) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- FSwap (canvas.m_LayerList, m_LayerList) ;
- }
- private:
- std::deque<FCObjLayer*> m_LayerList ;
- };
- //=============================================================================
- /**
- * Merge layers.
- */
- class FCCmdLayerMerge : public FCCmdComposite
- {
- public:
- /// Constructor.
- /// @param IndexList : list of layer's index.
- FCCmdLayerMerge (std::deque<int> IndexList)
- {
- if (IndexList.empty())
- {assert(false); return;}
- PCL_array<int> arr(IndexList.size()) ;
- for (size_t i=0 ; i < IndexList.size() ; i++)
- arr[i] = IndexList[i] ;
- // sort by small to big, delete layer from big
- FCOXOHelper::BubbleSort (arr.get(), IndexList.size()) ;
- for (size_t j=0 ; j < IndexList.size() ; j++)
- m_IndexList.push_back (arr[j]) ;
- }
- private:
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- if (m_IndexList.empty())
- {assert(false); return;}
- // calculate merged layer size
- RECT rcNewLayer = {0,0,0,0} ;
- int i ;
- for (i=0 ; i < (int)m_IndexList.size() ; i++)
- {
- FCObjLayer * pLayer = canvas.GetLayer(m_IndexList[i]) ; assert(pLayer);
- if (!pLayer)
- continue ;
- // layer's RECT
- RECT rcLayer = {0, 0, pLayer->Width(), pLayer->Height()} ;
- POINT pt = pLayer->GetGraphObjPos() ;
- OffsetRect (&rcLayer, pt.x, pt.y) ;
- if (i == 0)
- rcNewLayer = rcLayer ;
- else
- UnionRect (&rcNewLayer, &rcNewLayer, &rcLayer) ;
- }
- // make new merged layer
- FCObjLayer * pNewLayer = new FCObjLayer ;
- if (!pNewLayer->Create (RECTWIDTH(rcNewLayer), RECTHEIGHT(rcNewLayer), 32))
- {
- delete pNewLayer ;
- assert(false); return;
- }
- // merge layers (from bottom to top)
- for (i=0 ; i < (int)m_IndexList.size() ; i++)
- {
- FCObjLayer * pLayer = canvas.GetLayer(m_IndexList[i]) ; assert(pLayer);
- if (!pLayer)
- continue ;
- // position at new layer
- pNewLayer->CombineImage (*pLayer,
- pLayer->GetGraphObjPos().x - rcNewLayer.left,
- pLayer->GetGraphObjPos().y - rcNewLayer.top,
- pLayer->GetLayerTransparent()) ;
- if (pProgress)
- pProgress->SetProgress (100 * (i + 1) / m_IndexList.size()) ;
- }
- // set new merged layer's position
- pNewLayer->SetGraphObjPos (rcNewLayer.left, rcNewLayer.top) ;
- // insert new layer at min index
- PushImgCommand (new FCCmdLayerAdd (pNewLayer, m_IndexList[0])) ;
- // delete layers
- for (i = m_IndexList.size()-1 ; i >=0 ; i--)
- {
- FCObjLayer * pLayer = canvas.GetLayer(m_IndexList[i]) ; assert(pLayer);
- if (pLayer)
- PushImgCommand (new FCCmdLayerRemove (pLayer)) ;
- }
- FCCmdComposite::Execute (canvas, pProgress) ;
- }
- std::deque<int> m_IndexList ;
- };
- //=============================================================================
- /**
- * Delete layers from canvas
- */
- class FCCmdLayerListRemove : public FCCmdComposite
- {
- public:
- /// Constructor.
- /// @param IndexList : list of layer's index.
- FCCmdLayerListRemove (const FCObjCanvas& canvas, std::deque<int> IndexList)
- {
- if (IndexList.empty())
- {assert(false); return;}
- PCL_array<int> arr (IndexList.size()) ;
- for (size_t i=0 ; i < IndexList.size() ; i++)
- arr[i] = IndexList[i] ;
- // sort by small to big, delete layer from big to small
- FCOXOHelper::BubbleSort (arr.get(), IndexList.size()) ;
- for (int j=IndexList.size()-1 ; j >= 0 ; j--)
- PushImgCommand (new FCCmdLayerRemove(canvas.GetLayer(arr[j]))) ;
- }
- };
- //=============================================================================
- /**
- * Handle canvas.
- * <B>derived class must initialize member m_NewCanvasSize at constructor</B>
- */
- class FCCmdCanvasOperation : public FCCmdComposite
- {
- public:
- FCCmdCanvasOperation()
- {
- m_OldCanvasSize.cx = m_OldCanvasSize.cy = -1 ;
- m_NewCanvasSize.cx = m_NewCanvasSize.cy = -1 ;
- }
- virtual void Execute (FCObjCanvas& canvas, FCObjProgress* pProgress)
- {
- m_OldCanvasSize = canvas.GetCanvasDimension() ;
- FCCmdComposite::Execute (canvas, pProgress) ;
- canvas.SetCanvasDimension (m_NewCanvasSize) ;
- }
- virtual void Undo (FCObjCanvas& canvas)
- {
- FCCmdComposite::Undo(canvas) ;
- canvas.SetCanvasDimension (m_OldCanvasSize) ;
- }
- virtual void Redo (FCObjCanvas& canvas)
- {
- FCCmdComposite::Redo(canvas) ;
- canvas.SetCanvasDimension (m_NewCanvasSize) ;
- }
- private:
- SIZE m_OldCanvasSize ;
- protected:
- SIZE m_NewCanvasSize ;
- };
- //=============================================================================
- /**
- * Resize canvas.
- */
- class FCCmdCanvasResize : public FCCmdCanvasOperation
- {
- public:
- /// Constructor.
- /// @param nLeft,nTop,nRight,nBottom : canvas's delta.
- FCCmdCanvasResize (const FCObjCanvas& rCanvas, int nLeft, int nTop, int nRight, int nBottom)
- {
- const SIZE OldSize = rCanvas.GetCanvasDimension() ;
- m_NewCanvasSize.cx = OldSize.cx + nLeft + nRight ;
- m_NewCanvasSize.cy = OldSize.cy + nTop + nBottom ;
- if ((m_NewCanvasSize.cx < 1) || (m_NewCanvasSize.cy < 1))
- {
- m_NewCanvasSize = OldSize ;
- assert(false) ; return ;
- }
- // update position of all layers
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
- POINT ptNew = pLayer->GetGraphObjPos() ;
- ptNew.x += nLeft ; ptNew.y += nTop ;
- PushImgCommand (new FCCmdLayerMove (pLayer, ptNew)) ;
- }
- // clear selection
- PushImgCommand (new FCCmdSelectionClear()) ;
- }
- };
- //=============================================================================
- /**
- * Canvas rotate 90'
- */
- class FCCmdCanvasRotate90 : public FCCmdCanvasOperation
- {
- public:
- /// Constructor.
- FCCmdCanvasRotate90 (const FCObjCanvas& rCanvas)
- {
- const SIZE OldSize = rCanvas.GetCanvasDimension() ;
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
- PushImgCommand (new FCCmdLayerRotate90 (pLayer)) ;
- // calculate new position
- POINT ptOld = pLayer->GetGraphObjPos(),
- ptLB = {ptOld.x, ptOld.y + pLayer->Height()} ;
- ptOld.x = OldSize.cy - ptLB.y ;
- ptOld.y = ptLB.x ;
- PushImgCommand (new FCCmdLayerMove (pLayer, ptOld)) ;
- }
- PushImgCommand (new FCCmdSelectionClear()) ;
- // new canvas size
- m_NewCanvasSize.cx = OldSize.cy ; m_NewCanvasSize.cy = OldSize.cx ;
- }
- };
- //=============================================================================
- /**
- * Canvas rotate 270'
- */
- class FCCmdCanvasRotate270 : public FCCmdCanvasOperation
- {
- public:
- /// Constructor.
- FCCmdCanvasRotate270 (const FCObjCanvas& rCanvas)
- {
- const SIZE OldSize = rCanvas.GetCanvasDimension() ;
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
- PushImgCommand (new FCCmdLayerRotate270 (pLayer)) ;
- // calculate new position
- POINT ptOld = pLayer->GetGraphObjPos(),
- ptRT = {ptOld.x + pLayer->Width(), ptOld.y} ;
- ptOld.x = ptRT.y ;
- ptOld.y = OldSize.cx - ptRT.x ;
- PushImgCommand (new FCCmdLayerMove (pLayer, ptOld)) ;
- }
- PushImgCommand (new FCCmdSelectionClear()) ;
- // new canvas size
- m_NewCanvasSize.cx = OldSize.cy ; m_NewCanvasSize.cy = OldSize.cx ;
- }
- };
- //=============================================================================
- /**
- * Rotate canvas.
- */
- class FCCmdCanvasRotate : public FCCmdCanvasOperation
- {
- public:
- /// Constructor.
- /// @param nAngle : 0 -- 360
- FCCmdCanvasRotate (const FCObjCanvas& rCanvas, int nAngle)
- {
- nAngle = FClamp (nAngle, 0, 360) ;
- // 计算画布新尺寸
- const SIZE OldSize = rCanvas.GetCanvasDimension() ;
- const int nTmpAng = FMax (0, nAngle % 180) ;
- const double fSin = sin(AngleToRadian(nTmpAng % 90)),
- fCos = cos(AngleToRadian(nTmpAng % 90)) ;
- // 注意这里的宽高计算
- if (nTmpAng >= 90)
- {
- m_NewCanvasSize.cx = FRound (OldSize.cx * fSin + OldSize.cy * fCos) ;
- m_NewCanvasSize.cy = FRound (OldSize.cy * fSin + OldSize.cx * fCos) ;
- }
- else
- {
- m_NewCanvasSize.cx = FRound (OldSize.cx * fCos + OldSize.cy * fSin) ;
- m_NewCanvasSize.cy = FRound (OldSize.cy * fCos + OldSize.cx * fSin) ;
- }
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
-
- // 计算新位置
- // 这里特殊点,先移动,后旋转,因为旋转时会绕中心点旋转
- POINT ptNew = pLayer->GetGraphObjPos() ;
- ptNew.x += (m_NewCanvasSize.cx-OldSize.cx)/2 ;
- ptNew.y += (m_NewCanvasSize.cy-OldSize.cy)/2 ;
- PushImgCommand (new FCCmdLayerMove (pLayer, ptNew)) ;
-
- PushImgCommand (new FCCmdLayerRotate (pLayer, nAngle)) ;
- }
- PushImgCommand (new FCCmdSelectionClear()) ;
- }
- };
- //=============================================================================
- /**
- * Stretch canvas.
- */
- class FCCmdCanvasStretch : public FCCmdCanvasOperation
- {
- public:
- FCCmdCanvasStretch (const FCObjCanvas& rCanvas, int nNewW, int nNewH, INTERPOLATION_TYPE InterplType)
- {
- const SIZE OldSize = rCanvas.GetCanvasDimension() ;
- if ((nNewW <= 0) || (nNewH <= 0) || (OldSize.cx <= 0) || (OldSize.cy <= 0))
- {
- m_NewCanvasSize = OldSize ;
- assert(false) ; return ;
- }
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
- PushImgCommand (new FCCmdLayerStretch (pLayer,
- pLayer->Width() * nNewW / OldSize.cx,
- pLayer->Height() * nNewH / OldSize.cy,
- InterplType)) ;
- // calculate new position
- POINT ptOld = pLayer->GetGraphObjPos() ;
- ptOld.x = ptOld.x * nNewW / OldSize.cx ;
- ptOld.y = ptOld.y * nNewH / OldSize.cy ;
- PushImgCommand (new FCCmdLayerMove (pLayer, ptOld)) ;
- }
- PushImgCommand (new FCCmdSelectionClear()) ;
- m_NewCanvasSize.cx = nNewW ; m_NewCanvasSize.cy = nNewH ;
- }
- };
- //=============================================================================
- /**
- * Crop canvas.
- */
- class FCCmdCanvasCrop : public FCCmdCanvasOperation
- {
- public:
- /// Constructor.
- FCCmdCanvasCrop (const FCObjCanvas& rCanvas, RECT rcCanvas)
- {
- RECT rcSel = rcCanvas ;
- rCanvas.BoundRect (rcSel) ;
- if (IsRectEmpty(&rcSel))
- {
- m_NewCanvasSize = rCanvas.GetCanvasDimension() ;
- return ;
- }
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- // crop all layers
- PushImgCommand (new FCCmdCanvasCrop_Layer (rCanvas.GetLayer(i), rcSel)) ;
- }
- // clear selection
- PushImgCommand (new FCCmdSelectionClear()) ;
- m_NewCanvasSize.cx = RECTWIDTH(rcSel) ;
- m_NewCanvasSize.cy = RECTHEIGHT(rcSel) ;
- }
- private:
- // 裁剪单层逻辑
- class FCCmdCanvasCrop_Layer : public FCCmdLayerOperation
- {
- public:
- FCCmdCanvasCrop_Layer (FCObjLayer* pLayer, RECT rcCanvas) : FCCmdLayerOperation(pLayer), m_rcCanvas(rcCanvas) {}
- virtual void ProcessLayer (FCObjCanvas& canvas, FCObjLayer& rLayer, FCObjProgress* pProgress)
- {
- // calculate RECT in layer
- RECT rcLayer = m_rcCanvas ;
- rLayer.Canvas_to_Layer (rcLayer) ;
- rLayer.BoundRect (rcLayer) ;
- if (IsRectEmpty (&rcLayer))
- {
- // create transparency layer
- rLayer.Create (RECTWIDTH(m_rcCanvas), RECTHEIGHT(m_rcCanvas), 32) ;
- FCPixelFillColor cmdFillCr (FCColor::crWhite(), 0) ;
- rLayer.SinglePixelProcessProc (cmdFillCr, pProgress) ;
- rLayer.SetGraphObjPos (0, 0) ;
- }
- else
- {
- FCObjImage imgCrop ;
- canvas.MakeRegion (rLayer, imgCrop) ;
- // calc new layer's position, notice sequence !!!!!!
- rLayer.Layer_to_Canvas (rcLayer) ;
- (FCObjImage&)rLayer = imgCrop ;
- rLayer.SetGraphObjPos (rcLayer.left-m_rcCanvas.left, rcLayer.top-m_rcCanvas.top) ;
- }
- }
- private:
- RECT m_rcCanvas ; // rect of canvas
- };
- };
- //============================================================================
- // 自动裁减画布/auto crop canvas,裁掉canvas边上透明的区域
- class FCCmdCanvasAutoCrop : public FCCmdCanvasOperation
- {
- public:
- FCCmdCanvasAutoCrop (const FCObjCanvas& rCanvas)
- {
- const SIZE sizeOld = rCanvas.GetCanvasDimension() ;
- m_NewCanvasSize = sizeOld ; // must set size before return
- RECT rcBound = {0,0,0,0} ;
- for (int i=0 ; i < rCanvas.GetLayerNumber() ; i++)
- {
- FCObjLayer * pLayer = rCanvas.GetLayer(i) ;
- FCPixelGetOptimizedRect aCmd ;
- pLayer->SinglePixelProcessProc (aCmd) ;
- pLayer->Layer_to_Canvas (aCmd.m_rcOptimized) ;
- if (i == 0)
- rcBound = aCmd.m_rcOptimized ;
- else
- ::UnionRect (&rcBound, &rcBound, &aCmd.m_rcOptimized) ;
- }
- if (IsRectEmpty (&rcBound))
- return ;
- rCanvas.BoundRect (rcBound) ;
- if (IsRectEmpty(&rcBound))
- return ;
- int nRight = rcBound.right - sizeOld.cx,
- nBottom = rcBound.bottom - sizeOld.cy ;
- PushImgCommand (new FCCmdCanvasResize(rCanvas, -rcBound.left, -rcBound.top, nRight, nBottom)) ;
- m_NewCanvasSize.cx = sizeOld.cx - rcBound.left + nRight ;
- m_NewCanvasSize.cy = sizeOld.cy - rcBound.top + nBottom ;
- }
- };
- #endif
|