home *** CD-ROM | disk | FTP | other *** search
/ Megahits 4 / MegaHits_Vol.4.iso / mui / dev / gui / myimagegclass / source / myimagegclass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-24  |  11.6 KB  |  335 lines

  1. // -----------------------------------------------------------------------------
  2. // myimagegclass.c
  3. // BOOPSI subclass of gadgetclass that can send its ID whenever it renders.
  4. // Refreshes, centers, & scales its GA_Image attribute as well.
  5. // 05 Jan 1994
  6. // $Id: myimagegclass.c,v 1.39 94/01/11 02:59:42 rick Exp Locker: rick $
  7. // -----------------------------------------------------------------------------
  8. // No new methods
  9. //
  10. // Changed attributes
  11. // GA_Image       [ISG] Changing this refreshes the gadget imagery.  Also gettable.
  12. // GA_ID          [IS]  Nonzero will report a refresh using value.
  13. //
  14. // New attributes
  15. // GA_ScaleFlags     [ISG] Various image scaling options.
  16. // GA_ScaleRelWidth  [ISG] Width for relative scaling.
  17. // GA_ScaleRelHeight [ISG] Height for relative scaling.
  18. // GA_MUIRemember    [ISG] Remember packet for MUI destroy/remake actions on same object.
  19. // -----------------------------------------------------------------------------
  20.  
  21. #include <exec/types.h>
  22. #include <exec/memory.h>
  23. #include <intuition/intuition.h>
  24. #include <intuition/cghooks.h>
  25. #include <intuition/classes.h>
  26. #include <intuition/classusr.h>
  27. #include <intuition/gadgetclass.h>
  28. #include <graphics/scale.h>
  29. #include <proto/exec.h>
  30. #include <proto/intuition.h>
  31. #include <proto/gadtools.h>
  32. #include <proto/graphics.h>
  33. #include <proto/utility.h>
  34. #include "myimagegclass.h"
  35.  
  36. #define G(o)   ((struct Gadget *)o)
  37. #define I(o)   ((struct Image *)o)
  38. #define MIN(a, b)    ((a)<=(b)?(a):(b))
  39.  
  40. typedef struct
  41. {
  42.    SHORT relWidth, relHeight;
  43. } MyData;
  44.  
  45. typedef struct
  46. {
  47.    struct Image *image;    // normally stored in GadgetRender
  48.    ULONG flags;            // stored in UserData
  49.    UWORD id;               // stored in GadgetID
  50.    SHORT relWidth, relHeight;
  51. } RememberData;
  52.  
  53. static void __interrupt NotifyGadID(Class *cl, Object *o, struct gpRender *gpr)
  54. {
  55.    struct TagItem tt[2];
  56.  
  57.    tt[0].ti_Tag = GA_ID;
  58.    tt[0].ti_Data = G(o)->GadgetID;
  59.  
  60.    tt[1].ti_Tag = TAG_DONE;
  61.  
  62.    DoSuperMethod(cl, o, OM_NOTIFY, tt, gpr->gpr_GInfo, 0);
  63. }
  64.  
  65. static void __interrupt Render(Class *cl, Object *o, struct gpRender *gpr, MyData *myd)
  66. {
  67.    struct Gadget *g;
  68.    struct Image *img;
  69.  
  70.    g = G(o);  img = I(g->GadgetRender);
  71.  
  72.    if (g->GadgetID)
  73.       NotifyGadID(cl, o, gpr);  // this is what the gadget solely exists for
  74.  
  75.    if (gpr->gpr_RPort)
  76.    {
  77.       EraseRect(gpr->gpr_RPort, g->LeftEdge,g->TopEdge,g->LeftEdge+g->Width-1,g->TopEdge+g->Height-1);
  78.       if (img)
  79.          if ((ULONG)g->UserData & (~GAFL_AspectRatio))   // Lone aspect ratio flag draws normally
  80.          {  // scale image according to flags
  81.             struct BitMap sBM, dBM;
  82.             ULONG rassizeS, rassizeD;
  83.             USHORT sWidth,sHeight, dWidth,dHeight, sx,sy;
  84.  
  85.             InitBitMap(&sBM, img->Depth, img->Width,img->Height);
  86.             rassizeS = RASSIZE(img->Width,img->Height);
  87.  
  88.             dWidth = ((ULONG)g->UserData & GAFL_ScaleX) ? g->Width:img->Width;
  89.             dHeight = ((ULONG)g->UserData & GAFL_ScaleY) ? g->Height:img->Height;
  90.  
  91.             if (myd->relWidth && ((ULONG)g->UserData & GAFL_RelX))
  92.                dWidth = img->Width*dWidth/myd->relWidth;
  93.             if (myd->relHeight && ((ULONG)g->UserData & GAFL_RelY))
  94.                dHeight = img->Height*dHeight/myd->relHeight;
  95.  
  96.             if (((ULONG)g->UserData & GAFL_AspectRatio) && img->Width && img->Height)
  97.             {  // fit shape into its native pixel aspect ratio
  98.                BOOL smallAspect;
  99.                USHORT adjW, adjH;
  100.  
  101.                smallAspect = ((((ULONG)g->UserData & GAFL_ScaleXY) == GAFL_ScaleXY)||(((ULONG)g->UserData & GAFL_RelXY) == GAFL_RelXY));
  102.  
  103.                adjW = ((ULONG)g->UserData & (GAFL_ScaleY|GAFL_RelY)) ? ScalerDiv(img->Width,dHeight,img->Height):0;
  104.                adjH = ((ULONG)g->UserData & (GAFL_ScaleX|GAFL_RelX)) ? ScalerDiv(img->Height,dWidth,img->Width):0;
  105.  
  106.                // choose aspect that fits if x&y are scaled, otherwise choose largest aspect
  107.                if (smallAspect?(adjW*dHeight < adjH*dWidth):(adjW*dHeight > adjH*dWidth))
  108.                   dWidth = adjW;
  109.                else
  110.                   dHeight = adjH;
  111.             }
  112.  
  113.             if (dHeight > g->Height)
  114.             {  // Clip height here 'cause BitMapScale() works fine w/height
  115.                sHeight = ScalerDiv(img->Height,g->Height,dHeight);
  116.                dHeight = g->Height;
  117.                sy = img->Height/2-sHeight/2;
  118.             }
  119.             else
  120.             {
  121.                sy = 0;  sHeight = img->Height;
  122.             }
  123.             if (dWidth > g->Width)
  124.             {  // BitMapScale() doesn't work at all w/SrcX's not on word boundaries!
  125.                // So I clip width to word boundaries so it doesn't have to scale more
  126.                // than will fit in the display space, conserving memory.
  127.                sWidth = ScalerDiv(img->Width,g->Width,dWidth);
  128.                sx = (img->Width/2-sWidth/2)/16*16;
  129.                sWidth = (img->Width/2-sx)*2;
  130.                dWidth = ScalerDiv(dWidth, sWidth, img->Width);
  131.             }
  132.             else
  133.             {
  134.                sx = 0;  sWidth = img->Width;
  135.             }
  136.  
  137.             rassizeD = RASSIZE(dWidth,dHeight);
  138.             InitBitMap(&dBM, img->Depth, dWidth,dHeight);
  139.  
  140.             sBM.Planes[0] = (PLANEPTR)img->ImageData;
  141.             if (dBM.Planes[0] = (PLANEPTR)AllocVec(rassizeD*img->Depth,MEMF_CHIP|MEMF_CLEAR))
  142.             {
  143.                struct BitScaleArgs bsa;
  144.                register short i;
  145.  
  146.                for (i = 0; i < img->Depth; i++)
  147.                {
  148.                   sBM.Planes[i] = sBM.Planes[0] + rassizeS*i;
  149.                   dBM.Planes[i] = dBM.Planes[0] + rassizeD*i;
  150.                }
  151.  
  152.                bsa.bsa_SrcBitMap = &sBM;  bsa.bsa_DestBitMap = &dBM;
  153.                bsa.bsa_SrcX = sx;  bsa.bsa_SrcY = sy;
  154.                bsa.bsa_DestX = bsa.bsa_DestY = bsa.bsa_Flags = 0;
  155.                bsa.bsa_XSrcFactor = bsa.bsa_SrcWidth = sWidth;
  156.                bsa.bsa_YSrcFactor = bsa.bsa_SrcHeight = sHeight;
  157.                bsa.bsa_XDestFactor = dWidth;
  158.                bsa.bsa_YDestFactor = dHeight;
  159.  
  160.                BitMapScale(&bsa);   // scale it!
  161.  
  162.                // Clip width here 'cause BitMapScale() only works on word SrcX's!
  163.                if (dWidth > g->Width)
  164.                   BltBitMapRastPort(&dBM, dWidth/2-g->Width/2,0, gpr->gpr_RPort,
  165.                            g->LeftEdge,g->TopEdge+g->Height/2-dHeight/2,
  166.                            g->Width,dHeight, 0xc0);
  167.                else
  168.                   BltBitMapRastPort(&dBM, 0,0, gpr->gpr_RPort,
  169.                            g->LeftEdge+g->Width/2-dWidth/2,g->TopEdge+g->Height/2-dHeight/2,
  170.                            dWidth,dHeight, 0xc0);
  171.  
  172.                FreeVec(dBM.Planes[0]);
  173.             }
  174.          }
  175.          else if ((img->Width <= g->Width) && (img->Height <= g->Height))
  176.             DrawImage(gpr->gpr_RPort, img,
  177.                g->LeftEdge+g->Width/2-img->Width/2,
  178.                g->TopEdge+g->Height/2-img->Height/2);
  179.          else
  180.          {  // normal image w/clipping
  181.             struct BitMap bm;
  182.             PLANEPTR plane = (PLANEPTR)img->ImageData;
  183.             ULONG rassize = RASSIZE(img->Width, img->Height);
  184.             UWORD dWidth, dHeight;
  185.             register short i;
  186.  
  187.             // wrap a bitmap around the image data
  188.             InitBitMap(&bm, img->Depth, img->Width,img->Height);
  189.             for (i = 0; i < img->Depth; i++, plane += rassize)
  190.                bm.Planes[i] = plane;
  191.  
  192.             dWidth = MIN(img->Width,g->Width);  dHeight = MIN(img->Height,g->Height);
  193.  
  194.             BltBitMapRastPort(&bm, img->Width/2-dWidth/2,img->Height/2-dHeight/2, gpr->gpr_RPort,
  195.                            g->LeftEdge+g->Width/2-dWidth/2,g->TopEdge+g->Height/2-dHeight/2,
  196.                            dWidth,dHeight, 0xc0);
  197.          }
  198.    }
  199. }
  200.  
  201. static void __interrupt SetAttributes(Class *cl, Object *o, struct opSet *ops, MyData *myd)
  202. {
  203.    struct RastPort *rp;
  204.    struct TagItem *tState = ops->ops_AttrList,
  205.                   *tag = tState;
  206.    BOOL refresh = FALSE;
  207.  
  208.    //PrintTags(ops->ops_AttrList);
  209.  
  210.    while (tag = NextTagItem(&tState))
  211.       switch (tag->ti_Tag)
  212.       {
  213.          case GA_Image:
  214.             refresh = TRUE;  break;
  215.          case GA_ScaleFlags:
  216.             G(o)->UserData = (APTR)tag->ti_Data;  refresh = (BOOL)(G(o)->GadgetRender);  break;
  217.          case GA_ScaleRelWidth:  // refresh assignments only refresh if flag is set
  218.             myd->relWidth = tag->ti_Data;
  219.             if (myd->relWidth < 0)  myd->relWidth = 0;
  220.             refresh = ((ULONG)G(o)->UserData & GAFL_RelX);  break;
  221.          case GA_ScaleRelHeight:
  222.             myd->relHeight = tag->ti_Data;
  223.             if (myd->relHeight < 0)  myd->relHeight = 0;
  224.             refresh = ((ULONG)G(o)->UserData & GAFL_RelY);  break;
  225.          case GA_MUIRemember:
  226.          {
  227.             RememberData *rd = (RememberData *)tag->ti_Data;
  228.  
  229.             if (rd)
  230.             {
  231.                G(o)->GadgetRender = rd->image;
  232.                G(o)->UserData = (void *)rd->flags;
  233.                G(o)->GadgetID = rd->id;
  234.                myd->relWidth = rd->relWidth;
  235.                myd->relHeight = rd->relHeight;
  236.  
  237.                FreeMem(rd, sizeof(RememberData));
  238.             }
  239.             // don't refresh on a remember 'cause will get render method anyway!
  240.          }
  241.       }
  242.  
  243.    if (ops->ops_GInfo && refresh && (rp = ObtainGIRPort(ops->ops_GInfo)))
  244.    {
  245.       DoMethod(o, GM_RENDER, ops->ops_GInfo, rp, GREDRAW_REDRAW);
  246.       ReleaseGIRPort(rp);
  247.    }
  248. }
  249.  
  250. static ULONG __interrupt __saveds dispatchmyimagegclass(Class *cl, Object *o, Msg msg)
  251. {
  252.    MyData *myd;
  253.    ULONG retVal = 0l;
  254.  
  255.    myd = INST_DATA(cl,o);
  256.  
  257.    switch (msg->MethodID)
  258.    {
  259.       case OM_NEW:
  260.          if (o = (Object *)DoSuperMethodA(cl, o, (Msg *)msg))
  261.          {
  262.             SetAttributes(cl, o, (struct opSet *)msg, INST_DATA(cl,o));
  263.             retVal = (ULONG)o;
  264.          }
  265.          break;
  266.       case OM_SET:
  267.          DoSuperMethodA(cl, o, (Msg *)msg);
  268.          SetAttributes(cl, o, (struct opSet *)msg, myd);
  269.          break;
  270.       case GM_HITTEST:
  271.          retVal = FALSE;   // gadget can't be selected
  272.          break;
  273.       case GM_RENDER:
  274.          Render(cl, o, (struct gpRender *)msg, myd);
  275.          break;
  276.       case OM_GET:
  277.       {
  278.          struct opGet *opg = (struct opGet *)msg;
  279.  
  280.          switch (opg->opg_AttrID)
  281.          {  // Primarily for MUIA_Boopsi_Remember tags
  282.             case GA_Image:
  283.                *(opg->opg_Storage) = (ULONG)(G(o)->GadgetRender);
  284.                break;
  285.             case GA_ScaleFlags:
  286.                *(opg->opg_Storage) = (ULONG)(G(o)->UserData);
  287.                break;
  288.             case GA_ScaleRelWidth:
  289.                *(opg->opg_Storage) = (ULONG)myd->relWidth;
  290.                break;
  291.             case GA_ScaleRelHeight:
  292.                *(opg->opg_Storage) = (ULONG)myd->relHeight;
  293.                break;
  294.             case GA_MUIRemember:
  295.             {  // special remember packet that MUI collects & saves when destroying & remaking same object
  296.                RememberData *rd;
  297.  
  298.                if (rd = AllocMem(sizeof(RememberData),MEMF_ANY))
  299.                {
  300.                   rd->image = G(o)->GadgetRender;
  301.                   rd->flags = (ULONG)G(o)->UserData;
  302.                   rd->id = G(o)->GadgetID;
  303.                   rd->relWidth = myd->relWidth;
  304.                   rd->relHeight = myd->relHeight;
  305.                }
  306.                *(opg->opg_Storage) = (ULONG)rd;
  307.             }
  308.          }
  309.       }
  310.       default:
  311.          retVal = (ULONG)DoSuperMethodA(cl, o, (Msg *)msg);
  312.    }
  313.    return(retVal);
  314. }
  315.  
  316. void Free_myimagegclass(Class *cl)
  317. {
  318.    if (cl)
  319.       FreeClass(cl);
  320. }
  321.  
  322. Class *Init_myimagegclass(void)
  323. {
  324.    Class *cl;
  325.    extern ULONG HookEntry();    /* asm-to-C interface glue    */
  326.  
  327.    if (cl = MakeClass(NULL, GADGETCLASS, NULL,sizeof(MyData),0))
  328.    {
  329.       cl->cl_Dispatcher.h_Entry = HookEntry;
  330.       cl->cl_Dispatcher.h_SubEntry = dispatchmyimagegclass;
  331.    }
  332.  
  333.    return(cl);
  334. }
  335.