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(OString::number(nRadius) + " ");
100 AppendCERNURL(aStrBuf);
101
102 rOStm.WriteLine(aStrBuf);
103}
104
106{
107 OStringBuffer aStrBuf("circle ");
108
109 AppendNCSAURL(aStrBuf);
110 AppendNCSACoords(aStrBuf, aCenter);
111 AppendNCSACoords(aStrBuf, aCenter + Point(nRadius, 0));
112
113 rOStm.WriteLine(aStrBuf);
114}
115
117{
118 OStringBuffer aStrBuf("polygon ");
119 const sal_uInt16 nCount = aPoly.GetSize();
120
121 for (sal_uInt16 i = 0; i < nCount; ++i)
122 AppendCERNCoords(aStrBuf, aPoly[i]);
123
124 AppendCERNURL(aStrBuf);
125
126 rOStm.WriteLine(aStrBuf);
127}
128
130{
131 OStringBuffer aStrBuf("poly ");
132 const sal_uInt16 nCount = std::min( aPoly.GetSize(), sal_uInt16(100) );
133
134 AppendNCSAURL(aStrBuf);
135
136 for (sal_uInt16 i = 0; i < nCount; ++i)
137 AppendNCSACoords(aStrBuf, aPoly[i]);
138
139 rOStm.WriteLine(aStrBuf);
140}
141
142void ImageMap::Write( SvStream& rOStm, IMapFormat nFormat ) const
143{
144 switch( nFormat )
145 {
146 case IMapFormat::Binary : Write( rOStm ); break;
147 case IMapFormat::CERN : ImpWriteCERN( rOStm ); break;
148 case IMapFormat::NCSA : ImpWriteNCSA( rOStm ); break;
149
150 default:
151 break;
152 }
153}
154
156{
157 size_t nCount = maList.size();
158
159 for ( size_t i = 0; i < nCount; i++ )
160 {
161 IMapObject* pObj = maList[ i ].get();
162
163 switch( pObj->GetType() )
164 {
166 static_cast<IMapRectangleObject*>( pObj )->WriteCERN( rOStm );
167 break;
168
170 static_cast<IMapCircleObject*>( pObj )->WriteCERN( rOStm );
171 break;
172
174 static_cast<IMapPolygonObject*>( pObj )->WriteCERN( rOStm );
175 break;
176
177 default:
178 break;
179 }
180 }
181}
182
184{
185 size_t nCount = maList.size();
186
187 for ( size_t i = 0; i < nCount; i++ )
188 {
189 IMapObject* pObj = maList[ i ].get();
190
191 switch( pObj->GetType() )
192 {
194 static_cast<IMapRectangleObject*>( pObj )->WriteNCSA( rOStm );
195 break;
196
198 static_cast<IMapCircleObject*>( pObj )->WriteNCSA( rOStm );
199 break;
200
202 static_cast<IMapPolygonObject*>( pObj )->WriteNCSA( rOStm );
203 break;
204
205 default:
206 break;
207 }
208 }
209}
210
212{
214
215 if ( nFormat == IMapFormat::Detect )
216 nFormat = ImpDetectFormat( rIStm );
217
218 switch ( nFormat )
219 {
220 case IMapFormat::Binary : Read( rIStm ); break;
221 case IMapFormat::CERN : ImpReadCERN( rIStm ); break;
222 case IMapFormat::NCSA : ImpReadNCSA( rIStm ); break;
223
224 default:
225 break;
226 }
227
228 if ( !rIStm.GetError() )
229 nRet = IMAP_ERR_OK;
230
231 return nRet;
232}
233
235{
236 // delete old content
238
239 OStringBuffer aStr;
240 while ( rIStm.ReadLine( aStr ) )
242}
243
244void ImageMap::ImpReadCERNLine( std::string_view rLine )
245{
246 OString aStr( comphelper::string::stripStart(rLine, ' ') );
248 aStr = aStr.replaceAll(";", "");
249 aStr = aStr.toAsciiLowerCase();
250
251 const char* pStr = aStr.getStr();
252 char cChar = *pStr++;
253
254 // find instruction
255 OStringBuffer aBuf;
256 while ((cChar >= 'a') && (cChar <= 'z'))
257 {
258 aBuf.append(cChar);
259 cChar = *pStr++;
260 }
261 OString aToken = aBuf.makeStringAndClear();
262
263 if ( !(NOTEOL( cChar )) )
264 return;
265
266 if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) )
267 {
268 const Point aTopLeft( ImpReadCERNCoords( &pStr ) );
269 const Point aBottomRight( ImpReadCERNCoords( &pStr ) );
270 const OUString aURL( ImpReadCERNURL( &pStr ) );
271 const tools::Rectangle aRect( aTopLeft, aBottomRight );
272
273 maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) );
274 }
275 else if ( ( aToken == "circle" ) || ( aToken == "circ" ) )
276 {
277 const Point aCenter( ImpReadCERNCoords( &pStr ) );
278 const tools::Long nRadius = ImpReadCERNRadius( &pStr );
279 const OUString aURL( ImpReadCERNURL( &pStr ) );
280
281 maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) );
282 }
283 else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) )
284 {
285 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, '(') - 1;
286 tools::Polygon aPoly( nCount );
287
288 for ( sal_uInt16 i = 0; i < nCount; i++ )
289 aPoly[ i ] = ImpReadCERNCoords( &pStr );
290
291 const OUString aURL = ImpReadCERNURL( &pStr );
292
293 maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) );
294 }
295}
296
298{
299 OUStringBuffer aStrX;
300 OUStringBuffer aStrY;
301 Point aPt;
302 char cChar = *(*ppStr)++;
303
304 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
305 cChar = *(*ppStr)++;
306
307 if ( NOTEOL( cChar ) )
308 {
309 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
310 {
311 aStrX.append( cChar );
312 cChar = *(*ppStr)++;
313 }
314
315 if ( NOTEOL( cChar ) )
316 {
317 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
318 cChar = *(*ppStr)++;
319
320 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
321 {
322 aStrY.append( cChar );
323 cChar = *(*ppStr)++;
324 }
325
326 if ( NOTEOL( cChar ) )
327 while( NOTEOL( cChar ) && ( cChar != ')' ) )
328 cChar = *(*ppStr)++;
329
330 aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) );
331 }
332 }
333
334 return aPt;
335}
336
338{
339 OUStringBuffer aStr;
340 char cChar = *(*ppStr)++;
341
342 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
343 cChar = *(*ppStr)++;
344
345 if ( NOTEOL( cChar ) )
346 {
347 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
348 {
349 aStr.append( cChar );
350 cChar = *(*ppStr)++;
351 }
352 }
353
354 return o3tl::toInt32(aStr);
355}
356
357OUString ImageMap::ImpReadCERNURL( const char** ppStr )
358{
359 OUString aStr(OUString::createFromAscii(*ppStr));
360
363
364 return INetURLObject::GetAbsURL( u"", aStr );
365}
366
368{
369 // delete old content
371
372 OStringBuffer aStr;
373 while ( rIStm.ReadLine( aStr ) )
375}
376
377void ImageMap::ImpReadNCSALine( std::string_view rLine )
378{
379 OString aStr( comphelper::string::stripStart(rLine, ' ') );
381 aStr = aStr.replaceAll(";", "");
382 aStr = aStr.toAsciiLowerCase();
383
384 const char* pStr = aStr.getStr();
385 char cChar = *pStr++;
386
387 // find instruction
388 OStringBuffer aBuf;
389 while ((cChar >= 'a') && (cChar <= 'z'))
390 {
391 aBuf.append(cChar);
392 cChar = *pStr++;
393 }
394 OString aToken = aBuf.makeStringAndClear();
395
396 if ( !(NOTEOL( cChar )) )
397 return;
398
399 if ( aToken == "rect" )
400 {
401 const OUString aURL( ImpReadNCSAURL( &pStr ) );
402 const Point aTopLeft( ImpReadNCSACoords( &pStr ) );
403 const Point aBottomRight( ImpReadNCSACoords( &pStr ) );
404 const tools::Rectangle aRect( aTopLeft, aBottomRight );
405
406 maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) );
407 }
408 else if ( aToken == "circle" )
409 {
410 const OUString aURL( ImpReadNCSAURL( &pStr ) );
411 const Point aCenter( ImpReadNCSACoords( &pStr ) );
412 const Point aDX( aCenter - ImpReadNCSACoords( &pStr ) );
413 tools::Long nRadius = static_cast<tools::Long>(std::hypot( aDX.X(), aDX.Y()));
414
415 maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) );
416 }
417 else if ( aToken == "poly" )
418 {
419 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, ',') - 1;
420 const OUString aURL( ImpReadNCSAURL( &pStr ) );
421 tools::Polygon aPoly( nCount );
422
423 for ( sal_uInt16 i = 0; i < nCount; i++ )
424 aPoly[ i ] = ImpReadNCSACoords( &pStr );
425
426 maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) );
427 }
428}
429
430OUString ImageMap::ImpReadNCSAURL( const char** ppStr )
431{
432 OUStringBuffer aStr;
433 char cChar = *(*ppStr)++;
434
435 while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) )
436 cChar = *(*ppStr)++;
437
438 if ( NOTEOL( cChar ) )
439 {
440 while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) )
441 {
442 aStr.append( cChar );
443 cChar = *(*ppStr)++;
444 }
445 }
446
447 return INetURLObject::GetAbsURL( u"", aStr.makeStringAndClear() );
448}
449
451{
452 OUStringBuffer aStrX;
453 OUStringBuffer aStrY;
454 Point aPt;
455 char cChar = *(*ppStr)++;
456
457 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
458 cChar = *(*ppStr)++;
459
460 if ( NOTEOL( cChar ) )
461 {
462 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
463 {
464 aStrX.append( cChar );
465 cChar = *(*ppStr)++;
466 }
467
468 if ( NOTEOL( cChar ) )
469 {
470 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
471 cChar = *(*ppStr)++;
472
473 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
474 {
475 aStrY.append( cChar );
476 cChar = *(*ppStr)++;
477 }
478
479 aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) );
480 }
481 }
482
483 return aPt;
484}
485
487{
488 sal_uInt64 nPos = rIStm.Tell();
490 char cMagic[6];
491
492 rIStm.ReadBytes(cMagic, sizeof(cMagic));
493
494 // if we do not have an internal formats
495 // we check the format
496 if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
497 {
498 tools::Long nCount = 128;
499
500 rIStm.Seek( nPos );
501 OString aStr;
502 while ( rIStm.ReadLine( aStr ) && nCount-- )
503 {
504 aStr = aStr.toAsciiLowerCase();
505
506 if ( (aStr.indexOf("rect") != -1) ||
507 (aStr.indexOf("circ") != -1) ||
508 (aStr.indexOf("poly") != -1) )
509 {
510 if ( ( aStr.indexOf('(') != -1 ) &&
511 ( aStr.indexOf(')') != -1 ) )
512 {
513 nRet = IMapFormat::CERN;
514 }
515 else
516 nRet = IMapFormat::NCSA;
517
518 break;
519 }
520 }
521 }
522
523 rIStm.Seek( nPos );
524
525 return nRet;
526}
527
528/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OutputDevice * GetDefaultDevice()
Get the default "device" (in this case the default window).
Definition: svapp.cxx:1043
sal_Int32 nRadius
Definition: imapcirc.hxx:31
void WriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:94
void WriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:105
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:116
void WriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:129
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:234
void ImpReadCERNLine(std::string_view rLine)
Definition: imap2.cxx:244
void ImpReadNCSA(SvStream &rOStm)
Definition: imap2.cxx:367
static Point ImpReadCERNCoords(const char **ppStr)
Definition: imap2.cxx:297
void Write(SvStream &rOStm) const
Definition: imap.cxx:913
static OUString ImpReadNCSAURL(const char **ppStr)
Definition: imap2.cxx:430
void ImpWriteCERN(SvStream &rOStm) const
Definition: imap2.cxx:155
void ImpReadNCSALine(std::string_view rLine)
Definition: imap2.cxx:377
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:450
static IMapFormat ImpDetectFormat(SvStream &rIStm)
Definition: imap2.cxx:486
static OUString ImpReadCERNURL(const char **ppStr)
Definition: imap2.cxx:357
static tools::Long ImpReadCERNRadius(const char **ppStr)
Definition: imap2.cxx:337
void ClearImageMap()
Definition: imap.cxx:608
void ImpWriteNCSA(SvStream &rOStm) const
Definition: imap2.cxx:183
constexpr tools::Long Y() const
constexpr tools::Long X() const
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