Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / core / src / fxcodec / codec / fx_codec.cpp
index 456ec40..b2f70c7 100644 (file)
@@ -14,6 +14,10 @@ CCodec_ModuleMgr::CCodec_ModuleMgr()
     m_pJpxModule = FX_NEW CCodec_JpxModule;
     m_pJbig2Module = FX_NEW CCodec_Jbig2Module;
     m_pIccModule = FX_NEW CCodec_IccModule;
+    m_pPngModule = FX_NEW CCodec_PngModule;\r
+    m_pGifModule = FX_NEW CCodec_GifModule;\r
+    m_pBmpModule = FX_NEW CCodec_BmpModule;\r
+    m_pTiffModule = FX_NEW CCodec_TiffModule;\r
     m_pFlateModule = FX_NEW CCodec_FlateModule;
 }
 CCodec_ModuleMgr::~CCodec_ModuleMgr()
@@ -249,6 +253,343 @@ void CCodec_ModuleMgr::Destroy()
 {
     delete this;
 }
+CFX_DIBAttribute::CFX_DIBAttribute()\r
+{\r
+    FXSYS_memset32(this, 0, sizeof(CFX_DIBAttribute));\r
+    m_nXDPI = -1;\r
+    m_nYDPI = -1;\r
+    m_fAspectRatio = -1.0f;\r
+    m_pExif = FX_NEW CFX_DIBAttributeExif;\r
+}\r
+CFX_DIBAttribute::~CFX_DIBAttribute()\r
+{\r
+    if (m_pExif) {\r
+        delete m_pExif;\r
+    }\r
+}\r
+CFX_DIBAttributeExif::CFX_DIBAttributeExif()\r
+{\r
+    m_pExifData = NULL;\r
+    m_dwExifDataLen = 0;\r
+}\r
+CFX_DIBAttributeExif::~CFX_DIBAttributeExif()\r
+{\r
+    clear();\r
+}\r
+void CFX_DIBAttributeExif::clear()\r
+{\r
+    if (m_pExifData) {\r
+        FX_Free(m_pExifData);\r
+    }\r
+    m_pExifData = NULL;\r
+    FX_DWORD key = 0;\r
+    FX_LPBYTE buf = NULL;\r
+    FX_POSITION pos = NULL;\r
+    pos = m_TagHead.GetStartPosition();\r
+    while (pos) {\r
+        m_TagHead.GetNextAssoc(pos, key, buf);\r
+        if (buf) {\r
+            FX_Free(buf);\r
+        }\r
+    }\r
+    m_TagHead.RemoveAll();\r
+    pos = m_TagVal.GetStartPosition();\r
+    while (pos) {\r
+        m_TagVal.GetNextAssoc(pos, key, buf);\r
+        if (buf) {\r
+            FX_Free(buf);\r
+        }\r
+    }\r
+    m_TagVal.RemoveAll();\r
+}\r
+static FX_WORD _Read2BytesL(FX_LPBYTE data)\r
+{\r
+    ASSERT(data);\r
+    return data[0] | (data[1] << 8);\r
+}\r
+static FX_WORD _Read2BytesB(FX_LPBYTE data)\r
+{\r
+    ASSERT(data);\r
+    return data[1] | (data[0] << 8);\r
+}\r
+static FX_DWORD _Read4BytesL(FX_LPBYTE data)\r
+{\r
+    return _Read2BytesL(data) | (_Read2BytesL(data + 2) << 16);\r
+}\r
+static FX_DWORD _Read4BytesB(FX_LPBYTE data)\r
+{\r
+    return _Read2BytesB(data + 2) | (_Read2BytesB(data) << 16);\r
+}\r
+typedef FX_WORD (*_Read2Bytes) (FX_LPBYTE data);\r
+typedef FX_DWORD (*_Read4Bytes) (FX_LPBYTE data);\r
+typedef void (*_Write2Bytes) (FX_LPBYTE data, FX_WORD val);\r
+typedef void (*_Write4Bytes) (FX_LPBYTE data, FX_DWORD val);\r
+FX_LPBYTE CFX_DIBAttributeExif::ParseExifIFH(FX_LPBYTE data, FX_DWORD len, _Read2Bytes* pReadWord, _Read4Bytes* pReadDword)\r
+{\r
+    if (len > 8) {\r
+        FX_BOOL tag = FALSE;\r
+        if (FXSYS_memcmp32(data, "\x49\x49\x2a\x00", 4) == 0) {\r
+            if (pReadWord) {\r
+                *pReadWord = _Read2BytesL;\r
+            }\r
+            if (pReadDword) {\r
+                *pReadDword = _Read4BytesL;\r
+            }\r
+            tag = TRUE;\r
+        } else if (FXSYS_memcmp32(data, "\x4d\x4d\x00\x2a", 4) == 0) {\r
+            if (pReadWord) {\r
+                *pReadWord = _Read2BytesB;\r
+            }\r
+            if (pReadDword) {\r
+                *pReadDword = _Read4BytesB;\r
+            }\r
+            tag = TRUE;\r
+        }\r
+        if (tag) {\r
+            data += 4;\r
+            if (pReadDword) {\r
+                data += (*pReadDword)(data) - 4;\r
+            } else {\r
+                data += 4;\r
+            }\r
+        }\r
+    }\r
+    return data;\r
+}\r
+FX_BOOL CFX_DIBAttributeExif::ParseExifIFD(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pMap, FX_LPBYTE data, FX_DWORD len)\r
+{\r
+    if (pMap && data) {\r
+        if (len > 8) {\r
+            FX_WORD wTagNum = m_readWord(data);\r
+            data += 2;\r
+            FX_DWORD wTag;\r
+            FX_LPBYTE buf;\r
+            while (wTagNum--) {\r
+                wTag = m_readWord(data);\r
+                data += 2;\r
+                if (!pMap->Lookup(wTag, buf)) {\r
+                    buf = FX_Alloc(FX_BYTE, 10);\r
+                    if (buf == NULL) {\r
+                        return FALSE;\r
+                    }\r
+                    FXSYS_memcpy32(buf, data, 10);\r
+                    pMap->SetAt(wTag, buf);\r
+                }\r
+                data += 10;\r
+            }\r
+            FX_DWORD dwIFDOffset;\r
+            dwIFDOffset = m_readDword(data);\r
+            while (dwIFDOffset && dwIFDOffset < len) {\r
+                data = m_pExifData + dwIFDOffset;\r
+                wTagNum = m_readWord(data);\r
+                data += 2;\r
+                while (wTagNum--) {\r
+                    wTag = m_readWord(data);\r
+                    data += 2;\r
+                    if (!pMap->Lookup(wTag, buf)) {\r
+                        buf = FX_Alloc(FX_BYTE, 10);\r
+                        if (buf == NULL) {\r
+                            return FALSE;\r
+                        }\r
+                        FXSYS_memcpy32(buf, data, 10);\r
+                        pMap->SetAt(wTag, buf);\r
+                    }\r
+                    data += 10;\r
+                }\r
+                dwIFDOffset = m_readDword(data);\r
+            }\r
+            return TRUE;\r
+        }\r
+    }\r
+    return FALSE;\r
+}\r
+enum FX_ExifDataType {\r
+    FX_UnsignedByte = 1,\r
+    FX_AscString,\r
+    FX_UnsignedShort,\r
+    FX_UnsignedLong,\r
+    FX_UnsignedRation,\r
+    FX_SignedByte,\r
+    FX_Undefined,\r
+    FX_SignedShort,\r
+    FX_SignedLong,\r
+    FX_SignedRation,\r
+    FX_SignedFloat,\r
+    FX_DoubleFloat\r
+};\r
+FX_BOOL CFX_DIBAttributeExif::ParseExif(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pHead, FX_LPBYTE data, FX_DWORD len, CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pVal)\r
+{\r
+    if (pHead && data && pVal) {\r
+        if (len > 8) {\r
+            FX_LPBYTE old_data = data;\r
+            data = ParseExifIFH(data, len, &m_readWord, &m_readDword);\r
+            if (data == old_data) {\r
+                return FALSE;\r
+            }\r
+            if (pHead->GetCount() == 0) {\r
+                if (!ParseExifIFD(pHead, data, len)) {\r
+                    return FALSE;\r
+                }\r
+            }\r
+            FX_DWORD dwModuleNum;\r
+            FX_WORD type;\r
+            FX_DWORD dwSize;\r
+            FX_DWORD tag;\r
+            FX_LPBYTE head;\r
+            FX_POSITION pos = pHead->GetStartPosition();\r
+            while (pos) {\r
+                pHead->GetNextAssoc(pos, tag, head);\r
+                FX_LPBYTE val = NULL, buf = NULL, temp = NULL;\r
+                int i;\r
+                if (head) {\r
+                    type = m_readWord(head);\r
+                    head += 2;\r
+                    dwModuleNum = m_readDword(head);\r
+                    head += 4;\r
+                    switch (type) {\r
+                        case FX_UnsignedByte:\r
+                        case FX_AscString:\r
+                        case FX_SignedByte:\r
+                        case FX_Undefined:\r
+                            dwSize = dwModuleNum;\r
+                            val = FX_Alloc(FX_BYTE, dwSize);\r
+                            if (val == NULL) {\r
+                                return FALSE;\r
+                            }\r
+                            if (dwSize > 4) {\r
+                                FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);\r
+                            } else {\r
+                                FXSYS_memcpy32(val, head, dwSize);\r
+                            }\r
+                            break;\r
+                        case FX_UnsignedShort:\r
+                        case FX_SignedShort:\r
+                            dwSize = dwModuleNum << 1;\r
+                            val = FX_Alloc(FX_BYTE, dwSize);\r
+                            if (val == NULL) {\r
+                                return FALSE;\r
+                            }\r
+                            if (dwSize > 4) {\r
+                                FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);\r
+                            } else {\r
+                                FXSYS_memcpy32(val, head, dwSize);\r
+                            }\r
+                            buf = val;\r
+                            for(i = 0; i < (int)dwModuleNum; i ++) {\r
+                                *(FX_WORD*)buf = m_readWord(buf);\r
+                                buf += 2;\r
+                            }\r
+                            break;\r
+                        case FX_UnsignedLong:\r
+                        case FX_SignedLong:\r
+                        case FX_SignedFloat:\r
+                            dwSize = dwModuleNum << 2;\r
+                            val = FX_Alloc(FX_BYTE, dwSize);\r
+                            if (val == NULL) {\r
+                                return FALSE;\r
+                            }\r
+                            if (dwSize > 4) {\r
+                                FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);\r
+                            } else {\r
+                                FXSYS_memcpy32(val, head, dwSize);\r
+                            }\r
+                            buf = val;\r
+                            for(i = 0; i < (int)dwModuleNum; i ++) {\r
+                                *(FX_DWORD*)buf = m_readDword(buf);\r
+                                buf += 4;\r
+                            }\r
+                            break;\r
+                        case FX_UnsignedRation:\r
+                        case FX_SignedRation: {\r
+                                dwSize = dwModuleNum << 3;\r
+                                buf = FX_Alloc(FX_BYTE, dwSize);\r
+                                if (buf == NULL) {\r
+                                    return FALSE;\r
+                                }\r
+                                if (dwSize > 4) {\r
+                                    FXSYS_memcpy32(buf, old_data + m_readDword(head), dwSize);\r
+                                } else {\r
+                                    FXSYS_memcpy32(buf, head, dwSize);\r
+                                }\r
+                                temp = buf;\r
+                                val = FX_Alloc(FX_BYTE, dwSize / 2);\r
+                                if (val == NULL) {\r
+                                    FX_Free(buf);\r
+                                    return FALSE;\r
+                                }\r
+                                for(i = 0; i < (int)dwModuleNum; i ++) {\r
+                                    *(FX_DWORD*)temp = m_readDword(temp);\r
+                                    *(FX_DWORD*)(temp + 4) = m_readDword(temp + 4);\r
+                                    FX_DWORD* lNumerator = (FX_DWORD*)temp;\r
+                                    FX_DWORD* lNenominator = (FX_DWORD*)(temp + 4);\r
+                                    *(FX_FLOAT*)(val + i * 4) = (FX_FLOAT)(*lNumerator) / (FX_FLOAT)(*lNenominator);\r
+                                    temp += 8;\r
+                                }\r
+                                FX_Free(buf);\r
+                            }\r
+                            break;\r
+                        case FX_DoubleFloat:\r
+                            dwSize = dwModuleNum << 3;\r
+                            val = FX_Alloc(FX_BYTE, dwSize);\r
+                            if (val == NULL) {\r
+                                return FALSE;\r
+                            }\r
+                            if (dwSize > 4) {\r
+                                FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);\r
+                            } else {\r
+                                FXSYS_memcpy32(val, head, dwSize);\r
+                            }\r
+                            buf = val;\r
+                            for(i = 0; i < (int)dwModuleNum; i ++) {\r
+                                *(FX_DWORD*)buf = m_readDword(buf);\r
+                                *(FX_DWORD*)(buf + 4) = m_readDword(buf + 4);\r
+                                buf += 8;\r
+                            }\r
+                            break;\r
+                        default:\r
+                            return FALSE;\r
+                    }\r
+                }\r
+                pVal->SetAt(tag, val);\r
+            }\r
+            return TRUE;\r
+        }\r
+    }\r
+    return FALSE;\r
+}\r
+#define FXEXIF_INFOCONVERT(T) {T* src = (T*)ptr;       T* dst = (T*)val;       *dst = *src;}\r
+FX_BOOL CFX_DIBAttributeExif::GetInfo( FX_WORD tag, FX_LPVOID val )\r
+{\r
+    if (m_TagVal.GetCount() == 0) {\r
+        if (!ParseExif(&m_TagHead, m_pExifData, m_dwExifDataLen, &m_TagVal)) {\r
+            return FALSE;\r
+        }\r
+    }\r
+    FX_LPBYTE ptr = NULL;\r
+    if (m_TagVal.Lookup(tag, ptr)) {\r
+        switch (tag) {\r
+            case EXIFTAG_USHORT_RESUNIT:\r
+                FXEXIF_INFOCONVERT(FX_WORD);\r
+                {\r
+                    FX_WORD* ptr = (FX_WORD*)val;\r
+                    *ptr -= 1;\r
+                }\r
+                break;\r
+            case EXIFTAG_FLOAT_DPIX:\r
+            case EXIFTAG_FLOAT_DPIY:\r
+                FXEXIF_INFOCONVERT(FX_FLOAT);\r
+                break;\r
+            case EXIFTAG_USHORT_ORIENTATION:\r
+                FXEXIF_INFOCONVERT(FX_WORD);\r
+                break;\r
+            default: {\r
+                    FX_LPBYTE* dst = (FX_LPBYTE*)val;\r
+                    *dst = ptr;\r
+                }\r
+        }\r
+    }\r
+    return TRUE;\r
+}\r
 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
 {
 public: