home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / Non-RPC / !Perl / riscos / RISCOS / DrawFile / Object.pm < prev    next >
Text File  |  1999-01-20  |  10KB  |  326 lines

  1. package RISCOS::DrawFile::Object;
  2.  
  3. require RISCOS::DrawFile::Common;
  4.  
  5. use strict;
  6. use vars qw ($VERSION @ISA);
  7.  
  8. $VERSION = 0.04;
  9. @ISA = 'RISCOS::DrawFile::Common';
  10.  
  11. ### use SelfLoader;
  12. sub RISCOS::DrawFile::Object::new ($);
  13. sub RISCOS::DrawFile::Object::PrePack ;
  14. sub RISCOS::DrawFile::Object::Layer ($);
  15. sub RISCOS::DrawFile::Object::PackType ;
  16. sub RISCOS::DrawFile::Object::PackTypeSizeBBox ;
  17. sub RISCOS::DrawFile::Object::Type ;
  18. sub RISCOS::DrawFile::Object::Write ;
  19. 1;
  20. ### __DATA__
  21. # 0.02 does copy constructors.
  22. # 0.03 PrePack does BBox not BBoxCalc
  23. # 0.04 SelfLoader
  24.  
  25. sub new ($) {
  26.     my $proto = shift;
  27.     my $class = ref($proto) || $proto;
  28.  
  29.     my ($self, $type) = ({});
  30.     # It is defined and it is not a reference to something.
  31.     if (defined $_[0]) {
  32.     unless (ref $_[0]) {
  33.         $type = unpack ('I', $_[0])
  34.     } elsif (ref ($_[0]) eq $class) {
  35.         return [$_[0]->Clone()];    # All done
  36.     }
  37.     }
  38.  
  39.     if (defined $_[1]) {
  40.     my ($split, $spare);
  41.     if (ref $_[1] eq 'ARRAY') {
  42.         $split = $_[1];
  43.     } elsif (ref $_[1] eq 'CODE' && defined $type) {
  44.         # Call the bit of code, which will return an array.
  45.         $split = [&{$_[1]} ($type)];
  46.     } else {
  47.         $split = [];
  48.     }
  49.     ($type, $self->{'__LAYER'}, $self->{'__FLAGS'}, $spare) = @$split;
  50.     if ($spare) {
  51.         warn "Reserved type byte is $spare (expected 0) in object type $type"
  52.           if $^W;
  53.     }
  54.     $self->{'__SPARE'} = $spare;
  55.     }
  56.  
  57.     bless ($self, $class);
  58.     wantarray ? ($self, $type) : $self;
  59. }
  60.  
  61. # Mostly for the fonttable object to ennumerate fonts.
  62. # Text objects should push fontnames into the hashref in $_[0]
  63. sub PrePack {
  64.     my $self = shift;
  65.     $self->BBox (@_);
  66. }
  67.  
  68. sub Layer ($) {
  69.     my $self = shift;
  70.     my $layer = $self->{'__LAYER'};
  71.     $self->{'__LAYER'} = $_[0] if @_;
  72.     $layer;
  73. }
  74.  
  75. sub PackType {
  76.     my $self = shift;
  77.     my $type = defined $_[0] ? $_[0] : $self->{'__TYPE'};
  78.     return pack 'I', $type
  79.       unless defined $self->{'__LAYER'};
  80.     pack ('C4', $type, $self->{'__LAYER'}, $self->{'__FLAGS'},
  81.       $self->{'__SPARE'} | 0);
  82. }
  83.  
  84. sub PackTypeSizeBBox {
  85.     my $self = shift;
  86.     my $type = shift;
  87.     my $size = shift;
  88.     my $bbox;
  89.     if (defined ($_[0])) {
  90.     $bbox = pack 'i4', (ref $_[0] ? @{$_[0]} : @_);
  91.     } else {
  92.     # Need to cope with BBox returning undef or 0 (eg empty path objects)
  93.     $bbox = $self->BBox();
  94.     $bbox = $bbox ? pack 'i4', @$bbox
  95.               : pack 'x16';
  96.     # Can't combine the x16 template, as @{undef} is not ();
  97.     }
  98.     $self->PackType($type) . pack ('I', (defined $size ? $size
  99.                                : $self->Size()))
  100.                . $bbox;
  101. }
  102.  
  103. sub Type {
  104.     my $self = shift;
  105.     $self->{'__TYPE'};
  106. }
  107.  
  108. sub Write {
  109.     my $self = shift;
  110.     print {$_[0]} $self->Pack (@_);
  111. }
  112.  
  113. # The extended tag is described by the following structure:
  114. #
  115. # typedef unsigned char draw_tagtyp;
  116. # typedef unsigned char draw_layer;
  117. # typedef unsigned char draw_objflags;
  118. #
  119. # struct draw_extag            /* Extended object tag */
  120. # {
  121. #    draw_tagtyp tag;        /* Basic object type */
  122. #    draw_layer layer;        /* Object layer, 0 to 31 */
  123. #    draw_objflags flag;        /* Object flags */
  124. #    unsigned char spare;        /* For future expansion */
  125. # };
  126. #
  127. # The following bits in flag are used at present:
  128. #
  129. # #define flag_NODISPLAY        1    /* Never displayed */
  130. # #define flag_LOCKED        2    /* Object is locked */
  131. # #define flag_HIDDEN        4    /* Temporarily hidden */
  132.  
  133. 1;
  134. __END__
  135.  
  136. =head1 NAME
  137.  
  138. RISCOS::DrawFile::Object
  139.  
  140. =head1 SYNOPSIS
  141.  
  142. Abstract base class for DrawFile objects.
  143.  
  144. =head1 DESCRIPTION
  145.  
  146. C<RISCOS::DrawFile::Object> provdes an abstract base class for DrawFile objects
  147. to inherit from. It provides various methods, some of which are inherited from
  148. C<RISCOS::DrawFile::Common> and hence are also can be used on entire DrawFiles.
  149. See C<L<RISCOS::DrawFile::OpaqueObject>> for a minimal usable implementation of
  150. a DrawFile object.
  151.  
  152. =head2 Methods
  153.  
  154. =over 4
  155.  
  156. =item new <data>, [<split function>, ...]
  157.  
  158. Create a new DrawFile object. If C<data> is not a reference it is assumed to be
  159. packed data, and the first 4 bytes are interpreted as an integer to get the
  160. object type. If a second argument is provided, a reference to code is assumed
  161. to be a split function with the same interface as drawplus_split_type, and will
  162. be called to split the extended object tag. If the second argument is a
  163. reference to an array it is assumed to give (type, layer, flags, spare), and
  164. these values are used in place of any derived from the first 4 bytes.
  165.  
  166. If I<data> is a reference to an object of the same class as the new object will
  167. become then it is C<Clone()>ed and a list containing the clone returned. This
  168. allows all derived classes to easily implement a copy constructor.
  169.  
  170. In scalar context C<new> returns a blessed reference to the new object. In
  171. array context C<new> returns a list (object, type, fonttable). I<object> can be
  172. a reference to a list of objects, and I<fonttable> is normally C<undef>. See
  173. C<RISCOS::DrawFile::FontTable> for the procedure to return a fonttable if found.
  174.  
  175. Subclasses are expected to treat I<data> as based on its type. If a subclass
  176. recieves a reference to a list rather than a single blessed reference then it
  177. should return immediately with that list, as C<new> has been used as a copy
  178. constructor.
  179.  
  180. =over 4
  181.  
  182. =item scalar
  183.  
  184. raw bytes from a DrawFile
  185.  
  186. =item scalar reference
  187.  
  188. raw bytes from a DrawFile, with type, length and bounding box stripped
  189.  
  190. =item array reference
  191.  
  192. object dependent list of parameters to construct a new object
  193.  
  194. =back
  195.  
  196. If a second argument is proviced C<new> sets the Layer, Flags and Spare members
  197. of the object to the supplied/split values. C<new> B<never> sets the Type member
  198. of the object - it is the responsibility of the derived class to store the Type
  199. member as if it needs to retain this information.
  200.  
  201. =item PrePack <hash_reference>
  202.  
  203. is provided as a hook to perform calculations immediately before saving a
  204. DrawFile. The hash reference is used to store the names of fonts needed in the
  205. FontTable, keys are font names, values the number of text objects that use that
  206. font (see C<PrePack> in C<RISCOS::DrawFile::Text> if you really must
  207. know). The default C<PrePack> calls C<BBox> and returns this value. This ensures
  208. that if any objects have been changed then their containing groups' bounding
  209. boxes will be upadated to reflect this. Derived classes should maintain this
  210. behaviour.
  211.  
  212. =item Type
  213.  
  214. returns the objects type. The default method looks in 'C<__TYPE>', which relies
  215. on the derived class storing it there. If your derived class does not need to
  216. store the Type you B<must> override this method, typically with something like
  217.  
  218.     sub Type { 2; }
  219.  
  220. Most classes don't need to store the type, as most classes deal with only one
  221. type of object. Exceptions include C<OpaqueObject>, which stores all unknown
  222. object types, and C<Text>, which implements normal text (type 1) and
  223. transformed text (type 12).
  224.  
  225. =item Layer [<new_layer>]
  226.  
  227. returns the current layer. If an argument is provided it is used to set the
  228. ojbects layer, and the old layer is returned.
  229.  
  230. =item PackType [<type>]
  231.  
  232. packs the object's tag (type) into a 4 byte string. If the object has a layer
  233. defined then DrawPlus extended tag format is used.
  234.  
  235. The tag is taken from the first argument if supplied, else it is looked up as
  236. 'C<__TYPE>'. Note that C<new> in C<RISCOS::DrawFile::Object> does not set
  237. '<__TYPE>', instead returning the value to the derived class.
  238.  
  239. =item PackTypeSizeBBox <tag>, <size>, <bounding_box>
  240.  
  241. returns a 24 byte string for the header common to all DrawFile objects
  242. (apart from FontTables).
  243.  
  244. I<type> is passed to C<PackType> and the method C<Size> is called if I<size> is
  245. undefined. If I<bounding_box> is defined then the object bounding box is taken
  246. from it - if I<bounding_box> is an array reference should point to 4 values,
  247. otherwise arguments three to six are taken to be the bounding box. If
  248. I<bounding_box> is undefined then the method C<BBox> is called, and (0,0,0,0)
  249. used if this returns C<undef>.
  250.  
  251. Usually C<PackTypeSizeBBox> can be called with B<no> arguments and it will do
  252. the right thing.
  253.  
  254. =item Write <filehandle>, <fonttable>, ...
  255.  
  256. writes the object to the given filehandle. The default implementation C<print>s
  257. the result of calling C<Pack> with the remainder of the argument list. C<Write>
  258. should return true unless there was an error.
  259.  
  260. =back
  261.  
  262. =head2 Methods supplied by C<RISCOS::DrawFile::Common>
  263.  
  264. =over 4
  265.  
  266. =item Clone
  267.  
  268. returns a copy of this object.
  269.  
  270. =item BBox
  271.  
  272. returns a reference to an array giving the bounding box, or C<undef> if there is
  273. is no bounding box for this object (I<i.e.> font tables, empty paths, option
  274. objects). Note that option objects and empty paths store a bounding box of
  275. (0,0,0,0) when saved. C<BBox> will attempt to call C<BBox_Calc> (which the
  276. derived class B<must> provide) if the bounding box is currently unknown.
  277.  
  278. As the returned array reference B<is> the internal copy of the bounding box it
  279. must not be modified.
  280.  
  281. =item Inside <bbox>
  282.  
  283. =item InsideOrTouching <bbox>
  284.  
  285. =item Intersect <bbox>
  286.  
  287. =item IntersectOrTouching <bbox>
  288.  
  289. =item Outside <bbox>
  290.  
  291. return a reference to the object if it has the correct relationship with the
  292. bounding box (passed as an array reference), C<undef> if it does not.
  293.  
  294. =back
  295.  
  296. =head2 Methods derived classes must supply
  297.  
  298. In addition to the overriding above methods where appropriate (in particular
  299. C<Type>) derived classes must provide the following methods
  300.  
  301. =over 4
  302.  
  303. =item BBox_Calc
  304.  
  305. (re)calculates the bounding box, returning a reference to an array, or undef if
  306. there is no bounding box. As it has no idea about the data it contains
  307. C<OpaqueObject> simply returns the bounding box it was given when it was called.
  308.  
  309. =item Size
  310.  
  311. returns the size of the object when saved in a DrawFile
  312.  
  313. =item Pack <undef>, fonttable, ...
  314.  
  315. returns a scalar containing the object packed ready to save into a DrawFile.
  316.  
  317. =back
  318.  
  319. =head1 BUGS
  320.  
  321. Not tested enough.
  322.  
  323. =head1 AUTHOR
  324.  
  325. Nicholas Clark <F<nick@unfortu.net>>
  326.