1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <tools/stream.hxx>
22 #include <tools/zcodec.hxx>
23 #include "codec.hxx"
24 #include <memory>
25 
26 
GalleryCodec(SvStream & rIOStm)27 GalleryCodec::GalleryCodec( SvStream& rIOStm ) :
28     rStm( rIOStm )
29 {
30 }
31 
~GalleryCodec()32 GalleryCodec::~GalleryCodec()
33 {
34 }
35 
IsCoded(SvStream & rStm,sal_uInt32 & rVersion)36 bool GalleryCodec::IsCoded( SvStream& rStm, sal_uInt32& rVersion )
37 {
38     const sal_uInt64   nPos = rStm.Tell();
39     bool        bRet;
40     sal_uInt8       cByte1, cByte2, cByte3, cByte4, cByte5, cByte6;
41 
42     rStm.ReadUChar( cByte1 ).ReadUChar( cByte2 ).ReadUChar( cByte3 ).ReadUChar( cByte4 ).ReadUChar( cByte5 ).ReadUChar( cByte6 );
43 
44     if ( cByte1 == 'S' && cByte2 == 'V' && cByte3 == 'R' && cByte4 == 'L' && cByte5 == 'E' && ( cByte6 == '1' || cByte6 == '2' ) )
45     {
46         rVersion = ( ( cByte6 == '1' ) ? 1 : 2 );
47         bRet = true;
48     }
49     else
50     {
51         rVersion = 0;
52         bRet = false;
53     }
54 
55     rStm.Seek( nPos );
56 
57     return bRet;
58 }
59 
Write(SvStream & rStmToWrite)60 void GalleryCodec::Write( SvStream& rStmToWrite )
61 {
62     sal_uInt32 nPos, nCompSize;
63 
64     const sal_uInt32 nSize = rStmToWrite.TellEnd();
65     rStmToWrite.Seek( 0 );
66 
67     rStm.WriteChar( 'S' ).WriteChar( 'V' ).WriteChar( 'R' ).WriteChar( 'L' ).WriteChar( 'E' ).WriteChar( '2' );
68     rStm.WriteUInt32( nSize );
69 
70     nPos = rStm.Tell();
71     rStm.SeekRel( 4 );
72 
73     ZCodec aCodec;
74     aCodec.BeginCompression();
75     aCodec.Compress( rStmToWrite, rStm );
76     aCodec.EndCompression();
77 
78     nCompSize = rStm.Tell() - nPos - 4;
79     rStm.Seek( nPos );
80     rStm.WriteUInt32( nCompSize );
81     rStm.Seek( STREAM_SEEK_TO_END );
82 }
83 
Read(SvStream & rStmToRead)84 void GalleryCodec::Read( SvStream& rStmToRead )
85 {
86     sal_uInt32 nVersion = 0;
87 
88     if( !IsCoded( rStm, nVersion ) )
89         return;
90 
91     sal_uInt32  nCompressedSize, nUnCompressedSize;
92 
93     rStm.SeekRel( 6 );
94     rStm.ReadUInt32( nUnCompressedSize ).ReadUInt32( nCompressedSize );
95 
96     // decompress
97     if( 1 == nVersion )
98     {
99         std::unique_ptr<sal_uInt8[]> pCompressedBuffer(new sal_uInt8[ nCompressedSize ]);
100         rStm.ReadBytes(pCompressedBuffer.get(), nCompressedSize);
101         sal_uInt8*  pInBuf = pCompressedBuffer.get();
102         std::unique_ptr<sal_uInt8[]> pOutBuf(new sal_uInt8[ nUnCompressedSize ]);
103         sal_uInt8*  pTmpBuf = pOutBuf.get();
104         sal_uInt8*  pLast = pOutBuf.get() + nUnCompressedSize - 1;
105         sal_uIntPtr   nIndex = 0, nCountByte, nRunByte;
106         bool    bEndDecoding = false;
107 
108         do
109         {
110             nCountByte = *pInBuf++;
111 
112             if ( !nCountByte )
113             {
114                 nRunByte = *pInBuf++;
115 
116                 if ( nRunByte > 2 )
117                 {
118                     // filling absolutely
119                     memcpy( &pTmpBuf[ nIndex ], pInBuf, nRunByte );
120                     pInBuf += nRunByte;
121                     nIndex += nRunByte;
122 
123                     // note WORD alignment
124                     if ( nRunByte & 1 )
125                         pInBuf++;
126                 }
127                 else if ( nRunByte == 1 )   // End of the image
128                     bEndDecoding = true;
129             }
130             else
131             {
132                 const sal_uInt8 cVal = *pInBuf++;
133 
134                 memset( &pTmpBuf[ nIndex ], cVal, nCountByte );
135                 nIndex += nCountByte;
136             }
137         }
138         while ( !bEndDecoding && ( pTmpBuf <= pLast ) );
139 
140         rStmToRead.WriteBytes(pOutBuf.get(), nUnCompressedSize);
141     }
142     else if( 2 == nVersion )
143     {
144         ZCodec aCodec;
145 
146         aCodec.BeginCompression();
147         aCodec.Decompress( rStm, rStmToRead );
148         aCodec.EndCompression();
149     }
150 }
151 
152 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
153