+ems_picture & ems_animation splitting as even C55 doesn't support IEI 0x14
authorshort <>
Wed, 16 Oct 2002 23:08:06 +0000 (23:08 +0000)
committershort <>
Wed, 16 Oct 2002 23:08:06 +0000 (23:08 +0000)
Fixed deconcatenation of udhpositioned data
Fixed bogus warning during deconcatenation

GSM/SMS/NBS/Message.pm

index ed6fbe3..665fe3b 100644 (file)
@@ -119,9 +119,10 @@ sub _ie_ems_picture {
        );
 }
 
-sub _ie_ems_animation {
-       my ($self, %args) = @_;
-       my $bitmaps = $args{"bitmaps"};  # list of GSM::SMS::Bitmap instances
+# @$bitmaps
+sub ems_animation_maxsize
+{
+my($bitmaps)=@_;
 
        if (4 != @$bitmaps) {
                carp "Invalid length of EMS animation (4 required)"; return ();
@@ -129,24 +130,31 @@ sub _ie_ems_animation {
        my $bitmap = $$bitmaps[0];
        my ($width, $height) = ($bitmap->{"width"}, $bitmap->{"height"});
        for my $testbitmap (@$bitmaps) {
-               if ($width != $testbitmap->{"width"} || $height != $testbitmap->{"height"}) {
-                       carp "Non-matching sizes in EMS animation";
+               $width =max($width ,$testbitmap->{"width" });
+               $height=max($height,$testbitmap->{"height"});
                }
-       }
+       return ($width,$height);
+}
+
+sub _ie_ems_animation {
+       my ($self, %args) = @_;
+       my $bitmaps = $args{"bitmaps"};  # list of GSM::SMS::Bitmap instances
+
+       my ($width, $height) = ems_animation_maxsize($bitmaps);
 
        my $iei;
-          if ($width ==  8 && $height ==  8) { $iei = IEI_ANIMATION_SMALL   ; }
-       elsif ($width == 16 && $height == 16) { $iei = IEI_ANIMATION_LARGE   ; }
+          if ($width <=  8 && $height <=  8) { $iei = IEI_ANIMATION_SMALL   ; }
+       elsif ($width <= 16 && $height <= 16) { $iei = IEI_ANIMATION_LARGE   ; }
        else {
                $iei = IEI_ANIMATION_LARGE;
-               carp "Invalid frame size of EMS animation (8x8 or 16x16 required)";
+               carp "Invalid frame size of EMS animation (<=16x<=16 required)";
        }
 
        return $self->_iebuilder($iei,
                        $args{TEXT_POSITION}, # position in the SMS
                        &{sub {
                                my @r=();
-                               for $bitmap (@$bitmaps) {
+                               for my $bitmap (@$bitmaps) {
                                        push @r,$bitmap->pixlist_horiz();
                                }
                                return @r;
@@ -185,7 +193,69 @@ sub _udh_build {
        my @list=map { &{"_ie_".$$_{"type"}}($self,%$_); } @srcs;
        use strict 'refs';
        return "" if !@list;
-       return pack "C*",scalar(@list),@list;
+       # if it is too long it will be recalculated anyway
+       return pack "C*",(@list<=0xFF ? scalar(@list) : 0xFF),@list;
+}
+
+sub udh_prepare_ems_picture
+{
+my($udh)=@_;
+
+       my $bitmap=$udh->{"bitmap"};  # GSM::SMS::Bitmap instance
+       $bitmap->crop(0xFF*8,0xFF);
+       my ($width, $height) = ($bitmap->{"width"}, $bitmap->{"height"});
+
+       # pixel-payload of concat8 SMS w/one IEI_PICTURE_VARIABLE is 129 bytes
+       my $stripe=int(129/int(($width+7)/8));
+       carp "Image width too big to fit in one SMS part" if $stripe<=0;        # ==0
+       return $udh if $stripe>=$height;
+       my @r=();
+       for (my $y=0;$y<$height;$y+=$stripe) {
+               push @r,{
+                               %$udh,
+                               "bitmap"=>GSM::SMS::Bitmap->new($bitmap,0,$y,$width,min($stripe,$height-$y)),
+                               };
+               }
+       return @r;
+}
+
+sub udh_prepare_ems_animation
+{
+my($udh)=@_;
+
+       my $bitmaps = $udh->{"bitmaps"};  # list of GSM::SMS::Bitmap instances
+       my ($width, $height) = ems_animation_maxsize($bitmaps);
+       return $udh if $width<=16 && $height<=16;
+
+       my @r=();
+       my $height_now;
+       # Here we can't touch the text and thus we do split to lines without
+       # giving there a newline! For proper way see &gsmcmd::ems_animation_send
+       for (my $y=0;$y<$height;$y+=$height_now) {
+               $height_now=($y+8>=$height ? 8 : 16);
+               my $width_now;
+               for (my $x=0;$x<$width;$x+=$width_now) {
+                       # Never risk undeterministic wrapping if some rows yet to follow
+                       # And we must be a square, not much other possibilies exist
+                       $width_now=$height_now;
+                       push @r,{
+                                       %$udh,
+                                       "bitmaps"=>[ map({
+                                                       GSM::SMS::Bitmap->new($_,$x,$y,$width_now,$height_now);
+                                                       } @$bitmaps) ],
+                                       };
+                       }
+               }
+       return @r;
+}
+
+sub udh_prepare
+{
+my($udh)=@_;
+
+       return udh_prepare_ems_picture($udh)   if $udh->{"type"} eq "ems_picture";
+       return udh_prepare_ems_animation($udh) if $udh->{"type"} eq "ems_animation";
+       return $udh;
 }
 
 # Create a message from a payload
@@ -200,6 +270,7 @@ sub _store_try {
        my $PDU = GSM::SMS::PDU->new();
 
        my @udhs=($args{"udh"} ? @{$args{"udh"}} : ());
+       @udhs=map({ udh_prepare($_); } @udhs);
 
        # We put ME-specific default if ANY element of UDH was specified
        # Autodetect $dcs BEFORE possible concatenation UDH IEs get inserted!
@@ -238,8 +309,9 @@ sub _store_try {
                        if (@udhpositioned && $udhpositioned[0]{TEXT_POSITION} <= $position) { # "<=" should be "=="
                                if (USERDATA_LENGTH < length($self->_udh_build(@udhstatic,@udhpositioned_now,$udhpositioned[0]))
                                                +nail_payload_len($dcs,length($payload_now))) {
+                                       return (DECONCAT_TOTAL, undef) if !$deconcat_ieref;
                                        return "UDH IE (User Data Header Information Element) too long to fit in one SMS fragment"
-                                                       if $payload_now eq "";
+                                                       if $payload_now eq "" && !@udhpositioned_now;
                                        last;
                                        }