Home | History | Annotate | Download | only in parser
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_utils.h"
      9 #include "xfa/src/fxfa/src/common/xfa_object.h"
     10 #include "xfa/src/fxfa/src/common/xfa_document.h"
     11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
     12 #include "xfa/src/fxfa/src/common/xfa_script.h"
     13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
     14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
     15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
     16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
     17 #include "xfa_basic_imp.h"
     18 extern const XFA_PACKETINFO g_XFAPacketData[];
     19 extern const int32_t g_iXFAPacketCount;
     20 extern const XFA_ATTRIBUTEENUMINFO g_XFAEnumData[];
     21 extern const int32_t g_iXFAEnumCount;
     22 extern const XFA_ATTRIBUTEINFO g_XFAAttributeData[];
     23 extern const int32_t g_iXFAAttributeCount;
     24 extern const XFA_ELEMENTINFO g_XFAElementData[];
     25 extern const int32_t g_iXFAElementCount;
     26 extern const XFA_ELEMENTHIERARCHY g_XFAElementChildrenIndex[];
     27 extern const FX_WORD g_XFAElementChildrenData[];
     28 extern const XFA_ELEMENTHIERARCHY g_XFAElementAttributeIndex[];
     29 extern const uint8_t g_XFAElementAttributeData[];
     30 extern const XFA_NOTSUREATTRIBUTE g_XFANotsureAttributes[];
     31 extern const int32_t g_iXFANotsureCount;
     32 extern const XFA_ELEMENTHIERARCHY g_XFAElementPropertyIndex[];
     33 extern const XFA_PROPERTY g_XFAElementPropertyData[];
     34 extern const XFA_SCRIPTHIERARCHY g_XFAScriptIndex[];
     35 extern const XFA_METHODINFO g_SomMethodData[];
     36 extern const int32_t g_iSomMethodCount;
     37 extern const XFA_SCRIPTATTRIBUTEINFO g_SomAttributeData[];
     38 extern const int32_t g_iSomAttributeCount;
     39 XFA_LPCPACKETINFO XFA_GetPacketByName(const CFX_WideStringC& wsName) {
     40   int32_t iLength = wsName.GetLength();
     41   if (iLength == 0) {
     42     return NULL;
     43   }
     44   uint32_t uHash = FX_HashCode_String_GetW(wsName.GetPtr(), iLength);
     45   int32_t iStart = 0, iEnd = g_iXFAPacketCount - 1;
     46   do {
     47     int32_t iMid = (iStart + iEnd) / 2;
     48     XFA_LPCPACKETINFO pInfo = g_XFAPacketData + iMid;
     49     if (uHash == pInfo->uHash) {
     50       return pInfo;
     51     } else if (uHash < pInfo->uHash) {
     52       iEnd = iMid - 1;
     53     } else {
     54       iStart = iMid + 1;
     55     }
     56   } while (iStart <= iEnd);
     57   return NULL;
     58 }
     59 XFA_LPCPACKETINFO XFA_GetPacketByID(FX_DWORD dwPacket) {
     60   int32_t iStart = 0, iEnd = g_iXFAPacketCount - 1;
     61   do {
     62     int32_t iMid = (iStart + iEnd) / 2;
     63     FX_DWORD dwFind = (g_XFAPacketData + iMid)->eName;
     64     if (dwPacket == dwFind) {
     65       return g_XFAPacketData + iMid;
     66     } else if (dwPacket < dwFind) {
     67       iEnd = iMid - 1;
     68     } else {
     69       iStart = iMid + 1;
     70     }
     71   } while (iStart <= iEnd);
     72   return NULL;
     73 }
     74 XFA_LPCATTRIBUTEENUMINFO XFA_GetAttributeEnumByName(
     75     const CFX_WideStringC& wsName) {
     76   int32_t iLength = wsName.GetLength();
     77   if (iLength == 0) {
     78     return NULL;
     79   }
     80   uint32_t uHash = FX_HashCode_String_GetW(wsName.GetPtr(), iLength);
     81   int32_t iStart = 0, iEnd = g_iXFAEnumCount - 1;
     82   do {
     83     int32_t iMid = (iStart + iEnd) / 2;
     84     XFA_LPCATTRIBUTEENUMINFO pInfo = g_XFAEnumData + iMid;
     85     if (uHash == pInfo->uHash) {
     86       return pInfo;
     87     } else if (uHash < pInfo->uHash) {
     88       iEnd = iMid - 1;
     89     } else {
     90       iStart = iMid + 1;
     91     }
     92   } while (iStart <= iEnd);
     93   return NULL;
     94 }
     95 XFA_LPCATTRIBUTEENUMINFO XFA_GetAttributeEnumByID(XFA_ATTRIBUTEENUM eName) {
     96   return g_XFAEnumData + eName;
     97 }
     98 int32_t XFA_GetAttributeCount() {
     99   return g_iXFAAttributeCount;
    100 }
    101 XFA_LPCATTRIBUTEINFO XFA_GetAttributeByName(const CFX_WideStringC& wsName) {
    102   int32_t iLength = wsName.GetLength();
    103   if (iLength == 0) {
    104     return NULL;
    105   }
    106   uint32_t uHash = FX_HashCode_String_GetW(wsName.GetPtr(), iLength);
    107   int32_t iStart = 0, iEnd = g_iXFAAttributeCount - 1;
    108   do {
    109     int32_t iMid = (iStart + iEnd) / 2;
    110     XFA_LPCATTRIBUTEINFO pInfo = g_XFAAttributeData + iMid;
    111     if (uHash == pInfo->uHash) {
    112       return pInfo;
    113     } else if (uHash < pInfo->uHash) {
    114       iEnd = iMid - 1;
    115     } else {
    116       iStart = iMid + 1;
    117     }
    118   } while (iStart <= iEnd);
    119   return NULL;
    120 }
    121 XFA_LPCATTRIBUTEINFO XFA_GetAttributeByID(XFA_ATTRIBUTE eName) {
    122   return (eName < g_iXFAAttributeCount) ? (g_XFAAttributeData + eName) : NULL;
    123 }
    124 FX_BOOL XFA_GetAttributeDefaultValue(void*& pValue,
    125                                      XFA_ELEMENT eElement,
    126                                      XFA_ATTRIBUTE eAttribute,
    127                                      XFA_ATTRIBUTETYPE eType,
    128                                      FX_DWORD dwPacket) {
    129   XFA_LPCATTRIBUTEINFO pInfo = XFA_GetAttributeByID(eAttribute);
    130   if (pInfo == NULL) {
    131     return FALSE;
    132   }
    133   if (dwPacket && (dwPacket & pInfo->dwPackets) == 0) {
    134     return FALSE;
    135   }
    136   if (pInfo->eType == eType) {
    137     pValue = pInfo->pDefValue;
    138     return TRUE;
    139   } else if (pInfo->eType == XFA_ATTRIBUTETYPE_NOTSURE) {
    140     XFA_LPCNOTSUREATTRIBUTE pAttr =
    141         XFA_GetNotsureAttribute(eElement, eAttribute, eType);
    142     if (pAttr) {
    143       pValue = pAttr->pValue;
    144       return TRUE;
    145     }
    146   }
    147   return FALSE;
    148 }
    149 XFA_ATTRIBUTEENUM XFA_GetAttributeDefaultValue_Enum(XFA_ELEMENT eElement,
    150                                                     XFA_ATTRIBUTE eAttribute,
    151                                                     FX_DWORD dwPacket) {
    152   void* pValue;
    153   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
    154                                    XFA_ATTRIBUTETYPE_Enum, dwPacket)) {
    155     return (XFA_ATTRIBUTEENUM)(uintptr_t)pValue;
    156   }
    157   return XFA_ATTRIBUTEENUM_Unknown;
    158 }
    159 CFX_WideStringC XFA_GetAttributeDefaultValue_Cdata(XFA_ELEMENT eElement,
    160                                                    XFA_ATTRIBUTE eAttribute,
    161                                                    FX_DWORD dwPacket) {
    162   void* pValue;
    163   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
    164                                    XFA_ATTRIBUTETYPE_Cdata, dwPacket)) {
    165     return (const FX_WCHAR*)pValue;
    166   }
    167   return NULL;
    168 }
    169 FX_BOOL XFA_GetAttributeDefaultValue_Boolean(XFA_ELEMENT eElement,
    170                                              XFA_ATTRIBUTE eAttribute,
    171                                              FX_DWORD dwPacket) {
    172   void* pValue;
    173   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
    174                                    XFA_ATTRIBUTETYPE_Boolean, dwPacket)) {
    175     return (FX_BOOL)(uintptr_t)pValue;
    176   }
    177   return FALSE;
    178 }
    179 int32_t XFA_GetAttributeDefaultValue_Integer(XFA_ELEMENT eElement,
    180                                              XFA_ATTRIBUTE eAttribute,
    181                                              FX_DWORD dwPacket) {
    182   void* pValue;
    183   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
    184                                    XFA_ATTRIBUTETYPE_Integer, dwPacket)) {
    185     return (int32_t)(uintptr_t)pValue;
    186   }
    187   return 0;
    188 }
    189 CXFA_Measurement XFA_GetAttributeDefaultValue_Measure(XFA_ELEMENT eElement,
    190                                                       XFA_ATTRIBUTE eAttribute,
    191                                                       FX_DWORD dwPacket) {
    192   void* pValue;
    193   if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute,
    194                                    XFA_ATTRIBUTETYPE_Measure, dwPacket)) {
    195     return *(CXFA_Measurement*)pValue;
    196   }
    197   return CXFA_Measurement();
    198 }
    199 int32_t XFA_GetElementCount() {
    200   return g_iXFAElementCount;
    201 }
    202 XFA_LPCELEMENTINFO XFA_GetElementByName(const CFX_WideStringC& wsName) {
    203   int32_t iLength = wsName.GetLength();
    204   if (iLength == 0) {
    205     return NULL;
    206   }
    207   uint32_t uHash = FX_HashCode_String_GetW(wsName.GetPtr(), iLength);
    208   int32_t iStart = 0, iEnd = g_iXFAElementCount - 1;
    209   do {
    210     int32_t iMid = (iStart + iEnd) / 2;
    211     XFA_LPCELEMENTINFO pInfo = g_XFAElementData + iMid;
    212     if (uHash == pInfo->uHash) {
    213       return pInfo;
    214     } else if (uHash < pInfo->uHash) {
    215       iEnd = iMid - 1;
    216     } else {
    217       iStart = iMid + 1;
    218     }
    219   } while (iStart <= iEnd);
    220   return NULL;
    221 }
    222 XFA_LPCELEMENTINFO XFA_GetElementByID(XFA_ELEMENT eName) {
    223   return (eName < g_iXFAElementCount) ? (g_XFAElementData + eName) : NULL;
    224 }
    225 const FX_WORD* XFA_GetElementChildren(XFA_ELEMENT eElement, int32_t& iCount) {
    226   if (eElement >= g_iXFAElementCount) {
    227     return NULL;
    228   }
    229   XFA_LPCELEMENTHIERARCHY pElement = g_XFAElementChildrenIndex + eElement;
    230   iCount = pElement->wCount;
    231   return g_XFAElementChildrenData + pElement->wStart;
    232 }
    233 const uint8_t* XFA_GetElementAttributes(XFA_ELEMENT eElement, int32_t& iCount) {
    234   if (eElement >= g_iXFAElementCount) {
    235     return NULL;
    236   }
    237   XFA_LPCELEMENTHIERARCHY pElement = g_XFAElementAttributeIndex + eElement;
    238   iCount = pElement->wCount;
    239   return g_XFAElementAttributeData + pElement->wStart;
    240 }
    241 XFA_LPCATTRIBUTEINFO XFA_GetAttributeOfElement(XFA_ELEMENT eElement,
    242                                                XFA_ATTRIBUTE eAttribute,
    243                                                FX_DWORD dwPacket) {
    244   int32_t iCount = 0;
    245   const uint8_t* pAttr = XFA_GetElementAttributes(eElement, iCount);
    246   if (pAttr == NULL || iCount < 1) {
    247     return NULL;
    248   }
    249   CFX_DSPATemplate<uint8_t> search;
    250   int32_t index = search.Lookup(eAttribute, pAttr, iCount);
    251   if (index < 0) {
    252     return NULL;
    253   }
    254   XFA_LPCATTRIBUTEINFO pInfo = XFA_GetAttributeByID(eAttribute);
    255   ASSERT(pInfo != NULL);
    256   if (dwPacket == XFA_XDPPACKET_UNKNOWN) {
    257     return pInfo;
    258   }
    259   return (dwPacket & pInfo->dwPackets) ? pInfo : NULL;
    260 }
    261 XFA_LPCELEMENTINFO XFA_GetChildOfElement(XFA_ELEMENT eElement,
    262                                          XFA_ELEMENT eChild,
    263                                          FX_DWORD dwPacket) {
    264   int32_t iCount = 0;
    265   const FX_WORD* pChild = XFA_GetElementChildren(eElement, iCount);
    266   if (pChild == NULL || iCount < 1) {
    267     return NULL;
    268   }
    269   CFX_DSPATemplate<FX_WORD> search;
    270   int32_t index = search.Lookup(eChild, pChild, iCount);
    271   if (index < 0) {
    272     return NULL;
    273   }
    274   XFA_LPCELEMENTINFO pInfo = XFA_GetElementByID(eChild);
    275   ASSERT(pInfo != NULL);
    276   if (dwPacket == XFA_XDPPACKET_UNKNOWN) {
    277     return pInfo;
    278   }
    279   return (dwPacket & pInfo->dwPackets) ? pInfo : NULL;
    280 }
    281 XFA_LPCPROPERTY XFA_GetElementProperties(XFA_ELEMENT eElement,
    282                                          int32_t& iCount) {
    283   if (eElement >= g_iXFAElementCount) {
    284     return NULL;
    285   }
    286   XFA_LPCELEMENTHIERARCHY pElement = g_XFAElementPropertyIndex + eElement;
    287   iCount = pElement->wCount;
    288   return g_XFAElementPropertyData + pElement->wStart;
    289 }
    290 XFA_LPCPROPERTY XFA_GetPropertyOfElement(XFA_ELEMENT eElement,
    291                                          XFA_ELEMENT eProperty,
    292                                          FX_DWORD dwPacket) {
    293   int32_t iCount = 0;
    294   XFA_LPCPROPERTY pProperty = XFA_GetElementProperties(eElement, iCount);
    295   if (pProperty == NULL || iCount < 1) {
    296     return NULL;
    297   }
    298   int32_t iStart = 0, iEnd = iCount - 1, iMid;
    299   do {
    300     iMid = (iStart + iEnd) / 2;
    301     XFA_ELEMENT eName = (XFA_ELEMENT)pProperty[iMid].eName;
    302     if (eProperty == eName) {
    303       break;
    304     } else if (eProperty < eName) {
    305       iEnd = iMid - 1;
    306     } else {
    307       iStart = iMid + 1;
    308     }
    309   } while (iStart <= iEnd);
    310   if (iStart > iEnd) {
    311     return NULL;
    312   }
    313   XFA_LPCELEMENTINFO pInfo = XFA_GetElementByID(eProperty);
    314   ASSERT(pInfo != NULL);
    315   if (dwPacket == XFA_XDPPACKET_UNKNOWN) {
    316     return pProperty + iMid;
    317   }
    318   return (dwPacket & pInfo->dwPackets) ? (pProperty + iMid) : NULL;
    319 }
    320 XFA_LPCNOTSUREATTRIBUTE XFA_GetNotsureAttribute(XFA_ELEMENT eElement,
    321                                                 XFA_ATTRIBUTE eAttribute,
    322                                                 XFA_ATTRIBUTETYPE eType) {
    323   int32_t iStart = 0, iEnd = g_iXFANotsureCount - 1;
    324   do {
    325     int32_t iMid = (iStart + iEnd) / 2;
    326     XFA_LPCNOTSUREATTRIBUTE pAttr = g_XFANotsureAttributes + iMid;
    327     if (eElement == pAttr->eElement) {
    328       if (pAttr->eAttribute == eAttribute) {
    329         if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) {
    330           return pAttr;
    331         }
    332         return NULL;
    333       } else {
    334         int32_t iBefore = iMid - 1;
    335         if (iBefore >= 0) {
    336           pAttr = g_XFANotsureAttributes + iBefore;
    337           while (eElement == pAttr->eElement) {
    338             if (pAttr->eAttribute == eAttribute) {
    339               if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) {
    340                 return pAttr;
    341               }
    342               return NULL;
    343             }
    344             iBefore--;
    345             if (iBefore < 0) {
    346               break;
    347             }
    348             pAttr = g_XFANotsureAttributes + iBefore;
    349           }
    350         }
    351         int32_t iAfter = iMid + 1;
    352         if (iAfter <= g_iXFANotsureCount - 1) {
    353           pAttr = g_XFANotsureAttributes + iAfter;
    354           while (eElement == pAttr->eElement) {
    355             if (pAttr->eAttribute == eAttribute) {
    356               if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) {
    357                 return pAttr;
    358               }
    359               return NULL;
    360             }
    361             iAfter++;
    362             if (iAfter > g_iXFANotsureCount - 1) {
    363               break;
    364             }
    365             pAttr = g_XFANotsureAttributes + iAfter;
    366           }
    367         }
    368         return NULL;
    369       }
    370     } else if (eElement < pAttr->eElement) {
    371       iEnd = iMid - 1;
    372     } else {
    373       iStart = iMid + 1;
    374     }
    375   } while (iStart <= iEnd);
    376   return NULL;
    377 }
    378 int32_t XFA_GetMethodCount() {
    379   return g_iSomMethodCount;
    380 }
    381 XFA_LPCMETHODINFO XFA_GetMethodByName(XFA_ELEMENT eElement,
    382                                       const CFX_WideStringC& wsMethodName) {
    383   int32_t iLength = wsMethodName.GetLength();
    384   if (iLength == 0) {
    385     return NULL;
    386   }
    387   int32_t iElementIndex = eElement;
    388   while (iElementIndex != -1) {
    389     XFA_LPCSCRIPTHIERARCHY scriptIndex = g_XFAScriptIndex + iElementIndex;
    390     int32_t icount = scriptIndex->wMethodCount;
    391     if (icount == 0) {
    392       iElementIndex = scriptIndex->wParentIndex;
    393       continue;
    394     }
    395     uint32_t uHash = FX_HashCode_String_GetW(wsMethodName.GetPtr(), iLength);
    396     int32_t iStart = scriptIndex->wMethodStart, iEnd = iStart + icount - 1;
    397     do {
    398       int32_t iMid = (iStart + iEnd) / 2;
    399       XFA_LPCMETHODINFO pInfo = g_SomMethodData + iMid;
    400       if (uHash == pInfo->uHash) {
    401         return pInfo;
    402       } else if (uHash < pInfo->uHash) {
    403         iEnd = iMid - 1;
    404       } else {
    405         iStart = iMid + 1;
    406       }
    407     } while (iStart <= iEnd);
    408     iElementIndex = scriptIndex->wParentIndex;
    409   }
    410   return NULL;
    411 }
    412 XFA_LPCSCRIPTATTRIBUTEINFO XFA_GetScriptAttributeByName(
    413     XFA_ELEMENT eElement,
    414     const CFX_WideStringC& wsAttributeName) {
    415   int32_t iLength = wsAttributeName.GetLength();
    416   if (iLength == 0) {
    417     return NULL;
    418   }
    419   int32_t iElementIndex = eElement;
    420   while (iElementIndex != -1) {
    421     XFA_LPCSCRIPTHIERARCHY scriptIndex = g_XFAScriptIndex + iElementIndex;
    422     int32_t icount = scriptIndex->wAttributeCount;
    423     if (icount == 0) {
    424       iElementIndex = scriptIndex->wParentIndex;
    425       continue;
    426     }
    427     uint32_t uHash = FX_HashCode_String_GetW(wsAttributeName.GetPtr(), iLength);
    428     int32_t iStart = scriptIndex->wAttributeStart, iEnd = iStart + icount - 1;
    429     do {
    430       int32_t iMid = (iStart + iEnd) / 2;
    431       XFA_LPCSCRIPTATTRIBUTEINFO pInfo = g_SomAttributeData + iMid;
    432       if (uHash == pInfo->uHash) {
    433         return pInfo;
    434       } else if (uHash < pInfo->uHash) {
    435         iEnd = iMid - 1;
    436       } else {
    437         iStart = iMid + 1;
    438       }
    439     } while (iStart <= iEnd);
    440     iElementIndex = scriptIndex->wParentIndex;
    441   }
    442   return NULL;
    443 }
    444 void CXFA_Measurement::Set(const CFX_WideStringC& wsMeasure) {
    445   if (wsMeasure.IsEmpty()) {
    446     m_fValue = 0;
    447     m_eUnit = XFA_UNIT_Unknown;
    448     return;
    449   }
    450   int32_t iUsedLen = 0;
    451   int32_t iOffset = (wsMeasure.GetAt(0) == L'=') ? 1 : 0;
    452   FX_FLOAT fValue = FX_wcstof(wsMeasure.GetPtr() + iOffset,
    453                               wsMeasure.GetLength() - iOffset, &iUsedLen);
    454   XFA_UNIT eUnit = GetUnit(wsMeasure.Mid(iOffset + iUsedLen));
    455   Set(fValue, eUnit);
    456 }
    457 FX_BOOL CXFA_Measurement::ToString(CFX_WideString& wsMeasure) const {
    458   switch (GetUnit()) {
    459     case XFA_UNIT_Mm:
    460       wsMeasure.Format(L"%.8gmm", GetValue());
    461       return TRUE;
    462     case XFA_UNIT_Pt:
    463       wsMeasure.Format(L"%.8gpt", GetValue());
    464       return TRUE;
    465     case XFA_UNIT_In:
    466       wsMeasure.Format(L"%.8gin", GetValue());
    467       return TRUE;
    468     case XFA_UNIT_Cm:
    469       wsMeasure.Format(L"%.8gcm", GetValue());
    470       return TRUE;
    471     case XFA_UNIT_Mp:
    472       wsMeasure.Format(L"%.8gmp", GetValue());
    473       return TRUE;
    474     case XFA_UNIT_Pc:
    475       wsMeasure.Format(L"%.8gpc", GetValue());
    476       return TRUE;
    477     case XFA_UNIT_Em:
    478       wsMeasure.Format(L"%.8gem", GetValue());
    479       return TRUE;
    480     case XFA_UNIT_Percent:
    481       wsMeasure.Format(L"%.8g%%", GetValue());
    482       return TRUE;
    483     default:
    484       wsMeasure.Format(L"%.8g", GetValue());
    485       return FALSE;
    486   }
    487 }
    488 FX_BOOL CXFA_Measurement::ToUnit(XFA_UNIT eUnit, FX_FLOAT& fValue) const {
    489   fValue = GetValue();
    490   XFA_UNIT eFrom = GetUnit();
    491   if (eFrom == eUnit) {
    492     return TRUE;
    493   }
    494   switch (eFrom) {
    495     case XFA_UNIT_Pt:
    496       break;
    497     case XFA_UNIT_Mm:
    498       fValue *= 72 / 2.54f / 10;
    499       break;
    500     case XFA_UNIT_In:
    501       fValue *= 72;
    502       break;
    503     case XFA_UNIT_Cm:
    504       fValue *= 72 / 2.54f;
    505       break;
    506     case XFA_UNIT_Mp:
    507       fValue *= 0.001f;
    508       break;
    509     case XFA_UNIT_Pc:
    510       fValue *= 12.0f;
    511       break;
    512     default:
    513       fValue = 0;
    514       return FALSE;
    515   }
    516   switch (eUnit) {
    517     case XFA_UNIT_Pt:
    518       return TRUE;
    519     case XFA_UNIT_Mm:
    520       fValue /= 72 / 2.54f / 10;
    521       return TRUE;
    522     case XFA_UNIT_In:
    523       fValue /= 72;
    524       return TRUE;
    525     case XFA_UNIT_Cm:
    526       fValue /= 72 / 2.54f;
    527       return TRUE;
    528     case XFA_UNIT_Mp:
    529       fValue /= 0.001f;
    530       return TRUE;
    531     case XFA_UNIT_Pc:
    532       fValue /= 12.0f;
    533       return TRUE;
    534     default:
    535       fValue = 0;
    536       return FALSE;
    537   }
    538   return FALSE;
    539 }
    540 XFA_UNIT CXFA_Measurement::GetUnit(const CFX_WideStringC& wsUnit) {
    541   if (wsUnit == FX_WSTRC(L"mm")) {
    542     return XFA_UNIT_Mm;
    543   } else if (wsUnit == FX_WSTRC(L"pt")) {
    544     return XFA_UNIT_Pt;
    545   } else if (wsUnit == FX_WSTRC(L"in")) {
    546     return XFA_UNIT_In;
    547   } else if (wsUnit == FX_WSTRC(L"cm")) {
    548     return XFA_UNIT_Cm;
    549   } else if (wsUnit == FX_WSTRC(L"pc")) {
    550     return XFA_UNIT_Pc;
    551   } else if (wsUnit == FX_WSTRC(L"mp")) {
    552     return XFA_UNIT_Mp;
    553   } else if (wsUnit == FX_WSTRC(L"em")) {
    554     return XFA_UNIT_Em;
    555   } else if (wsUnit == FX_WSTRC(L"%")) {
    556     return XFA_UNIT_Percent;
    557   } else {
    558     return XFA_UNIT_Unknown;
    559   }
    560 }
    561 IFX_Stream* XFA_CreateWideTextRead(const CFX_WideString& wsBuffer) {
    562   return new CXFA_WideTextRead(wsBuffer);
    563 }
    564 CXFA_WideTextRead::CXFA_WideTextRead(const CFX_WideString& wsBuffer)
    565     : m_wsBuffer(wsBuffer), m_iPosition(0), m_iRefCount(1) {}
    566 void CXFA_WideTextRead::Release() {
    567   if (--m_iRefCount < 1) {
    568     delete this;
    569   }
    570 }
    571 IFX_Stream* CXFA_WideTextRead::Retain() {
    572   m_iRefCount++;
    573   return this;
    574 }
    575 FX_DWORD CXFA_WideTextRead::GetAccessModes() const {
    576   return FX_STREAMACCESS_Read | FX_STREAMACCESS_Text;
    577 }
    578 int32_t CXFA_WideTextRead::GetLength() const {
    579   return m_wsBuffer.GetLength() * sizeof(FX_WCHAR);
    580 }
    581 int32_t CXFA_WideTextRead::Seek(FX_STREAMSEEK eSeek, int32_t iOffset) {
    582   switch (eSeek) {
    583     case FX_STREAMSEEK_Begin:
    584       m_iPosition = iOffset;
    585       break;
    586     case FX_STREAMSEEK_Current:
    587       m_iPosition += iOffset;
    588       break;
    589     case FX_STREAMSEEK_End:
    590       m_iPosition = m_wsBuffer.GetLength() + iOffset;
    591       break;
    592   }
    593   if (m_iPosition < 0) {
    594     m_iPosition = 0;
    595   }
    596   if (m_iPosition > m_wsBuffer.GetLength()) {
    597     m_iPosition = m_wsBuffer.GetLength();
    598   }
    599   return GetPosition();
    600 }
    601 int32_t CXFA_WideTextRead::GetPosition() {
    602   return m_iPosition * sizeof(FX_WCHAR);
    603 }
    604 FX_BOOL CXFA_WideTextRead::IsEOF() const {
    605   return m_iPosition >= m_wsBuffer.GetLength();
    606 }
    607 int32_t CXFA_WideTextRead::ReadString(FX_WCHAR* pStr,
    608                                       int32_t iMaxLength,
    609                                       FX_BOOL& bEOS,
    610                                       int32_t const* pByteSize) {
    611   if (iMaxLength > m_wsBuffer.GetLength() - m_iPosition) {
    612     iMaxLength = m_wsBuffer.GetLength() - m_iPosition;
    613   }
    614   FXSYS_wcsncpy(pStr, (const FX_WCHAR*)m_wsBuffer + m_iPosition, iMaxLength);
    615   m_iPosition += iMaxLength;
    616   bEOS = IsEOF();
    617   return iMaxLength;
    618 }
    619 FX_WORD CXFA_WideTextRead::GetCodePage() const {
    620   return (sizeof(FX_WCHAR) == 2) ? FX_CODEPAGE_UTF16LE : FX_CODEPAGE_UTF32LE;
    621 }
    622 FX_WORD CXFA_WideTextRead::SetCodePage(FX_WORD wCodePage) {
    623   return GetCodePage();
    624 }
    625