OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #ifndef CORE_SRC_FPDFTEXT_TEXT_INT_H_ | 7 #ifndef CORE_SRC_FPDFTEXT_TEXT_INT_H_ |
8 #define CORE_SRC_FPDFTEXT_TEXT_INT_H_ | 8 #define CORE_SRC_FPDFTEXT_TEXT_INT_H_ |
9 | 9 |
10 class CPDF_TextPage; | 10 class CPDF_TextPage; |
11 class CPDF_LinkExtract; | 11 class CPDF_LinkExtract; |
12 class CPDF_TextPageFind; | 12 class CPDF_TextPageFind; |
13 class CPDF_DocProgressiveSearch; | 13 class CPDF_DocProgressiveSearch; |
14 #define FPDFTEXT_CHAR_ERROR» » » -1 | 14 #define FPDFTEXT_CHAR_ERROR -1 |
15 #define FPDFTEXT_CHAR_NORMAL» » 0 | 15 #define FPDFTEXT_CHAR_NORMAL 0 |
16 #define FPDFTEXT_CHAR_GENERATED»» 1 | 16 #define FPDFTEXT_CHAR_GENERATED 1 |
17 #define FPDFTEXT_CHAR_UNUNICODE»» 2 | 17 #define FPDFTEXT_CHAR_UNUNICODE 2 |
18 #define FPDFTEXT_CHAR_HYPHEN» » 3 | 18 #define FPDFTEXT_CHAR_HYPHEN 3 |
19 #define FPDFTEXT_CHAR_PIECE» » » 4 | 19 #define FPDFTEXT_CHAR_PIECE 4 |
20 #define FPDFTEXT_MC_PASS» » » 0 | 20 #define FPDFTEXT_MC_PASS 0 |
21 #define FPDFTEXT_MC_DONE» » » 1 | 21 #define FPDFTEXT_MC_DONE 1 |
22 #define FPDFTEXT_MC_DELAY» » » 2 | 22 #define FPDFTEXT_MC_DELAY 2 |
23 typedef struct _PAGECHAR_INFO { | 23 typedef struct _PAGECHAR_INFO { |
24 int»» » » » m_CharCode; | 24 int m_CharCode; |
25 FX_WCHAR» » » m_Unicode; | 25 FX_WCHAR m_Unicode; |
26 FX_FLOAT» » » m_OriginX; | 26 FX_FLOAT m_OriginX; |
27 FX_FLOAT» » » m_OriginY; | 27 FX_FLOAT m_OriginY; |
28 int32_t» » » m_Flag; | 28 int32_t m_Flag; |
29 CFX_FloatRect» » m_CharBox; | 29 CFX_FloatRect m_CharBox; |
30 CPDF_TextObject*» m_pTextObj; | 30 CPDF_TextObject* m_pTextObj; |
31 CFX_AffineMatrix» m_Matrix; | 31 CFX_AffineMatrix m_Matrix; |
32 int»» » » » m_Index; | 32 int m_Index; |
33 } PAGECHAR_INFO; | 33 } PAGECHAR_INFO; |
34 typedef»CFX_SegmentedArray<PAGECHAR_INFO> PAGECHAR_InfoArray; | 34 typedef CFX_SegmentedArray<PAGECHAR_INFO> PAGECHAR_InfoArray; |
35 typedef struct { | 35 typedef struct { |
36 int»m_Start; | 36 int m_Start; |
37 int m_nCount; | 37 int m_nCount; |
38 } FPDF_SEGMENT; | 38 } FPDF_SEGMENT; |
39 typedef CFX_ArrayTemplate<FPDF_SEGMENT> SEGMENT_Array; | 39 typedef CFX_ArrayTemplate<FPDF_SEGMENT> SEGMENT_Array; |
40 typedef struct { | 40 typedef struct { |
41 CPDF_TextObject*» m_pTextObj; | 41 CPDF_TextObject* m_pTextObj; |
42 CFX_AffineMatrix» m_formMatrix; | 42 CFX_AffineMatrix m_formMatrix; |
43 } PDFTEXT_Obj; | 43 } PDFTEXT_Obj; |
44 typedef CFX_ArrayTemplate<PDFTEXT_Obj> LINEOBJ; | 44 typedef CFX_ArrayTemplate<PDFTEXT_Obj> LINEOBJ; |
45 class CPDF_TextPage: public IPDF_TextPage | 45 class CPDF_TextPage : public IPDF_TextPage { |
46 { | 46 public: |
47 public: | 47 CPDF_TextPage(const CPDF_Page* pPage, int flags = 0); |
48 CPDF_TextPage(const CPDF_Page* pPage, int flags = 0); | 48 CPDF_TextPage(const CPDF_PageObjects* pPage, int flags = 0); |
49 CPDF_TextPage(const CPDF_PageObjects* pPage, int flags = 0); | 49 CPDF_TextPage(const CPDF_Page* pPage, CPDFText_ParseOptions ParserOptions); |
50 CPDF_TextPage(const CPDF_Page* pPage, CPDFText_ParseOptions ParserOptions); | 50 virtual FX_BOOL ParseTextPage(); |
51 virtual FX_BOOL ParseTextPage(); | 51 virtual void NormalizeObjects(FX_BOOL bNormalize); |
52 virtual void NormalizeObjects(FX_BOOL
bNormalize); | 52 virtual FX_BOOL IsParsered() const { return m_IsParsered; } |
53 virtual FX_BOOL IsParsered() const | 53 virtual ~CPDF_TextPage(){}; |
54 { | 54 |
55 return m_IsParsered; | 55 public: |
56 } | 56 virtual int CharIndexFromTextIndex(int TextIndex) const; |
57 virtual ~CPDF_TextPage() {}; | 57 virtual int TextIndexFromCharIndex(int CharIndex) const; |
58 public: | 58 virtual int CountChars() const; |
59 virtual int CharIndexFromTextIndex(int TextIndex)const ; | 59 virtual void GetCharInfo(int index, FPDF_CHAR_INFO& info) const; |
60 virtual int TextIndexFromCharIndex(int CharIndex)const; | 60 virtual void GetRectArray(int start, |
61 virtual int CountChars() const; | 61 int nCount, |
62 virtual void GetCharInfo(int index, F
PDF_CHAR_INFO & info) const; | 62 CFX_RectArray& rectArray) const; |
63 virtual void GetRectArray(int start,
int nCount, CFX_RectArray& rectArray) const; | 63 virtual int GetIndexAtPos(CPDF_Point point, |
64 virtual int GetIndexAtPos(CPDF_Point
point, FX_FLOAT xTorelance, FX_FLOAT yTorelance) const; | 64 FX_FLOAT xTorelance, |
65 virtual int GetIndexAtPos(FX_FLOAT x
, FX_FLOAT y, FX_FLOAT xTorelance, | 65 FX_FLOAT yTorelance) const; |
66 FX_FLOAT yTorelance) const; | 66 virtual int GetIndexAtPos(FX_FLOAT x, |
67 virtual CFX_WideString GetTextByRect(const CFX_FloatRec
t& rect) const; | 67 FX_FLOAT y, |
68 virtual void GetRectsArrayByRect(cons
t CFX_FloatRect& rect, CFX_RectArray& resRectArray) const; | 68 FX_FLOAT xTorelance, |
69 virtual CFX_WideString GetPageText(int start = 0, int n
Count = -1) const; | 69 FX_FLOAT yTorelance) const; |
70 | 70 virtual CFX_WideString GetTextByRect(const CFX_FloatRect& rect) const; |
71 virtual int CountRects(int start, in
t nCount); | 71 virtual void GetRectsArrayByRect(const CFX_FloatRect& rect, |
72 virtual void GetRect(int rectIndex, F
X_FLOAT& left, FX_FLOAT& top | 72 CFX_RectArray& resRectArray) const; |
73 , FX_FLOAT& right, FX_FLOAT &bottom)
const; | 73 virtual CFX_WideString GetPageText(int start = 0, int nCount = -1) const; |
74 virtual FX_BOOL GetBaselineRotate(int re
ctIndex, int& Rotate); | 74 |
75 virtual FX_BOOL GetBaselineRotate(const
CFX_FloatRect& rect, int& Rotate); | 75 virtual int CountRects(int start, int nCount); |
76 virtual int CountBoundedSegm
ents(FX_FLOAT left, FX_FLOAT top, | 76 virtual void GetRect(int rectIndex, |
77 FX_FLOAT right, FX_FLOAT bottom, FX_BOOL bContains = FALSE); | 77 FX_FLOAT& left, |
78 virtual void GetBoundedSegment(int in
dex, int& start, int& count) const; | 78 FX_FLOAT& top, |
79 virtual int GetWordBreak(int index,
int direction) const; | 79 FX_FLOAT& right, |
80 public: | 80 FX_FLOAT& bottom) const; |
81 const PAGECHAR_InfoArray* GetCharList() const | 81 virtual FX_BOOL GetBaselineRotate(int rectIndex, int& Rotate); |
82 { | 82 virtual FX_BOOL GetBaselineRotate(const CFX_FloatRect& rect, int& Rotate); |
83 return &m_charList; | 83 virtual int CountBoundedSegments(FX_FLOAT left, |
84 } | 84 FX_FLOAT top, |
85 static FX_BOOL IsRectIntersect(const CF
X_FloatRect& rect1, const CFX_FloatRect& rect2); | 85 FX_FLOAT right, |
86 static FX_BOOL IsLetter(FX_WCHAR unicod
e); | 86 FX_FLOAT bottom, |
87 private: | 87 FX_BOOL bContains = FALSE); |
88 FX_BOOL IsHyphen(FX_WCHA
R curChar); | 88 virtual void GetBoundedSegment(int index, int& start, int& count) const; |
89 bool IsControlChar(co
nst PAGECHAR_INFO& charInfo); | 89 virtual int GetWordBreak(int index, int direction) const; |
90 FX_BOOL GetBaselineRotat
e(int start, int end, int& Rotate); | 90 |
91 void ProcessObject(); | 91 public: |
92 void ProcessFormObjec
t(CPDF_FormObject* pFormObj, const CFX_AffineMatrix& formMatrix); | 92 const PAGECHAR_InfoArray* GetCharList() const { return &m_charList; } |
93 void ProcessTextObjec
t(PDFTEXT_Obj pObj); | 93 static FX_BOOL IsRectIntersect(const CFX_FloatRect& rect1, |
94 void ProcessTextObjec
t(CPDF_TextObject* pTextObj, const CFX_AffineMatrix& formMatrix, FX_POSITIO
N ObjPos); | 94 const CFX_FloatRect& rect2); |
95 int ProcessInsertObj
ect(const CPDF_TextObject* pObj, const CFX_AffineMatrix& formMatrix); | 95 static FX_BOOL IsLetter(FX_WCHAR unicode); |
96 FX_BOOL GenerateCharInfo
(FX_WCHAR unicode, PAGECHAR_INFO& info); | 96 |
97 FX_BOOL IsSameAsPreTextO
bject(CPDF_TextObject* pTextObj, FX_POSITION ObjPos); | 97 private: |
98 FX_BOOL IsSameTextObject
(CPDF_TextObject* pTextObj1, CPDF_TextObject* pTextObj2); | 98 FX_BOOL IsHyphen(FX_WCHAR curChar); |
99 int GetCharWidth(FX_
DWORD charCode, CPDF_Font* pFont) const; | 99 bool IsControlChar(const PAGECHAR_INFO& charInfo); |
100 void CloseTempLine(); | 100 FX_BOOL GetBaselineRotate(int start, int end, int& Rotate); |
101 void OnPiece(IFX_Bidi
Char* pBidi, CFX_WideString& str); | 101 void ProcessObject(); |
102 int32_t PreMarkedContent(PDFTEXT_Obj pObj); | 102 void ProcessFormObject(CPDF_FormObject* pFormObj, |
103 void ProcessMarkedContent(PDFTEXT_Obj pObj); | 103 const CFX_AffineMatrix& formMatrix); |
104 void CheckMarkedContentObject(int32_t& start, int32_t& nCount
) const; | 104 void ProcessTextObject(PDFTEXT_Obj pObj); |
105 void FindPreviousTextObject(void); | 105 void ProcessTextObject(CPDF_TextObject* pTextObj, |
106 void AddCharInfoByLRDirection(CFX_WideString& str, int i); | 106 const CFX_AffineMatrix& formMatrix, |
107 void AddCharInfoByRLDirection(CFX_WideString& str, int i); | 107 FX_POSITION ObjPos); |
108 int32_t GetTextObjectWritingMode(const CPDF_TextObject* pTextObj); | 108 int ProcessInsertObject(const CPDF_TextObject* pObj, |
109 int32_t FindTextlineFlowDirection(); | 109 const CFX_AffineMatrix& formMatrix); |
110 void SwapTempTextBuf(int32_t iCharListStartAppend, | 110 FX_BOOL GenerateCharInfo(FX_WCHAR unicode, PAGECHAR_INFO& info); |
111 int32_t iBufStartAppend); | 111 FX_BOOL IsSameAsPreTextObject(CPDF_TextObject* pTextObj, FX_POSITION ObjPos); |
112 FX_BOOL IsRightToLeft(const CPDF_TextObject* pTextObj, | 112 FX_BOOL IsSameTextObject(CPDF_TextObject* pTextObj1, |
113 const CPDF_Font* pFont, | 113 CPDF_TextObject* pTextObj2); |
114 int nItems) const; | 114 int GetCharWidth(FX_DWORD charCode, CPDF_Font* pFont) const; |
115 protected: | 115 void CloseTempLine(); |
116 CPDFText_ParseOptions m_ParseOptions; | 116 void OnPiece(IFX_BidiChar* pBidi, CFX_WideString& str); |
117 CFX_WordArray m_CharIndex; | 117 int32_t PreMarkedContent(PDFTEXT_Obj pObj); |
118 const CPDF_PageObjects* m_pPage; | 118 void ProcessMarkedContent(PDFTEXT_Obj pObj); |
119 PAGECHAR_InfoArray m_charList; | 119 void CheckMarkedContentObject(int32_t& start, int32_t& nCount) const; |
120 CFX_WideTextBuf m_TextBuf; | 120 void FindPreviousTextObject(void); |
121 PAGECHAR_InfoArray m_TempCharList; | 121 void AddCharInfoByLRDirection(CFX_WideString& str, int i); |
122 CFX_WideTextBuf m_TempTextBuf; | 122 void AddCharInfoByRLDirection(CFX_WideString& str, int i); |
123 int m_parserflag; | 123 int32_t GetTextObjectWritingMode(const CPDF_TextObject* pTextObj); |
124 CPDF_TextObject* m_pPreTextObj; | 124 int32_t FindTextlineFlowDirection(); |
125 CFX_AffineMatrix m_perMatrix; | 125 void SwapTempTextBuf(int32_t iCharListStartAppend, int32_t iBufStartAppend); |
126 FX_BOOL m_IsParsered; | 126 FX_BOOL IsRightToLeft(const CPDF_TextObject* pTextObj, |
127 CFX_AffineMatrix m_DisplayMatrix; | 127 const CPDF_Font* pFont, |
128 | 128 int nItems) const; |
129 SEGMENT_Array m_Segment; | 129 |
130 CFX_RectArray m_SelRects; | 130 protected: |
131 LINEOBJ m_LineObj; | 131 CPDFText_ParseOptions m_ParseOptions; |
132 int32_t m_TextlineDir; | 132 CFX_WordArray m_CharIndex; |
133 CFX_FloatRect m_CurlineRect; | 133 const CPDF_PageObjects* m_pPage; |
134 }; | 134 PAGECHAR_InfoArray m_charList; |
135 class CPDF_TextPageFind: public IPDF_TextPageFind | 135 CFX_WideTextBuf m_TextBuf; |
136 { | 136 PAGECHAR_InfoArray m_TempCharList; |
137 public: | 137 CFX_WideTextBuf m_TempTextBuf; |
138 CPDF_TextPageFind(const IPDF_TextPage* pTextPage); | 138 int m_parserflag; |
139 virtual ~CPDF_TextPageFi
nd() {}; | 139 CPDF_TextObject* m_pPreTextObj; |
140 public: | 140 CFX_AffineMatrix m_perMatrix; |
141 virtual FX_BOOL FindFirst(const CFX_Wide
String& findwhat, int flags, int startPos = 0); | 141 FX_BOOL m_IsParsered; |
142 virtual FX_BOOL FindNext(); | 142 CFX_AffineMatrix m_DisplayMatrix; |
143 virtual FX_BOOL FindPrev(); | 143 |
144 | 144 SEGMENT_Array m_Segment; |
145 virtual void GetRectArray(CFX_RectArr
ay& rects) const; | 145 CFX_RectArray m_SelRects; |
146 virtual int GetCurOrder() const; | 146 LINEOBJ m_LineObj; |
147 virtual int GetMatchedCount()const; | 147 int32_t m_TextlineDir; |
148 protected: | 148 CFX_FloatRect m_CurlineRect; |
149 void ExtractFindWhat(
const CFX_WideString& findwhat); | 149 }; |
150 FX_BOOL IsMatchWholeWord
(const CFX_WideString& csPageText, int startPos, int endPos); | 150 class CPDF_TextPageFind : public IPDF_TextPageFind { |
151 FX_BOOL ExtractSubString
(CFX_WideString& rString, const FX_WCHAR* lpszFullString, | 151 public: |
152 int iSubString, FX_WCHAR chSep); | 152 CPDF_TextPageFind(const IPDF_TextPage* pTextPage); |
153 CFX_WideString MakeReverse(const CFX_Wi
deString& str); | 153 virtual ~CPDF_TextPageFind(){}; |
154 int ReverseFind(cons
t CFX_WideString& csPageText, const CFX_WideString& csWord, int nStartPos, int&
WordLength); | 154 |
155 int GetCharIndex(int
index) const; | 155 public: |
156 private: | 156 virtual FX_BOOL FindFirst(const CFX_WideString& findwhat, |
157 CFX_WordArray m_CharIndex; | 157 int flags, |
158 const IPDF_TextPage* m_pTextPage; | 158 int startPos = 0); |
159 CFX_WideString m_strText; | 159 virtual FX_BOOL FindNext(); |
160 CFX_WideString m_findWhat; | 160 virtual FX_BOOL FindPrev(); |
161 int m_flags; | 161 |
162 CFX_WideStringArray m_csFindWhatArray; | 162 virtual void GetRectArray(CFX_RectArray& rects) const; |
163 int m_findNextStart; | 163 virtual int GetCurOrder() const; |
164 int m_findPreStart; | 164 virtual int GetMatchedCount() const; |
165 FX_BOOL m_bMatchCase; | 165 |
166 FX_BOOL m_bMatchWholeWor
d; | 166 protected: |
167 int m_resStart; | 167 void ExtractFindWhat(const CFX_WideString& findwhat); |
168 int m_resEnd; | 168 FX_BOOL IsMatchWholeWord(const CFX_WideString& csPageText, |
169 CFX_RectArray m_resArray; | 169 int startPos, |
170 FX_BOOL m_IsFind; | 170 int endPos); |
171 }; | 171 FX_BOOL ExtractSubString(CFX_WideString& rString, |
172 class CPDF_LinkExt | 172 const FX_WCHAR* lpszFullString, |
173 { | 173 int iSubString, |
174 public: | 174 FX_WCHAR chSep); |
175 CPDF_LinkExt() {}; | 175 CFX_WideString MakeReverse(const CFX_WideString& str); |
176 int m_Start; | 176 int ReverseFind(const CFX_WideString& csPageText, |
177 int m_Count; | 177 const CFX_WideString& csWord, |
178 CFX_WideString m_strUrl; | 178 int nStartPos, |
179 virtual ~CPDF_LinkExt()
{}; | 179 int& WordLength); |
| 180 int GetCharIndex(int index) const; |
| 181 |
| 182 private: |
| 183 CFX_WordArray m_CharIndex; |
| 184 const IPDF_TextPage* m_pTextPage; |
| 185 CFX_WideString m_strText; |
| 186 CFX_WideString m_findWhat; |
| 187 int m_flags; |
| 188 CFX_WideStringArray m_csFindWhatArray; |
| 189 int m_findNextStart; |
| 190 int m_findPreStart; |
| 191 FX_BOOL m_bMatchCase; |
| 192 FX_BOOL m_bMatchWholeWord; |
| 193 int m_resStart; |
| 194 int m_resEnd; |
| 195 CFX_RectArray m_resArray; |
| 196 FX_BOOL m_IsFind; |
| 197 }; |
| 198 class CPDF_LinkExt { |
| 199 public: |
| 200 CPDF_LinkExt(){}; |
| 201 int m_Start; |
| 202 int m_Count; |
| 203 CFX_WideString m_strUrl; |
| 204 virtual ~CPDF_LinkExt(){}; |
180 }; | 205 }; |
181 typedef CFX_ArrayTemplate<CPDF_LinkExt*> LINK_InfoArray; | 206 typedef CFX_ArrayTemplate<CPDF_LinkExt*> LINK_InfoArray; |
182 class CPDF_LinkExtract: public IPDF_LinkExtract | 207 class CPDF_LinkExtract : public IPDF_LinkExtract { |
183 { | 208 public: |
184 public: | 209 CPDF_LinkExtract(); |
185 CPDF_LinkExtract(); | 210 virtual ~CPDF_LinkExtract(); |
186 virtual» » » » » » » ~CPDF_LinkExtrac
t(); | 211 virtual FX_BOOL ExtractLinks(const IPDF_TextPage* pTextPage); |
187 virtual FX_BOOL» » » » » ExtractLinks(const IPDF_
TextPage* pTextPage); | 212 virtual FX_BOOL IsExtract() const { return m_IsParserd; } |
188 virtual» FX_BOOL»» » » » IsExtract() const | 213 |
189 { | 214 public: |
190 return m_IsParserd; | 215 virtual int CountLinks() const; |
191 } | 216 virtual CFX_WideString GetURL(int index) const; |
192 public: | 217 virtual void GetBoundedSegment(int index, int& start, int& count) const; |
193 virtual int»» » » » » CountLinks() const; | 218 virtual void GetRects(int index, CFX_RectArray& rects) const; |
194 virtual» CFX_WideString» » » GetURL(int index) const; | 219 |
195 virtual» void» » » » » GetBoundedSegment(int in
dex, int& start, int& count) const; | 220 protected: |
196 virtual» void» » » » » GetRects(int index, CFX_
RectArray& rects)const; | 221 void parserLink(); |
197 protected: | 222 void DeleteLinkList(); |
198 void» » » » » » » parserLink(); | 223 FX_BOOL CheckWebLink(CFX_WideString& strBeCheck); |
199 void» » » » » » » DeleteLinkList()
; | 224 FX_BOOL CheckMailLink(CFX_WideString& str); |
200 FX_BOOL» » » » » » » CheckWebLink(CFX
_WideString& strBeCheck); | 225 FX_BOOL AppendToLinkList(int start, int count, const CFX_WideString& strUrl); |
201 FX_BOOL» » » » » » » CheckMailLink(CF
X_WideString& str); | 226 |
202 FX_BOOL» » » » » » » AppendToLinkList
(int start, int count, const CFX_WideString& strUrl); | 227 private: |
203 private: | 228 LINK_InfoArray m_LinkList; |
204 LINK_InfoArray» » » » » m_LinkList; | 229 const CPDF_TextPage* m_pTextPage; |
205 const CPDF_TextPage*» » » m_pTextPage; | 230 CFX_WideString m_strPageText; |
206 CFX_WideString» » » » » m_strPageText; | 231 FX_BOOL m_IsParserd; |
207 FX_BOOL» » » » » » » m_IsParserd; | |
208 }; | 232 }; |
209 FX_STRSIZE FX_Unicode_GetNormalization(FX_WCHAR wch, FX_WCHAR* pDst); | 233 FX_STRSIZE FX_Unicode_GetNormalization(FX_WCHAR wch, FX_WCHAR* pDst); |
210 void NormalizeString(CFX_WideString& str); | 234 void NormalizeString(CFX_WideString& str); |
211 void NormalizeCompositeChar(FX_WCHAR wChar, CFX_WideString& sDest); | 235 void NormalizeCompositeChar(FX_WCHAR wChar, CFX_WideString& sDest); |
212 | 236 |
213 #endif // CORE_SRC_FPDFTEXT_TEXT_INT_H_ | 237 #endif // CORE_SRC_FPDFTEXT_TEXT_INT_H_ |
OLD | NEW |