Merge pull request #4927 from mkortstiege/masterprompt
[vuplus_xbmc] / tools / TexturePacker / XBTFWriter.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "XBTFWriter.h"
22 #define __STDC_FORMAT_MACROS
23 #include <inttypes.h>
24 #include "guilib/XBTF.h"
25 #include "utils/EndianSwap.h"
26 #if defined(TARGET_FREEBSD) || defined(TARGET_DARWIN)
27 #include <stdlib.h>
28 #elif !defined(TARGET_DARWIN)
29 #include <malloc.h>
30 #endif
31 #include <memory.h>
32
33 #define WRITE_STR(str, size, file) fwrite(str, size, 1, file)
34 #define WRITE_U32(i, file) { uint32_t _n = Endian_SwapLE32(i); fwrite(&_n, 4, 1, file); }
35 #define WRITE_U64(i, file) { uint64_t _n = i; _n = Endian_SwapLE64(i); fwrite(&_n, 8, 1, file); }
36
37 CXBTFWriter::CXBTFWriter(CXBTF& xbtf, const std::string& outputFile) : m_xbtf(xbtf)
38 {
39   m_outputFile = outputFile;
40   m_file = NULL;
41   m_data = NULL;
42   m_size = 0;
43 }
44
45 bool CXBTFWriter::Create()
46 {
47   m_file = fopen(m_outputFile.c_str(), "wb");
48   if (m_file == NULL)
49   {
50     return false;
51   }
52
53   return true;
54 }
55
56 bool CXBTFWriter::Close()
57 {
58   if (m_file == NULL || m_data == NULL)
59   {
60     return false;
61   }
62
63   fwrite(m_data, 1, m_size, m_file);
64
65   Cleanup();
66
67   return true;
68 }
69
70 void CXBTFWriter::Cleanup()
71 {
72   free(m_data);
73   m_data = NULL;
74   m_size = 0;
75   if (m_file)
76   {
77     fclose(m_file);
78     m_file = NULL;
79   }
80 }
81
82 bool CXBTFWriter::AppendContent(unsigned char const* data, size_t length)
83 {
84   unsigned char *new_data = (unsigned char *)realloc(m_data, m_size + length);
85
86   if (new_data == NULL)
87   { // OOM - cleanup and fail
88     Cleanup();
89     return false;
90   }
91
92   m_data = new_data;
93
94   memcpy(m_data + m_size, data, length);
95   m_size += length;
96
97   return true;
98 }
99
100 bool CXBTFWriter::UpdateHeader(const std::vector<unsigned int>& dupes)
101 {
102   if (m_file == NULL)
103   {
104     return false;
105   }
106
107   uint64_t offset = m_xbtf.GetHeaderSize();
108
109   WRITE_STR(XBTF_MAGIC, 4, m_file);
110   WRITE_STR(XBTF_VERSION, 1, m_file);
111
112   std::vector<CXBTFFile>& files = m_xbtf.GetFiles();
113   WRITE_U32(files.size(), m_file);
114   for (size_t i = 0; i < files.size(); i++)
115   {
116     CXBTFFile& file = files[i];
117
118     // Convert path to lower case
119     char* ch = file.GetPath();
120     while (*ch)
121     {
122       *ch = tolower(*ch);
123       ch++;
124     }
125
126     WRITE_STR(file.GetPath(), 256, m_file);
127     WRITE_U32(file.GetLoop(), m_file);
128
129     std::vector<CXBTFFrame>& frames = file.GetFrames();
130     WRITE_U32(frames.size(), m_file);
131     for (size_t j = 0; j < frames.size(); j++)
132     {
133       CXBTFFrame& frame = frames[j];
134       if (dupes[i] != i)
135         frame.SetOffset(files[dupes[i]].GetFrames()[j].GetOffset());
136       else
137       {
138         frame.SetOffset(offset);
139         offset += frame.GetPackedSize();
140       }
141
142       WRITE_U32(frame.GetWidth(), m_file);
143       WRITE_U32(frame.GetHeight(), m_file);
144       WRITE_U32(frame.GetFormat(true), m_file);
145       WRITE_U64(frame.GetPackedSize(), m_file);
146       WRITE_U64(frame.GetUnpackedSize(), m_file);
147       WRITE_U32(frame.GetDuration(), m_file);
148       WRITE_U64(frame.GetOffset(), m_file);
149     }
150   }
151
152   // Sanity check
153   int64_t pos = ftell(m_file);
154   if (pos != (int64_t)m_xbtf.GetHeaderSize())
155   {
156     printf("Expected header size (%" PRId64 ") != actual size (%" PRId64 ")\n", m_xbtf.GetHeaderSize(), pos);
157     return false;
158   }
159
160   return true;
161 }