/* AbiSource * * Copyright (C) 2005 Daniel d'Andrada T. de Carvalho * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ // Class definition include #include "ODi_Abi_Data.h" // AbiWord includes #include #include #include #include // External includes #include #include #include #include /** * Constructor */ ODi_Abi_Data::ODi_Abi_Data(PD_Document* pDocument, GsfInfile* pGsfInfile) : m_pAbiDocument (pDocument), m_pGsfInfile (pGsfInfile) { } /** * Adds an data item ( tag) in the AbiWord document for the specified image. * * Code mainly from Dom Lachowicz and/or Robert Staudinger. * * @param rDataId Receives the id that has been given to the added data item. * @param ppAtts The attributes of a element. */ void ODi_Abi_Data::addImageDataItem(UT_String& rDataId, const XML_Char** ppAtts) { const UT_UTF8String* pID; UT_Error error = UT_OK; const XML_Char* pHRef = UT_getAttribute ("xlink:href", ppAtts); UT_ByteBuf img_buf; GsfInfile* pPictures_dir; char* pMimetype; IE_ImpGraphic* pImporter = NULL; FG_Graphic* pFG = NULL; UT_ByteBuf* pPictData = NULL; UT_uint32 imageID; // If we have a string smaller then this we are in trouble. File corrupted? UT_ASSERT (strlen(pHRef) >= strlen("Pictures/a")); // The subdirectory that holds the picture. e.g: "ObjectReplacements" or "Pictures" UT_String dirName; // The file name of the picture. e.g.: "Object 1" or "10000201000000D100000108FF0E3707.png" UT_String fileName; UT_ASSERT(pHRef); pID = m_href_to_id[pHRef]; if (pID != NULL) { // This image was already added. // Use the existing data item id. rDataId = pID->utf8_str(); return; } // Get a new, unique, ID. imageID = m_pAbiDocument->getUID(UT_UniqueId::Image); UT_String_sprintf(rDataId, "%d", imageID); // Add this id to the list UT_ASSERT(m_href_to_id.ins(pHRef, rDataId.c_str()) == TRUE); _splitDirectoryAndFileName(pHRef, dirName, fileName); pPictures_dir = GSF_INFILE(gsf_infile_child_by_name(m_pGsfInfile, dirName.c_str())); // Loads img_buf error = _loadStream(pPictures_dir, fileName.c_str(), img_buf); g_object_unref (G_OBJECT (pPictures_dir)); if (error != UT_OK) { return; } // Builds pImporter from img_buf error = IE_ImpGraphic::constructImporter (&img_buf, IEGFT_Unknown, &pImporter); if ((error != UT_OK) || !pImporter) { goto Cleanup; } // Loads pFG error = pImporter->importGraphic(&img_buf, &pFG); if ((error != UT_OK) || !pFG) { // pictData is already freed in ~FG_Graphic goto Cleanup; } // Builds pPictData from pFG // TODO: can we get back a vector graphic? pPictData = static_cast(pFG)->getRaster_PNG(); if (!pPictData) { // i don't think that this could ever happen, but... UT_ASSERT(UT_SHOULD_NOT_HAPPEN); goto Cleanup; } // // Create the data item. // // the data item will free the token we passed (mime-type) pMimetype = UT_strdup ("image/png"); if (!m_pAbiDocument->createDataItem(rDataId.c_str(), false, pPictData, (void*)pMimetype, NULL)) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); FREEP(pMimetype); } Cleanup: DELETEP(pImporter); } /** * Code from Dom Lachowicz and/or Robert Staudinger. */ UT_Error ODi_Abi_Data::_loadStream (GsfInfile* oo, const char* stream, UT_ByteBuf& buf ) { guint8 const *data = NULL; size_t len = 0; static const size_t BUF_SZ = 4096; buf.truncate (0); GsfInput * input = gsf_infile_child_by_name(oo, stream); if (!input) return UT_ERROR; if (gsf_input_size (input) > 0) { while ((len = gsf_input_remaining (input)) > 0) { len = UT_MIN (len, BUF_SZ); if (NULL == (data = gsf_input_read (input, len, NULL))) { g_object_unref (G_OBJECT (input)); return UT_ERROR; } buf.append ((const UT_Byte *)data, len); } } g_object_unref (G_OBJECT (input)); return UT_OK; } /** * Takes a string like "./ObjectReplacements/Object 1" and split it into * subdirectory name ("ObjectReplacements") and file name ("Object 1"). */ void ODi_Abi_Data::_splitDirectoryAndFileName(const XML_Char* pHRef, UT_String& dirName, UT_String& fileName) const { UT_String href; UT_String str; int iStart, nChars, i, len; href = pHRef; //// // Get the directory name str = href.substr(0, 2); if (str == "./") { iStart = 2; } else { iStart = 0; } len = href.length(); for (i=iStart, nChars=0; i 0 && nChars < len); dirName = href.substr(iStart, nChars); //// // Get the file name iStart = iStart + nChars + 1; nChars = len - iStart; UT_ASSERT (nChars); // The file name must have at least one char. fileName = href.substr(iStart, nChars); }