LibreOffice Module vcl (master) 1
imap2.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include <comphelper/string.hxx>
22#include <string.h>
23#include <o3tl/string_view.hxx>
24#include <rtl/strbuf.hxx>
25#include <vcl/outdev.hxx>
26#include <vcl/svapp.hxx>
27#include <tools/urlobj.hxx>
28
29#include <svl/urihelper.hxx>
30#include <vcl/imap.hxx>
31#include <vcl/imapobj.hxx>
32#include <vcl/imaprect.hxx>
33#include <vcl/imapcirc.hxx>
34#include <vcl/imappoly.hxx>
35
36#include <math.h>
37
38#define NOTEOL(c) ((c)!='\0')
39
40void IMapObject::AppendCERNCoords(OStringBuffer& rBuf, const Point& rPoint100)
41{
42 const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MapUnit::Map100thMM ) ) );
43
44 rBuf.append('(');
45 rBuf.append(static_cast<sal_Int32>(aPixPt.X()));
46 rBuf.append(',');
47 rBuf.append(static_cast<sal_Int32>(aPixPt.Y()));
48 rBuf.append(") ");
49}
50
51void IMapObject::AppendNCSACoords(OStringBuffer& rBuf, const Point& rPoint100)
52{
53 const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MapUnit::Map100thMM ) ) );
54
55 rBuf.append(static_cast<sal_Int32>(aPixPt.X()));
56 rBuf.append(',');
57 rBuf.append(static_cast<sal_Int32>(aPixPt.Y()));
58 rBuf.append(' ');
59}
60
61void IMapObject::AppendCERNURL(OStringBuffer& rBuf) const
62{
63 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative("", aURL), osl_getThreadTextEncoding()));
64}
65
66void IMapObject::AppendNCSAURL(OStringBuffer& rBuf) const
67{
68 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative("", aURL), osl_getThreadTextEncoding()));
69 rBuf.append(' ');
70}
71
73{
74 OStringBuffer aStrBuf("rectangle ");
75
76 AppendCERNCoords(aStrBuf, aRect.TopLeft());
78 AppendCERNURL(aStrBuf);
79
80 rOStm.WriteLine(aStrBuf);
81}
82
84{
85 OStringBuffer aStrBuf("rect ");
86
87 AppendNCSAURL(aStrBuf);
88 AppendNCSACoords(aStrBuf, aRect.TopLeft());
90
91 rOStm.WriteLine(aStrBuf);
92}
93
95{
96 OStringBuffer aStrBuf("circle ");
97
98 AppendCERNCoords(aStrBuf, aCenter);
99 aStrBuf.append(nRadius);
100 aStrBuf.append(' ');
101 AppendCERNURL(aStrBuf);
102
103 rOStm.WriteLine(aStrBuf);
104}
105
107{
108 OStringBuffer aStrBuf("circle ");
109
110 AppendNCSAURL(aStrBuf);
111 AppendNCSACoords(aStrBuf, aCenter);
112 AppendNCSACoords(aStrBuf, aCenter + Point(nRadius, 0));
113
114 rOStm.WriteLine(aStrBuf);
115}
116
118{
119 OStringBuffer aStrBuf("polygon ");
120 const sal_uInt16 nCount = aPoly.GetSize();
121
122 for (sal_uInt16 i = 0; i < nCount; ++i)
123 AppendCERNCoords(aStrBuf, aPoly[i]);
124
125 AppendCERNURL(aStrBuf);
126
127 rOStm.WriteLine(aStrBuf);
128}
129
131{
132 OStringBuffer aStrBuf("poly ");
133 const sal_uInt16 nCount = std::min( aPoly.GetSize(), sal_uInt16(100) );
134
135 AppendNCSAURL(aStrBuf);
136
137 for (sal_uInt16 i = 0; i < nCount; ++i)
138 AppendNCSACoords(aStrBuf, aPoly[i]);
139
140 rOStm.WriteLine(aStrBuf);
141}
142
143void ImageMap::Write( SvStream& rOStm, IMapFormat nFormat ) const
144{
145 switch( nFormat )
146 {
147 case IMapFormat::Binary : Write( rOStm ); break;
148 case IMapFormat::CERN : ImpWriteCERN( rOStm ); break;
149 case IMapFormat::NCSA : ImpWriteNCSA( rOStm ); break;
150
151 default:
152 break;
153 }
154}
155
157{
158 size_t nCount = maList.size();
159
160 for ( size_t i = 0; i < nCount; i++ )
161 {
162 IMapObject* pObj = maList[ i ].get();
163
164 switch( pObj->GetType() )
165 {
167 static_cast<IMapRectangleObject*>( pObj )->WriteCERN( rOStm );
168 break;
169
171 static_cast<IMapCircleObject*>( pObj )->WriteCERN( rOStm );
172 break;
173
175 static_cast<IMapPolygonObject*>( pObj )->WriteCERN( rOStm );
176 break;
177
178 default:
179 break;
180 }
181 }
182}
183
185{
186 size_t nCount = maList.size();
187
188 for ( size_t i = 0; i < nCount; i++ )
189 {
190 IMapObject* pObj = maList[ i ].get();
191
192 switch( pObj->GetType() )
193 {
195 static_cast<IMapRectangleObject*>( pObj )->WriteNCSA( rOStm );
196 break;
197
199 static_cast<IMapCircleObject*>( pObj )->WriteNCSA( rOStm );
200 break;
201
203 static_cast<IMapPolygonObject*>( pObj )->WriteNCSA( rOStm );
204 break;
205
206 default:
207 break;
208 }
209 }
210}
211
213{
215
216 if ( nFormat == IMapFormat::Detect )
217 nFormat = ImpDetectFormat( rIStm );
218
219 switch ( nFormat )
220 {
221 case IMapFormat::Binary : Read( rIStm ); break;
222 case IMapFormat::CERN : ImpReadCERN( rIStm ); break;
223 case IMapFormat::NCSA : ImpReadNCSA( rIStm ); break;
224
225 default:
226 break;
227 }
228
229 if ( !rIStm.GetError() )
230 nRet = IMAP_ERR_OK;
231
232 return nRet;
233}
234
236{
237 // delete old content
239
240 OStringBuffer aStr;
241 while ( rIStm.ReadLine( aStr ) )
243}
244
245void ImageMap::ImpReadCERNLine( std::string_view rLine )
246{
247 OString aStr( comphelper::string::stripStart(rLine, ' ') );
249 aStr = aStr.replaceAll(";", "");
250 aStr = aStr.toAsciiLowerCase();
251
252 const char* pStr = aStr.getStr();
253 char cChar = *pStr++;
254
255 // find instruction
256 OStringBuffer aBuf;
257 while ((cChar >= 'a') && (cChar <= 'z'))
258 {
259 aBuf.append(cChar);
260 cChar = *pStr++;
261 }
262 OString aToken = aBuf.makeStringAndClear();
263
264 if ( !(NOTEOL( cChar )) )
265 return;
266
267 if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) )
268 {
269 const Point aTopLeft( ImpReadCERNCoords( &pStr ) );
270 const Point aBottomRight( ImpReadCERNCoords( &pStr ) );
271 const OUString aURL( ImpReadCERNURL( &pStr ) );
272 const tools::Rectangle aRect( aTopLeft, aBottomRight );
273
274 maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) );
275 }
276 else if ( ( aToken == "circle" ) || ( aToken == "circ" ) )
277 {
278 const Point aCenter( ImpReadCERNCoords( &pStr ) );
279 const tools::Long nRadius = ImpReadCERNRadius( &pStr );
280 const OUString aURL( ImpReadCERNURL( &pStr ) );
281
282 maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) );
283 }
284 else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) )
285 {
286 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, '(') - 1;
287 tools::Polygon aPoly( nCount );
288
289 for ( sal_uInt16 i = 0; i < nCount; i++ )
290 aPoly[ i ] = ImpReadCERNCoords( &pStr );
291
292 const OUString aURL = ImpReadCERNURL( &pStr );
293
294 maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) );
295 }
296}
297
299{
300 OUStringBuffer aStrX;
301 OUStringBuffer aStrY;
302 Point aPt;
303 char cChar = *(*ppStr)++;
304
305 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
306 cChar = *(*ppStr)++;
307
308 if ( NOTEOL( cChar ) )
309 {
310 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
311 {
312 aStrX.append( cChar );
313 cChar = *(*ppStr)++;
314 }
315
316 if ( NOTEOL( cChar ) )
317 {
318 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
319 cChar = *(*ppStr)++;
320
321 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
322 {
323 aStrY.append( cChar );
324 cChar = *(*ppStr)++;
325 }
326
327 if ( NOTEOL( cChar ) )
328 while( NOTEOL( cChar ) && ( cChar != ')' ) )
329 cChar = *(*ppStr)++;
330
331 aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) );
332 }
333 }
334
335 return aPt;
336}
337
339{
340 OUStringBuffer aStr;
341 char cChar = *(*ppStr)++;
342
343 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
344 cChar = *(*ppStr)++;
345
346 if ( NOTEOL( cChar ) )
347 {
348 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
349 {
350 aStr.append( cChar );
351 cChar = *(*ppStr)++;
352 }
353 }
354
355 return o3tl::toInt32(aStr);
356}
357
358OUString ImageMap::ImpReadCERNURL( const char** ppStr )
359{
360 OUString aStr(OUString::createFromAscii(*ppStr));
361
364
365 return INetURLObject::GetAbsURL( u"", aStr );
366}
367
369{
370 // delete old content
372
373 OStringBuffer aStr;
374 while ( rIStm.ReadLine( aStr ) )
376}
377
378void ImageMap::ImpReadNCSALine( std::string_view rLine )
379{
380 OString aStr( comphelper::string::stripStart(rLine, ' ') );
382 aStr = aStr.replaceAll(";", "");
383 aStr = aStr.toAsciiLowerCase();
384
385 const char* pStr = aStr.getStr();
386 char cChar = *pStr++;
387
388 // find instruction
389 OStringBuffer aBuf;
390 while ((cChar >= 'a') && (cChar <= 'z'))
391 {
392 aBuf.append(cChar);
393 cChar = *pStr++;
394 }
395 OString aToken = aBuf.makeStringAndClear();
396
397 if ( !(NOTEOL( cChar )) )
398 return;
399
400 if ( aToken == "rect" )
401 {
402 const OUString aURL( ImpReadNCSAURL( &pStr ) );
403 const Point aTopLeft( ImpReadNCSACoords( &pStr ) );
404 const Point aBottomRight( ImpReadNCSACoords( &pStr ) );
405 const tools::Rectangle aRect( aTopLeft, aBottomRight );
406
407 maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) );
408 }
409 else if ( aToken == "circle" )
410 {
411 const OUString aURL( ImpReadNCSAURL( &pStr ) );
412 const Point aCenter( ImpReadNCSACoords( &pStr ) );
413 const Point aDX( aCenter - ImpReadNCSACoords( &pStr ) );
414 tools::Long nRadius = static_cast<tools::Long>(std::hypot( aDX.X(), aDX.Y()));
415
416 maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) );
417 }
418 else if ( aToken == "poly" )
419 {
420 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, ',') - 1;
421 const OUString aURL( ImpReadNCSAURL( &pStr ) );
422 tools::Polygon aPoly( nCount );
423
424 for ( sal_uInt16 i = 0; i < nCount; i++ )
425 aPoly[ i ] = ImpReadNCSACoords( &pStr );
426
427 maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) );
428 }
429}
430
431OUString ImageMap::ImpReadNCSAURL( const char** ppStr )
432{
433 OUStringBuffer aStr;
434 char cChar = *(*ppStr)++;
435
436 while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) )
437 cChar = *(*ppStr)++;
438
439 if ( NOTEOL( cChar ) )
440 {
441 while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) )
442 {
443 aStr.append( cChar );
444 cChar = *(*ppStr)++;
445 }
446 }
447
448 return INetURLObject::GetAbsURL( u"", aStr.makeStringAndClear() );
449}
450
452{
453 OUStringBuffer aStrX;
454 OUStringBuffer aStrY;
455 Point aPt;
456 char cChar = *(*ppStr)++;
457
458 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
459 cChar = *(*ppStr)++;
460
461 if ( NOTEOL( cChar ) )
462 {
463 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
464 {
465 aStrX.append( cChar );
466 cChar = *(*ppStr)++;
467 }
468
469 if ( NOTEOL( cChar ) )
470 {
471 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
472 cChar = *(*ppStr)++;
473
474 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
475 {
476 aStrY.append( cChar );
477 cChar = *(*ppStr)++;
478 }
479
480 aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) );
481 }
482 }
483
484 return aPt;
485}
486
488{
489 sal_uInt64 nPos = rIStm.Tell();
491 char cMagic[6];
492
493 rIStm.ReadBytes(cMagic, sizeof(cMagic));
494
495 // if we do not have an internal formats
496 // we check the format
497 if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
498 {
499 tools::Long nCount = 128;
500
501 rIStm.Seek( nPos );
502 OString aStr;
503 while ( rIStm.ReadLine( aStr ) && nCount-- )
504 {
505 aStr = aStr.toAsciiLowerCase();
506
507 if ( (aStr.indexOf("rect") != -1) ||
508 (aStr.indexOf("circ") != -1) ||
509 (aStr.indexOf("poly") != -1) )
510 {
511 if ( ( aStr.indexOf('(') != -1 ) &&
512 ( aStr.indexOf(')') != -1 ) )
513 {
514 nRet = IMapFormat::CERN;
515 }
516 else
517 nRet = IMapFormat::NCSA;
518
519 break;
520 }
521 }
522 }
523
524 rIStm.Seek( nPos );
525
526 return nRet;
527}
528
529/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1172
sal_Int32 nRadius
Definition: imapcirc.hxx:31
void WriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:94
void WriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:106
void AppendNCSAURL(OStringBuffer &rBuf) const
Definition: imap2.cxx:66
virtual IMapObjectType GetType() const =0
void AppendCERNURL(OStringBuffer &rBuf) const
Definition: imap2.cxx:61
static void AppendNCSACoords(OStringBuffer &rBuf, const Point &rPoint100)
Definition: imap2.cxx:51
OUString aURL
Definition: imapobj.hxx:59
static void AppendCERNCoords(OStringBuffer &rBuf, const Point &rPoint100)
Definition: imap2.cxx:40
void WriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:117
void WriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:130
tools::Polygon aPoly
Definition: imappoly.hxx:31
void WriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:83
tools::Rectangle aRect
Definition: imaprect.hxx:30
void WriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:72
static OUString GetAbsURL(std::u16string_view rTheBaseURIRef, OUString const &rTheRelURIRef, EncodeMechanism eEncodeMechanism=EncodeMechanism::WasEncoded, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
void ImpReadCERN(SvStream &rOStm)
Definition: imap2.cxx:235
void ImpReadCERNLine(std::string_view rLine)
Definition: imap2.cxx:245
void ImpReadNCSA(SvStream &rOStm)
Definition: imap2.cxx:368
static Point ImpReadCERNCoords(const char **ppStr)
Definition: imap2.cxx:298
void Write(SvStream &rOStm) const
Definition: imap.cxx:913
static OUString ImpReadNCSAURL(const char **ppStr)
Definition: imap2.cxx:431
void ImpWriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:156
void ImpReadNCSALine(std::string_view rLine)
Definition: imap2.cxx:378
std::vector< std::unique_ptr< IMapObject > > maList
Definition: imap.hxx:39
void Read(SvStream &rIStm)
Definition: imap.cxx:949
static Point ImpReadNCSACoords(const char **ppStr)
Definition: imap2.cxx:451
static IMapFormat ImpDetectFormat(SvStream &rIStm)
Definition: imap2.cxx:487
static OUString ImpReadCERNURL(const char **ppStr)
Definition: imap2.cxx:358
static tools::Long ImpReadCERNRadius(const char **ppStr)
Definition: imap2.cxx:338
void ClearImageMap()
Definition: imap.cxx:608
void ImpWriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:184
sal_uInt64 Tell() const
bool WriteLine(std::string_view rStr)
bool ReadLine(OStringBuffer &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
ErrCode GetError() const
sal_uInt16 GetSize() const
constexpr Point TopLeft() const
constexpr Point BottomRight() const
int nCount
URL aURL
float u
#define NOTEOL(c)
Definition: imap2.cxx:38
IMapFormat
Definition: imapobj.hxx:45
#define IMAPMAGIC
Definition: imapobj.hxx:39
#define IMAP_ERR_OK
Definition: imapobj.hxx:52
#define IMAP_ERR_FORMAT
Definition: imapobj.hxx:53
sal_uInt16 nPos
aStr
aBuf
SVL_DLLPUBLIC OUString simpleNormalizedMakeRelative(OUString const &baseUriReference, OUString const &uriReference)
OString strip(const OString &rIn, char c)
OString stripStart(const OString &rIn, char c)
sal_Int32 getTokenCount(std::string_view rIn, char cTok)
int i
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
long Long
sal_uIntPtr sal_uLong