From: pottier@clipper.ens.fr (Francois Pottier) Subject: csmp-digest-v3-074 Date: Tue, 6 Dec 1994 17:53:07 +0100 (MET) C.S.M.P. Digest Tue, 06 Dec 94 Volume 3 : Issue 74 Today's Topics: Faster SetCPixel Alternatives? Newbie Q Regarding Window Updates Pascal ProcPtr Example? QDGX and Pict resources TransSkel 3.18 (THINK C, Metrowerks) now available how can I implement-program Plug-Ins? using HLock before memcpy The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier (pottier@clipper.ens.fr). The digest is a collection of article threads from the internet newsgroup comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi- regularly and want an archive of the discussions. If you don't know what a newsgroup is, you probably don't have access to it. Ask your systems administrator(s) for details. If you don't have access to news, you may still be able to post messages to the group by using a mail server like anon.penet.fi (mail help@anon.penet.fi for more information). Each issue of the digest contains one or more sets of articles (called threads), with each set corresponding to a 'discussion' of a particular subject. The articles are not edited; all articles included in this digest are in their original posted form (as received by our news server at nef.ens.fr). Article threads are not added to the digest until the last article added to the thread is at least two weeks old (this is to ensure that the thread is dead before adding it to the digest). Article threads that consist of only one message are generally not included in the digest. The digest is officially distributed by two means, by email and ftp. If you want to receive the digest by mail, send email to listserv@ens.fr with no subject and one of the following commands as body: help Sends you a summary of commands subscribe csmp-digest Your Name Adds you to the mailing list signoff csmp-digest Removes you from the list Once you have subscribed, you will automatically receive each new issue as it is created. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest. Questions related to the ftp site should be directed to scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP digest are available there. Also, the digests are available to WAIS users. To search back issues with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html. ------------------------------------------------------- >From smithab@hydra.syr.edu (Core Dumped) Subject: Faster SetCPixel Alternatives? Date: 12 Nov 1994 18:27:26 GMT Organization: Syracuse University, Syracuse, NY Hi. I am working on a fractal program which has to assemble a 640 by 480 picture pixel by pixel. Currently I am using SetCPixel since the color of each pixel I set is different from the previous. What I would like to know, is how to draw directly into the GWorld PixMap. I have tried this: I am trying to use 'baseAddr' to find the PixMap location, and write to it directly, but my colors get messed up, and can't get rowBytes to give me any information. I am writing to a 40 by 40 GWorld, which is 16-bit color. Seems to me that rowBytes should be 80, but it's zero!? Also, if I remove rowBytes from my assignment, and manually replace it with 80, that results in a skewing of the picture. Even more curiously, using 96 for the offset to the next line gives perfect alignment, but crashes the program with Error 11 at the end of the GWorld. Do powermac GWorlds have 16 bytes of some extra information in each line? Perhaps my color structure is wrong also. I was assuming that 16bit color looks like this in memory (each letter = 1 bit): GGGGGRRRRRBBBBBM ^ Least sig. bit at the left. Is this correct? If so, why can't I write a short word directly into memory? I am having to do this write in two calls, one for each byte. Any info on the above would be great. -Adam Smith smithab@mailbox.syr.edu +++++++++++++++++++++++++++ >From mjew@dnai.com (Matthew Jew) Date: Wed, 16 Nov 1994 11:09:01 -0800 Organization: Bold Print Inc. In article <3a31ee$n1c@newstand.syr.edu>, smithab@hydra.syr.edu (Core Dumped) wrote: > Hi. I am working on a fractal program which has to assemble a 640 by 480 > picture pixel by pixel. Currently I am using SetCPixel since the color > of each pixel I set is different from the previous. What I would like to > know, is how to draw directly into the GWorld PixMap. > Yes, SetCPixel is not the fastest thing in the world, but I was always taught that mucking around with the pixmap directly was very very very bad idea. Your drawing routine (as described) sounds like it would work *only* with 16-bit color pixmaps. Will your program need to handle other color depths? Tread carefully. Doing things like this will almost guarantee your program will break when the system software changes. +++++++++++++++++++++++++++ >From kenp@tuli (Kenneth Prehoda) Date: 16 Nov 1994 20:33:09 GMT Organization: Division of Information Technology Matthew Jew (mjew@dnai.com) wrote: : In article <3a31ee$n1c@newstand.syr.edu>, smithab@hydra.syr.edu (Core : Dumped) wrote: : > Hi. I am working on a fractal program which has to assemble a 640 by 480 : > picture pixel by pixel. Currently I am using SetCPixel since the color : > of each pixel I set is different from the previous. What I would like to : > know, is how to draw directly into the GWorld PixMap. : > : Yes, SetCPixel is not the fastest thing in the world, but I was always : taught that mucking around with the pixmap directly was very very : very bad idea. Then you were taught incorrectly. It is true that mucking around with a windows's pixmap, or anything else that would draw directly to the screen is asking for trouble. However, there is absolutely nothing wrong with drawing directly into an offscreen pixmap. In fact, this is the Apple sanctioned way to do fast drawing: Do all of your direct drawing to an offscreen GWorld and copybits that to the screen. : Your drawing routine (as described) sounds like it would work *only* with : 16-bit color pixmaps. Will your program need to handle other color depths? : Tread carefully. Doing things like this will almost guarantee your : program will break when the system software changes. If your program needs to handle different color depths, then it can make gworlds with different depths. Not complicated. Your warnings are not necessary. This WILL NOT break when system software changes. If it does, then a lot of currently well-behaved programs will. -Ken Prehoda Department of Biochemistry University of Wisconsin-Madison kenp@nmrfam.wisc.edu +++++++++++++++++++++++++++ >From mjew@dnai.com (Matthew Jew) Date: Wed, 16 Nov 1994 16:46:57 -0800 Organization: Bold Print Inc. In article <3adqa5$7ti@news.doit.wisc.edu>, kenp@tuli (Kenneth Prehoda) wrote: > : Yes, SetCPixel is not the fastest thing in the world, but I was always > : taught that mucking around with the pixmap directly was very very > : very bad idea. > > Then you were taught incorrectly. It is true that mucking around > with a windows's pixmap, or anything else that would draw directly > to the screen is asking for trouble. However, there is absolutely > nothing wrong with drawing directly into an offscreen pixmap. In > fact, this is the Apple sanctioned way to do fast drawing: Do all > of your direct drawing to an offscreen GWorld and copybits that > to the screen. Yes, you are right. I wrote before I thought carefully about what he was asking. Thanks for pointing that out. > If your program needs to handle different color depths, then it can > make gworlds with different depths. Not complicated. > However, in his original question, he was asking *specifically* about the format for 16-bit color pixmaps, and how to write to them. Therefore, even if he did make a pixmap of a different depth (not complicated), the routine would have to be rewritten to handle the differently formatted pixmap (more complicated). +++++++++++++++++++++++++++ >From macneils@aol.com (MacneilS) Date: 16 Nov 1994 22:05:13 -0500 Organization: America Online, Inc. (1-800-827-6364) In article , mjew@dnai.com (Matthew Jew) writes: >>>>>> but I was always taught that mucking around with the pixmap directly was very very very bad idea. <<<<<< develop Issue 17 says that it's 100% OK to change the pixmap of a GWorld directly, and that doing such will be supported on ALL future machines. The article also tells you the best way to do it, and when to do it. Take Care, MacneilS@aol.com +++++++++++++++++++++++++++ >From smithab@hydra.syr.edu (Core Dumped) Date: 17 Nov 1994 12:49:49 GMT Organization: Syracuse University >> If your program needs to handle different color depths, then it can >> make gworlds with different depths. Not complicated. >> > >However, in his original question, he was asking *specifically* about the >format for 16-bit color pixmaps, and how to write to them. Therefore, even >if he did make a pixmap of a different depth (not complicated), the >routine would have to be rewritten to handle the differently formatted >pixmap (more complicated). Yes, I did ask specifically about 16-bit GWorlds. I am using 16bit because it is a nice compromise of GWorld size and image quality. Having my routine only write to 16-bit GWorlds also means that I don't have to use any conditionals or function pointers to switch between separate drawing routines for each possible bit-depth GWorld, which makes for a simpler, faster program. I just let copybits take care of the color translation, so my program is optimized for 16-bit monitors (though performance doesn't suffer much at 32-bits). It's just a fractal program, and it doesn't ever use the full 32768 colors anyways :) Thanks to everyone who helped me out with this! I'm currently trying to track down some of these past 'Develop's. -Adam smithab@mailbox.syr.edu +++++++++++++++++++++++++++ >From Bruce@hoult.actrix.gen.nz (Bruce Hoult) Date: Sat, 19 Nov 1994 12:56:58 +1300 (NZDT) Organization: (none) mjew@dnai.com (Matthew Jew) writes: > In article <3a31ee$n1c@newstand.syr.edu>, smithab@hydra.syr.edu (Core > Dumped) wrote: > > > Hi. I am working on a fractal program which has to assemble a 640 by 480 > > picture pixel by pixel. Currently I am using SetCPixel since the color > > of each pixel I set is different from the previous. What I would like to > > know, is how to draw directly into the GWorld PixMap. > > > > Yes, SetCPixel is not the fastest thing in the world, but I was always > taught that mucking around with the pixmap directly was very very very bad idea. > Your drawing routine (as described) sounds like it would work *only* with > 16-bit color pixmaps. Will your program need to handle other color depths? > Tread carefully. Doing things like this will almost guarantee your program will > break when the system software changes. No, GWorlds are guarenteed always to work. If he creates a 4-bit deep GWorld then he will always get a 4-bit deep GWorld, even in the far distant future, and the layout of the pixmap will always be the same. And no matter what Apple does to the screen hardware, CopyBits will always know how to copy from a 4-bit GWorld to whatever the new screen format is -- it may not always be optimally fast, but it will always work. -- Bruce +++++++++++++++++++++++++++ >From bhamlin@netcom.com (Brian Hamlin) Date: Mon, 21 Nov 1994 00:33:04 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) If you want to set pixels directly in GWorlds: - use the flag 'keepLocal' when calling NewGWorld - use routines GetGWorldPixMap(), then GetPixBaseAddr() to find pixels - LockPixels whenever accessing bits - remember to clear the high bit of rowBytes when calc' bit positions ! When CopyBits()'ing from a GWorld - don't mix GetPort()/SetPort() with GetGWorld()/SetGWorld() - always SetGWorld to the dst GrafPort - set ForeColor(blackColor) BackColor(whiteColor) in dst Port ! -- -- Brian M. Hamlin noEsis software construction bhamlin@netcom.com +1 510 271-7971 +++++++++++++++++++++++++++ >From 103t_english@west.cscwc.pima.edu Date: 21 Nov 94 17:21:31 MST Organization: (none) In article , bhamlin@netcom.com (Brian Hamlin) writes: > If you want to set pixels directly in GWorlds: > - use the flag 'keepLocal' when calling NewGWorld I thought that one could draw to graphics card cache as well if one wanted? Lawson --------------------------- >From ineluki@u.washington.edu (Paul McElroy) Subject: Newbie Q Regarding Window Updates Date: 22 Nov 1994 20:01:40 GMT Organization: University of Washington I have a simple question. What is the correct procedure to make sure the correct window is updated on an updateEvt? My WaitNextEvent loop includes: switch(event) { case updateEvt: HandleUpdate((WindowPtr)event->message); break; Ok, and down here in HandleUpdate, I get 'window', the Window Pointer that was passed from above, and the usual stuff: GetPort(&savePort); SetPort(window); BeginUpdate(window); DrawControls(window); ...etc... EndUpdate(window); SetPort(savePort); Now, how do I distinguish between one window and another here? My app has two windows displayed at once, one with a pic and a control, the other with a different pic and controls. What is the procedure to update the correct window with the correct pic and controls? Is it with a switch(window) or if(window)? Thanks for any replies. ineluki@u.washington.edu +++++++++++++++++++++++++++ >From Eric Kidd Date: 22 Nov 1994 22:25:47 GMT Organization: Dartmouth College In article <3atin4$m6a@nntp1.u.washington.edu> Paul McElroy, ineluki@u.washington.edu writes: > Now, how do I distinguish between one window and another here? My app > has two windows displayed at once, one with a pic and a control, the > other with a different pic and controls. What is the procedure to update > the correct window with the correct pic and controls? Is it with a > switch(window) or if(window)? Thanks for any replies. In general, you can identify windows on screen by using the refCon field in the window record. Assign some unique value to this when the window is created (perhaps a pointer to the data describing the window) and use this to identify your windows. (Either switch or if can be used, depending on the situation and your style.) In the following code, I assign refCon a pointer to data which: 1) identifies the type of window 2) provides info on drawing it The latter varies, so I create two different data records with the ID field at the top of each. For example (from memory, my IM books are packed--check your header files for spelling errors and whatnot if this won't compile): typedef struct { short id; ControlHandle myControl; PictHandle myPict; } myWinData1; typedef struct { short id; ControlHandle myControl; ControlHandle myOtherControl; PictHandle myPict; } myWinData2; /* Yes, unions work as well. */ # define WINTYPE1 (1) # define WINTYPE2 (2) .... at window creation (of the first type) // create window here myWinData1* data = (myWinData1*) NewPtr( sizeof(myWinData1) ); // Handles work, too // check to see if data == 0. Don't proceed if it does, // because that means the system couldn't allocate // memory. win->refCon = (long) data; data->id = WINTYPE1; // fill out rest of info .... at drawing time // since the ID is in the same place in both structures // we can pick either type to check it. Once we know // what it is, the doDrawWinTypeX functions can coerce // the refCon to the right pointer type internally. // There is a way to identify DA refCons, but it has become // mostly irrelevant under System 7. See the manual. switch ( ((myWinData1*) theWindow->refCon)->id ) { case WINTYPE1: doDrawWinType1( theWindow ); break; case WINTYPE2: doDrawWinType2( theWindow ); break; }; That's very rough, but it may point you in the correct direction. If you'd like a better presentation of this, mail me at emk@dartmouth.edu, (or wait for someone else to elaborate). My books will be unpacked when I return from Thanksgiving (I'm headed home tomorrow morning). Have fun programming and consider getting Inside Macintosh: Toolbox Essentials for a more enjoyable experience. The sample code is very good, and helped me to implement a great number of things that would have kept me up all night otherwise. --------------------------- >From pzwiefel@students.wisc.edu (Zwiefelhofer) Subject: Pascal ProcPtr Example? Date: Sat, 19 Nov 1994 14:20:41 -0600 Organization: Division of Information Technology I'd like to give the user the ability to choose between several transfer functions in a program. I would like to use functions as procedure pointers for convenience. Does anyone have any Pascal examples of how to declare my procedures or functions so that I can use the @ operator on them and then pass a pointer to them depending on which function the user chose? Thanks. Dave +++++++++++++++++++++++++++ >From pottier@drakkar.ens.fr (Francois Pottier) Date: 21 Nov 1994 12:56:48 GMT Organization: Ecole Normale Superieure, PARIS, France In article , Zwiefelhofer wrote: >I'd like to give the user the ability to choose between several transfer >functions in a program. I would like to use functions as procedure >pointers for convenience. If you want to use function pointers, then you will have to use some inline assembly. Not much, but it can be a problem if you don't assembly at all. There is a way to do it in pure Think Pascal without pointers. I don't know what you mean by a transfer function; let's say it's a function from reals to reals. You can declare function Transfer1 (x : real) : real; blah blah... function Transfer2 (x : real) : real; more blah blah... procedure ComputeUsingTransferFunction (function f (x : real) : real); begin ... use f ... end; and finally you can call ComputeUsingTransferFunction(Transfer1) or ComputeUsingTransferFunction(Transfer2). Unfortunately, as far as I know, you have to pass function names as parameters to ComputeUsingTransferFunction; I mean, you can't use a variable of type "function (x : real) : real". The Think Pascal doc should explain all this in detail... Hope this helps -- Francois Pottier pottier@dmi.ens.fr - ---------------------------------------------------------------------------- Check my WWW page at http://acacia.ens.fr:8080/home/pottier/index.html ... +++++++++++++++++++++++++++ >From pzwiefel@students.wisc.edu (Zwiefelhofer) Date: Sun, 20 Nov 1994 19:28:27 -0600 Organization: Division of Information Technology In article , Jaeger@fquest.com (Brian Stern) wrote: > Here's an example of jumping to a procedure that takes no parameters: > > procedure JumpToOldFilter (theFilterProc: ProcPtr); > {Move the procptr to the stack and JSR to it } > inline > $205F, $4E90; {MoveA.L (A7)+, A0 ; JSR (A0) } > > > You can modify this based on the parameters that you need to pass and/or > return. Look at the disassembled code that the compiler generates to call > a procedure like the one you want to call. Model your inline procedure > after that code. Obviously this example won't work on the PPC. I'm afraid this is beyond me. Do I really need to muck about with assembly? I thought that there would be a comparatively simple method of declaring a specific type of procPtr for functions that take one extended and return one extended. Is this possible? Any examples? Ideas? Thanks. -Dave +++++++++++++++++++++++++++ >From greg@cosc.canterbury.ac.nz (Greg Ewing) Date: 21 Nov 1994 04:36:59 GMT Organization: University of Canterbury, Christchurch, New Zealand In article , pzwiefel@students.wisc.edu (Zwiefelhofer) writes: |> I thought that there would be a comparatively simple method of |> declaring a specific type of procPtr for functions that take one extended |> and return one extended. Unfortunately, in Pascal there is no such method. Pascal has no notion of a pointer to a procedure the way C has. Applying @ to a procedure is just a kludge that was added to provide a way of passing procedures to the toolbox. The Pascal compiler has no idea what type of pointer this is, and doesn't have the concepts to understand even if you tried to explain to it. If you are using Object Pascal there is a much better method of achieving what you want. Define an object type which has a method for carrying out whatever it is you want to do, and define subtypes which implement it in different ways. e.g. type Transformer = object procedure MungeIt(inp: MyStuff; var out: MyStuff); end; FirstTransformer = object(Transformer) procedure MungeIt(inp: MyStuff; var out: MyStuff); override; end; SecondTransformer = object(Transformer) procedure MungeIt(inp: MyStuff; var out: MyStuff); override; end; {etc...} procedure FirstTransformer.MungeIt(inp: MyStuff; var out: MyStuff); begin {Munge your stuff the first way} end; procedure SecondTransformer.MungeIt(inp: MyStuff; var out: MyStuff); begin {Munge your stuff the second way} end; {etc...} Now make an instance of each of these objects and let the user choose one of them somehow, e.g. var transformers: array[1..numTransformers] of Transformer; procedure InitialiseTransformers; {Call this when you're initialising your application} var t1: FirstTransformer; t2: SecondTransformer; {etc} begin new(t1); transformers[1] := t1; new(t2); transformers[2] := t2; {etc} end; procedure ApplyATransformer(whichOne: integer; inp: MyStuff; var out: MyStuff); begin transformers[whichOne].MungeIt(inp, out); end; There are many ways you use this stuff. The point is that you can pass around Transformers the same way you would procedure pointers, and call them easily and safely. If you don't know about Object Pascal, find out - it makes a lot of things much easier, and is the basis of some very powerful GUI frameworks like MacApp and the Think Class Library. |> -Dave Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of Japan Inc.| greg@cosc.canterbury.ac.nz +--------------------------------------+ +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 22 Nov 94 10:06:44 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , pzwiefel@students.wisc.edu (Zwiefelhofer) writes: > In article , > Jaeger@fquest.com (Brian Stern) wrote: > >> Here's an example of jumping to a procedure that takes no parameters: >> >> procedure JumpToOldFilter (theFilterProc: ProcPtr); >> {Move the procptr to the stack and JSR to it } >> inline >> $205F, $4E90; {MoveA.L (A7)+, A0 ; JSR (A0) } >> >> >> You can modify this based on the parameters that you need to pass and/or >> return. Look at the disassembled code that the compiler generates to call >> a procedure like the one you want to call. Model your inline procedure >> after that code. Obviously this example won't work on the PPC. > > I'm afraid this is beyond me. Do I really need to muck about with > assembly? I thought that there would be a comparatively simple method of > declaring a specific type of procPtr for functions that take one extended > and return one extended. Stay cool! The above two words of machine code are all you will need. You can use them to call any Pascal procedure or function, regardless of the arguments or function result type. For example, you want to call a function like Function F ( X : Extended ) : Extended; You can do it like this: Function Call_F ( X : Extended; F : ProcPtr ) : Extended; Inline $205F, { move.l (sp)+, a0 } $4E90; { jsr (a0) } eg FPtr := @F; Y := Call_F(X, FPtr) The only rule to remember when defining the "Call_F" routine is that the argument list and function result types must match those of the routine you're going to call, except that Call_F takes an extra argument, which is the address of the routine to call. This must be the last argument. The inline code is always the same! Lawrence D'Oliveiro fone: +64-7-856-2889 Computer Services Dept fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From greg@cosc.canterbury.ac.nz (Greg Ewing) Date: 22 Nov 1994 01:50:21 GMT Organization: University of Canterbury, Christchurch, New Zealand In article , pzwiefel@students.wisc.edu (Zwiefelhofer) writes: |> I really don't |> want to go through several if-then statements in a procedure that may be |> called several 100K times per session if I don't absolutely have to. Have you considered using a case statement switching on an integer or enumerated type? If the range of cases is contiguous this should compile into a table lookup, which will be faster than a chain of if-thens if there are enough cases. |> -Dave Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of Japan Inc.| greg@cosc.canterbury.ac.nz +--------------------------------------+ +++++++++++++++++++++++++++ >From pzwiefel@students.wisc.edu (Zwiefelhofer) Date: Mon, 21 Nov 1994 21:30:49 -0600 Organization: Division of Information Technology In article <1994Nov22.100645.35467@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote: > Stay cool! The above two words of machine code are all you will need. Okay, I'll give it a go! Thanks. -Dave +++++++++++++++++++++++++++ >From obo@dec59.ruk.cuni.cz (Ondrej Bojar) Date: 21 Nov 1994 13:21:55 GMT Organization: Charles University Prague, Computer Center When I wanted to do this (for updating windows), I had to ask a friend to create an MPW .o file of a C routine calling my proc (at procptr) with some params. I think pascal has only some routine called DOJSR (don't quote me) that doesn't allow to pass any parameters. I think it's easier to use objects... --------------------------- >From jaks@netcom.com (Eric Jackson) Subject: QDGX and Pict resources Date: Wed, 16 Nov 1994 20:47:07 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) I would like to be able to read in a 'pict' recource from a resource file into my Quick Draw GX application. This pict consists of a color bit map image. In all of the examples that I have seen in the Quick Draw GX Developer CD the bit maps are of a type called 'pxmp'. What I would like to do is to read my pict into a BitMapShape and them clip it. Any suggestions would be nice. Eric Jaskson jaks@netcom.com +++++++++++++++++++++++++++ >From jaks@netcom.com (Eric Jackson) Date: Wed, 16 Nov 1994 22:57:09 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) In article , Eric Jackson wrote: >I would like to be able to read in a 'pict' recource from a resource >file into my Quick Draw GX application. This pict consists of a >color bit map image. > >In all of the examples that I have seen in the Quick Draw GX Developer CD >the bit maps are of a type called 'pxmp'. > >What I would like to do is to read my pict into a BitMapShape and them clip it. >Any suggestions would be nice. > >Eric Jaskson >jaks@netcom.com > Well I have been able to draw my first gxShape that was imported from a picture. There is a good discussion of how to do this in QuickDraw GX environment and utilities. Here is some sample code that works: void DoInitialization(gWindow) WindowPtr gWindow; { gxTransform PerspectiveTransform; gxMapping PerspectiveTransformMapping; PicHandle Picture = (PicHandle) GetResource ('PICT',128); gxShape aPictureShape; Rect PictureBox; Point styleStrech; PictureBox = (**Picture).picFrame; aPictureShape = GXNewShape(gxPictureType); styleStrech.v = 1; styleStrech.h = 1; GXConvertPICTToShape(Picture, gxDefaultOptionsTranslation,&PictureBox,&PictureBox, styleStrech,aPictureShape, nil); gShape = aPictureShape; } This code works with the *graphics shell.c* program shell that comes with the QuickDraw GX SDK, later on it will draw gShape for me automatically. I still don't really understand how to get this into a BitMap shape yet but I will keep working. Shure does not seem to be a lot of discussion about Quick Draw GX basics on here yet. Eric Jackson jaks@netcom.com +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 17 Nov 94 16:56:39 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , jaks@netcom.com (Eric Jackson) writes: > I would like to be able to read in a 'pict' recource from a resource > file into my Quick Draw GX application. This pict consists of a > color bit map image. > > In all of the examples that I have seen in the Quick Draw GX Developer CD > the bit maps are of a type called 'pxmp'. > > What I would like to do is to read my pict into a BitMapShape and them clip it. > Any suggestions would be nice. Are you trying to a) read QuickDraw pictures in from PICT resources and convert them to GX shapes, or b) read flattened GX shapes in from resources and unflatten them? The first is easy, the second is only slightly harder. To convert a QuickDraw picture to a GX shape, you use GXConvertPICTToShape. To unflatten a GX shape, you use GXUnflattenShape. There is source code for a routine called HandleToShape in the GX libraries, that should do exactly what you want. By the way, Apple seems to have standardized on 'qdgx' as the OSType type code for GX shapes (as opposed to 'grfx', which some pre-release utilities used, and which I prefer :-)). So if you want to store a flattened GX shape in a resource, make it a resource of type 'qdgx'. Then when you copy it to the clipboard from ResEdit, it will display properly in other GX-savvy programs. And conversely, you can create the shape in another program, and paste it into your resource forks with ResEdit. Lawrence D'Oliveiro fone: +64-7-856-2889 Computer Services Dept fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From jaks@netcom.com (Eric Jackson) Date: Mon, 21 Nov 1994 05:32:36 GMT Organization: NETCOM On-line Communication Services (408 261-4700 guest) In article <1994Nov17.165639.35369@waikato.ac.nz>, Lawrence D'Oliveiro, Waikato University wrote: >In article , jaks@netcom.com (Eric Jackson) writes: >> I would like to be able to read in a 'pict' recource from a resource >> file into my Quick Draw GX application. This pict consists of a >> color bit map image. >> >> In all of the examples that I have seen in the Quick Draw GX Developer CD >> the bit maps are of a type called 'pxmp'. >> >> What I would like to do is to read my pict into a BitMapShape and them clip it. >> Any suggestions would be nice. > >Are you trying to > > a) read QuickDraw pictures in from PICT resources and convert them to > GX shapes, or > b) read flattened GX shapes in from resources and unflatten them? > >The first is easy, the second is only slightly harder. > >To convert a QuickDraw picture to a GX shape, you use GXConvertPICTToShape. > >To unflatten a GX shape, you use GXUnflattenShape. There is source code for >a routine called HandleToShape in the GX libraries, that should do exactly >what you want. > >By the way, Apple seems to have standardized on 'qdgx' as the OSType type >code for GX shapes (as opposed to 'grfx', which some pre-release utilities >used, and which I prefer :-)). So if you want to store a flattened GX shape >in a resource, make it a resource of type 'qdgx'. Then when you copy it to >the clipboard from ResEdit, it will display properly in other GX-savvy programs. >And conversely, you can create the shape in another program, and paste it >into your resource forks with ResEdit. > >Lawrence D'Oliveiro fone: +64-7-856-2889 >Computer Services Dept fax: +64-7-838-4066 >University of Waikato electric mail: ldo@waikato.ac.nz >Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 Actually I got that far already. That is I read in my picture and then converted it into a gxPictureType shape. Now what I wanted to do was to change my PictureShape into a gxBitmapShape. I was able to do this as well but I seem to have lost all of my color information in doing this. The way I did this was by calling GXSetShapeType(PictureShapeThatWillBecomeBitMapShape,gxBitmapShape); When I put my picture that I have created by exactly the method that you discribed what happend is that I get a black and white bit map and all of my color gets lost. What I would like to do is to keep my color information. For now what I have been doing is to just move forward and work with a picture shape and not convert it into a bitmap. Maybe what I should be doing is to just draw my picture shape into a bitmap but I have not gotten around to trying this just yet since there is so much other stuff that I have been working with. I can report that I think that QuickDraw GX is really fun to work with and has a lot of nice features. Eric Jackson jaks@netcom.com +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 22 Nov 94 10:26:20 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , jaks@netcom.com (Eric Jackson) writes: > > Actually I got that far already. That is I read in my picture and then > converted it into a gxPictureType shape. Now what I wanted to do was to > change my PictureShape into a gxBitmapShape. > > I was able to do this as well but I seem to have lost all of my color > information in doing this. > > The way I did this was by calling > > GXSetShapeType(PictureShapeThatWillBecomeBitMapShape,gxBitmapShape); > > When I put my picture that I have created by exactly the method that you > discribed what happend is that I get a black and white bit map and all of > my color gets lost. What I would like to do is to keep my color information. > For now what I have been doing is to just move forward and work with a picture > shape and not convert it into a bitmap. Maybe what I should be doing is to > just draw my picture shape into a bitmap but I have not gotten around to trying > this just yet since there is so much other stuff that I have been working with. I guess if GXSetShapeType is changing the picture to a black-and-white bitmap, then you really have to draw the shape into a bitmap of the depth you need, if you want to keep the colours. The good news is, it's not much harder than QuickDraw GWorld calls. Here's an outline of the steps: 1) Set up a gxBitmap record describing the bitmap shape you want to create, initializing the fields as follows: image := nil (* let GX allocate the pixels for you *) width := the desired width in pixels height := the desired height in pixels rowBytes := (width + 31) DIV 32 * 4 pixelSize := 32 space := gxRGB32Space set := nil (* ignored for direct depths *) profile := nil. 2) Create a bitmap shape from the gxBitmap record, using GXNewBitmap. 3) Create an offscreen viewgroup using GXNewViewGroup. 4) Create an offscreen view device, using GXNewViewDevice, passing the bitmap you created in step 2, and the view group you created in step 3. 5) Create a viewport attached to the viewgroup you created in step 3. Now all you have to do is draw your shape into the viewport you created in step 5. Tip: you should create a full shape with an appropriate background colour (eg white) and draw it into the offscreen viewport first, to initialize all the pixels to a known value, before drawing your picture shape. Once you've finished with the offscreen structures, you can dispose of them by calling GXDisposeViewGroup on the offscreen viewgroup. This will automatically dispose of the attached view device and viewport as well. All that will be left is the bitmap shape. > I can report that I think that QuickDraw GX is really fun to work with and > has a lot of nice features. Same here! Lawrence D'Oliveiro fone: +64-7-856-2889 Computer Services Dept fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 22 Nov 94 13:06:37 +1300 Organization: University of Waikato, Hamilton, New Zealand In article <1994Nov22.102621.35468@waikato.ac.nz>, I wrote: > 1) Set up a gxBitmap record describing the bitmap shape you want to create, .. > rowBytes := (width + 31) DIV 32 * 4 Oops! This calculation is only correct for a 1-bit-deep pixmap. For 32 bits per pixel, it should of course be rowBytes := width * 4 Lawrence D'Oliveiro fone: +64-7-856-2889 Computer Services Dept fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 --------------------------- >From dubois@uakari.primate.wisc.edu (Paul DuBois) Subject: TransSkel 3.18 (THINK C, Metrowerks) now available Date: 21 Nov 1994 10:56:42 -0600 Organization: Castra Parvulorum Release 3.18 of TransSkel, a skeleton for Macintosh application development under THINK C or Metrowerks C, is now available. This release is quite similar to release 3.17, with the following differences: - It compiles under either the universal headers or the old Apple headers. Prior releases compiled only under the old headers. - It compiles under THINK C or Metrowerks C. Prior releases were written for THINK C only. - It can be used to generate either 68K or PowerPC code. Prior releases worked only for 68K code. PowerPC code generation has been tested only with Metrowerks C - 3.17 broke compatibility of the THINK C library with THINK Pascal programs. 3.18 fixes that. TransDisplay 3.06 and TransEdit 3.06 are also available now, and have been updated in similar ways. TransDisplay and TransEdit are modules that can be dropped into TransSkel-based projects to provide display-only or editable text windows. TransSkel, TransDisplay, and TransEdit are available via any of the following: anonymous ftp to ftp.primate.wisc.edu (under /pub/mac/TransSkel) gopher to gopher.primate.wisc.edu (select "Primate Center Software Archives") WWW using URL http://www.primate.wisc.edu/ (select "Primate Center Software Archives") -- Paul DuBois dubois@primate.wisc.edu --------------------------- >From juez@informatik.fh-augsburg.de (Juez Markus) Subject: how can I implement-program Plug-Ins? Date: 9 Nov 1994 13:23:04 GMT Organization: Fachhochschule Augsburg, Germany How can I implement Plug-Ins into my program (like filters in the Photoshop)? What kind of data-structures and functions do I need? Will I need an extra program to generate the moduls (like the filters)? Many Thanks for hints +++++++++++++++++++++++++++ >From nick+@pitt.edu ( nick.c ) Date: Wed, 09 Nov 1994 12:59:24 -0500 Organization: The Pitt, Chemistry In article <39qifo$7ju@av2.rz.fh-augsburg.de>, juez@informatik.fh-augsburg.de (Juez Markus) wrote: > How can I implement Plug-Ins into my program (like filters in the Photoshop)? > What kind of data-structures and functions do I need? > Will I need an extra program to generate the moduls (like the filters)? > > Many Thanks for hints Don't really know, but can think of a few possibilities. If it's simple, you can create "preferences" like files, that toggle on or off or configure pre-made functionality it the program. That would be the easiest, and if your just need file translation filters, it would be doable. If not, compile code resources (an option in the compiler in both CW & SC++), imbed those resources in files with the type and creator set for your app, then have the app scan a certain folder in the same folder (or in the preference folder) as your app on startup, and load those code resources that it finds. Not sure about the interface between those resources and your app's code. Maybe just call a function with the same name as the module as it loads them, and that function tells your program what functions in your app the module interfaces to. Then you'd have to do negotiation within your program to make sure two modules don't step on each others feet. Hmm... Might be easier if you mentioned what the modules are supposed to do. Are they just file translation filters, or do they have to have functionality of some kind? Internet: nick+@pitt.edu _/ _/ _/ _/_/_/ _/ _/ eWorld: nick _/_/ _/ _/ _/ _/ _/_/_/ CIS: 71232,766 _/ _/_/ _/ _/ _/ _/ http://www.pitt.edu/~nick/ _/ _/ _/ _/_/_/ _/ _/ +++++++++++++++++++++++++++ >From oster@netcom.com (David Phillip Oster) Date: Wed, 9 Nov 1994 20:57:52 GMT Organization: Netcom Online Communications Services (408-241-9760 login: guest) Here is what you need to do: 1.) Define a storage location for the plug-ins. such as, for an application called Foo, a folder called "Foo Pouch", which your installer creates, and which you search for in the same folder as your application, the preferences folder, and the System Folder (for System 6 (no preferences)) the name of the pouch folder should be in a 'STR ' or 'STR#' resource for easy internationalization. 2.) Define a resource type to hold your plug-in exectuable code. You should allow any resID number, since some development systems have restrictions on which id numbers can be used for multi-segment code resources. Decide whether you will allow multiple code resources per file. For example, Photoshop lets you bundle an import resource, an export resource, and a filter into the same file, each is its own resource type. It uses the resource name to tell the user, so each has its own name. 3.) Decide on the user interface to plug-ins. Commonly, at program start-up, you scan the pouch and collect all the files of the correct types. Then you scan for appropriate code resources, then put the names of the resources in the menus. You can also use the file names, or run the code resources and ask them for the correct name. 4.) decide on the programmer's interface. MPW likes to pass parameters as longs, and pascal development systems usually can't generate C interfaces, so your best bet is to have the entry point of your code resource be something like: extern pascal long PlugIn(long selector, CallbackPtr callback, long param1, long param2, long param3, long refcon); where params 1 through 3 will have specific meanings depending upon which function selector is asking to be performed. CallbackPtr is something like this: typedef struct CallbackRec{ DrawFunc erase; DrawFunc paint; }CallbackRec, *CallbackPtr; where DrawFunc is something like: typedef pascal void (*DrawFunc)(Rect *); This is the place where you define services that your application will perform when asked to by the code resource of the plug-in. You'll need to define a bunch of selectors for what you want the plug-in to do. You should definately give the plug-in an Init selector, and a dispose selector, and have Init return an error or a refcon, which will be passed back to the plug-in on each call, so the plug-in can have some persistent storage. You should definately set the CurResFile to the plug-in's file while it is running, so it can easily get at any resources it needs. The Init selector should pass the interface version in param1 and the program version in param2, so that the plug-in can cope with different versions of your program. The actual call to the plug-in looks like: h = GetResource('PLUG', 1); HLock(h); xh = StripAddress(h); ((PlugInFunc) *xh)(kInit, callbacks, kInterfaceVer1, kProgVer1, 0, 0); HUnlock(h); -- - ------- oster@netcom.com ---------- "A man hears what he wants to hear and misremembers the rest." -- Paul Simon, ("The Boxer") +++++++++++++++++++++++++++ >From jonasw@lysator.liu.se (Jonas Wallden) Date: 10 Nov 1994 10:22:19 GMT Organization: (none) juez@informatik.fh-augsburg.de (Juez Markus) writes: >How can I implement Plug-Ins into my program (like filters in the Photoshop)? >What kind of data-structures and functions do I need? >Will I need an extra program to generate the moduls (like the filters)? > >Many Thanks for hints Plug-in code is not too hard to write. Basically you load resources from external files and call them with a predefined set of parameters. If you are writing your own application you are free to design this calling interface any way you like, but if you are writing e.g. BBEdit externals you should read the documentation to see what the application requires from your code. Now, you asked for the first case, and here are some hints: * Keep a list of external files that you open so you can set the correct resource file before calling the code. This will make life easier for the external in case it needs to access resources in it's own file. * Define an API that can be extended in future versions. Parameter blocks are great for this; just place a version number first in the parameter block so the extension knows which fields in the pb that are available. When you call you simply pass a pointer to this block (whose size can vary among different versions). * Provide a parameter block with callbacks. This is a list of function pointers that point to routines in your application that the extension can call to request services from you. This can e.g. be window handling in case you need to handle floating windows. * Make sure the resources are locked down while you call them. Also call StripAddress on the handle to ensure compatibility with 24-bit systems. * Define a number of messages that you pass to the extension. Look at some of Apple's xDEF docs to get inspiration. It is very useful for the extension to know when it's called the first time, and when it's about to be closed down so it can allocate and dispose of memory that it needs. Also define error messages, or use the error codes already defined for other Toolbox managers. * Write a header file that you ship together with your application so other programmers can compile their extensions. Declare all C routines as 'pascal'. * Document required resources, file types/creators and other stuff that your application expects to find in the external resource files as well. There are a number of sample applications that you can look at. E.g., check out the CodeWarrior CD which includes instructions on how to write code that work on PowerPC Macs, and how to call PPC from 68K and vice versa. BBEdit is also a good place to start. Read the programmer documentation that is included to get an idea of how things work. Finally, writing externals is just like writing any other code resource and can be done in Pascal or C. Note though that Pascal is not as flexible so you might need some inline assembly to use e.g. callback routines. Disclaimer: those who have seen my shareware application PowerScan knows that I don't follow all of the recommendations myself. This is because I've learned most things by doing it the wrong way... :-) ............... ....................... ........... ............... jonas wallden internet applelink phone/fax mac hacker jonasw@lysator.liu.se sw1369 +46-13-176084 +++++++++++++++++++++++++++ >From sandvik@apple.com (Kent Sandvik) Date: Mon, 21 Nov 1994 18:05:51 -0800 Organization: Apple Computer, Inc. Developer Technical Support I would like to know why developers in general are not interested to use the Component Manager for plug-in material. Let me know more of the pros and cons so I could provide feedback to engineering and marketing about this all. Cheers, Kent -- Kent Sandvik sandvik@apple.com New Media Analyst/Programmer Private activities on Internet. +++++++++++++++++++++++++++ >From spencerl@crl.com (Spencer Low) Date: 21 Nov 1994 22:08:01 -0800 Organization: LowTek Creations Kent Sandvik (sandvik@apple.com) wrote: > I would like to know why developers in general are not interested to use > the Component Manager for plug-in material. Let me know more of the pros > and cons so I could provide feedback to engineering and marketing about > this all. I just got into this thread, but... One reason I'm reluctant to use the Component Manager is all the UniversalProcPtr stuff needed for use with the Universal Headers. It's not as easy as, say a Control Strip plug-in. I do think that components are easier to use in an application (OpenComponent, call the stuff, CloseComponent). Another con is the glue necessary for PowerMac native components (I've read about this in the Component Manager 3 Q/A Tech Note). Spencer -- ________________________________________________________________________ Spencer Low ------- LowTek Creations ------- spencerl@crl.com --------------------------- >From tjb@acpub.duke.edu (Thomas J. Bryce) Subject: using HLock before memcpy Date: 19 Nov 1994 03:04:19 GMT Organization: Duke University, Durham, NC, USA I notice people usually surround a memcpy statement of a handle or pointer with HLock and HUnlock. Is this necessary always? I'm inclined to believe, YES, but I'd like to hear it stated directly rather than assuming it from seeing it done all the time. It seems you can't rely on the memory to not be moved if you copy the pointer from the handle and use it for a while, as in memcpy (*handle1, *handle2,size); Could someone verify this for me? Tom +++++++++++++++++++++++++++ >From wem53067@uxa.cso.uiuc.edu (TheBard) Date: Fri, 18 Nov 1994 21:52:29 -0600 Organization: Bard 'O Matic Software In article <3ajpvj$49l@news.duke.edu>, tjb@acpub.duke.edu (Thomas J. Bryce) wrote: > It seems you can't rely on the memory to not be moved if you copy the > pointer from the handle and use it for a while, as in memcpy (*handle1, > *handle2,size); > > Could someone verify this for me? I'll verify it. :) You see, the whole idea of using handles is to let the ystem move memory around. That way you don't get a swiss-cheese looking memory map. Now, if for some reason you don't lock the handles, and then you try to copy.. the one you are copying to or from may move and then you are writting to or from some other place than you wanted to. Yuk. Lock your handles :) Wayde -- ===================================================================== --=The Bard=-- "Just remember, no matter where you go, there you are!" - ------------------------------------------------------------------- PGP Public Key available upon request +++++++++++++++++++++++++++ >From Jaeger@fquest.com (Brian Stern) Date: 19 Nov 1994 05:52:41 GMT Organization: The University of Texas at Austin, Austin, Texas In article <3ajpvj$49l@news.duke.edu>, tjb@acpub.duke.edu (Thomas J. Bryce) wrote: < I notice people usually surround a memcpy statement of a handle or < pointer with HLock and HUnlock. Is this necessary always? < < I'm inclined to believe, YES, but I'd like to hear it stated directly rather < than assuming it from seeing it done all the time. < < It seems you can't rely on the memory to not be moved if you copy the < pointer from the handle and use it for a while, as in memcpy (*handle1, < *handle2,size); < < Could someone verify this for me? < < Tom If the memcopy routine is in a non-resident segment then calling it could cause the segment to be loaded. I assume that it's in the ANSI lib. If you make sure that the segment containing ANSI is loaded before you call memcopy and is never unloaded then you're probably safe and don't need to lock the handle. I don't know how memcopy is implemented. It's probably a bytewise copy, something like *dest++ = *src++. Code like that won't cause memory to move. Many people would rather be safe than sorry. If other people are likely to use your code in other projects where ANSI may not be loaded and locked then you're better off locking the handle. Good luck, -- Brian Stern :-{)} Toolbox commando and Menu bard Jaeger@fquest.com +++++++++++++++++++++++++++ >From pgontier@novell.com (Pete Gontier) Date: Mon, 21 Nov 1994 12:29:07 -0700 Organization: Novell, Inc., Walnut Creek/Macintosh Site In article <3ajpvj$49l@news.duke.edu>, tjb@acpub.duke.edu (Thomas J. Bryce) wrote: > I notice people usually surround a memcpy statement of a handle or > pointer with HLock and HUnlock. Is this necessary always? Depends on what code segment 'memcpy' lives in. If it's in another segment, the handle might move when that segment is loaded. Since there isn't a good way to tell if 'memcpy' is in the same segement as the code calling it, 'HLock' is a good idea. I just call 'BlockMoveData'; it's a trap call, so no segment will load. The net savings are one, maybe two, trap calls over the usual 'HGetState'/'HLock'/'HUnlock' sequence, and 'BlockMoveData' is generally much faster for surprisingly small blocks. -- Views expressed here do not necessarily reflect those of my employer. --------------------------- End of C.S.M.P. Digest **********************