LibreOffice Module sdext (master)  1
wrapper.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 #include <config_folders.h>
21 
22 #include <contentsink.hxx>
23 #include <pdfparse.hxx>
24 #include <pdfihelper.hxx>
25 #include <wrapper.hxx>
26 
27 #include <o3tl/string_view.hxx>
28 #include <osl/file.h>
29 #include <osl/file.hxx>
30 #include <osl/thread.h>
31 #include <osl/process.h>
32 #include <osl/diagnose.h>
33 #include <rtl/bootstrap.hxx>
34 #include <rtl/ustring.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <rtl/strbuf.hxx>
37 #include <sal/log.hxx>
38 
40 #include <com/sun/star/io/XInputStream.hpp>
41 #include <com/sun/star/uno/XComponentContext.hpp>
42 #include <com/sun/star/awt/FontDescriptor.hpp>
43 #include <com/sun/star/beans/XMaterialHolder.hpp>
44 #include <com/sun/star/rendering/PathCapType.hpp>
45 #include <com/sun/star/rendering/PathJoinType.hpp>
46 #include <com/sun/star/rendering/XPolyPolygon2D.hpp>
47 #include <com/sun/star/geometry/Matrix2D.hpp>
48 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
49 #include <com/sun/star/geometry/RealRectangle2D.hpp>
50 #include <com/sun/star/geometry/RealSize2D.hpp>
51 #include <com/sun/star/task/XInteractionHandler.hpp>
52 #include <com/sun/star/awt/FontWeight.hpp>
53 #include <tools/diagnose_ex.h>
54 
59 
60 #include <vcl/metric.hxx>
61 #include <vcl/font.hxx>
62 #include <vcl/virdev.hxx>
63 
64 #include <cstddef>
65 #include <memory>
66 #include <string_view>
67 #include <unordered_map>
68 #include <string.h>
69 #include <stdlib.h>
70 
71 #include <rtl/character.hxx>
72 
73 using namespace com::sun::star;
74 
75 namespace pdfi
76 {
77 
78 namespace
79 {
80 
81 // identifier of the strings coming from the out-of-process xpdf
82 // converter
83 enum parseKey {
84  CLIPPATH,
85  DRAWCHAR,
86  DRAWIMAGE,
87  DRAWLINK,
88  DRAWMASK,
89  DRAWMASKEDIMAGE,
90  DRAWSOFTMASKEDIMAGE,
91  ENDPAGE,
92  ENDTEXTOBJECT,
93  EOCLIPPATH,
94  EOFILLPATH,
95  FILLPATH,
96  HYPERLINK,
97  INTERSECTCLIP,
98  INTERSECTEOCLIP,
99  POPSTATE,
100  PUSHSTATE,
101  RESTORESTATE,
102  SAVESTATE,
103  SETBLENDMODE,
104  SETFILLCOLOR,
105  SETFONT,
106  SETLINECAP,
107  SETLINEDASH,
108  SETLINEJOIN,
109  SETLINEWIDTH,
110  SETMITERLIMIT,
111  SETPAGENUM,
112  SETSTROKECOLOR,
113  SETTEXTRENDERMODE,
114  SETTRANSFORMATION,
115  STARTPAGE,
116  STROKEPATH,
117  UPDATEBLENDMODE,
118  UPDATECTM,
119  UPDATEFILLCOLOR,
120  UPDATEFILLOPACITY,
121  UPDATEFLATNESS,
122  UPDATEFONT,
123  UPDATELINECAP,
124  UPDATELINEDASH,
125  UPDATELINEJOIN,
126  UPDATELINEWIDTH,
127  UPDATEMITERLIMIT,
128  UPDATESTROKECOLOR,
129  UPDATESTROKEOPACITY,
130  NONE
131 };
132 
133 #if defined _MSC_VER && defined __clang__
134 #pragma clang diagnostic push
135 #pragma clang diagnostic ignored "-Wdeprecated-register"
136 #pragma clang diagnostic ignored "-Wextra-tokens"
137 #endif
138 #include <hash.cxx>
139 #if defined _MSC_VER && defined __clang__
140 #pragma clang diagnostic pop
141 #endif
142 
143 class Parser
144 {
145  friend class LineParser;
146 
147  typedef std::unordered_map< sal_Int64,
148  FontAttributes > FontMapType;
149 
151  const uno::Reference<uno::XComponentContext> m_xContext;
153  const oslFileHandle m_pErr;
154  FontMapType m_aFontMap;
155 
156 public:
157  Parser( const ContentSinkSharedPtr& rSink,
158  oslFileHandle pErr,
159  const uno::Reference<uno::XComponentContext>& xContext ) :
160  m_xContext(xContext),
161  m_pSink(rSink),
162  m_pErr(pErr),
163  m_aFontMap(101)
164  {}
165 
166  void parseLine( const OString& rLine );
167 };
168 
169 class LineParser {
170  Parser & m_parser;
171  OString m_aLine;
172 
173  static void parseFontFamilyName( FontAttributes& aResult );
174  void readInt32( sal_Int32& o_Value );
175  void readInt64( sal_Int64& o_Value );
176  void readDouble( double& o_Value );
177  void readBinaryData( uno::Sequence<sal_Int8>& rBuf );
178 
179  uno::Sequence<beans::PropertyValue> readImageImpl();
180 
181 public:
182  std::size_t m_nCharIndex = 0;
183 
184  LineParser(Parser & parser, OString const & line): m_parser(parser), m_aLine(line) {}
185 
186  std::string_view readNextToken();
187  sal_Int32 readInt32();
188  double readDouble();
189 
190  uno::Reference<rendering::XPolyPolygon2D> readPath();
191 
192  void readChar();
193  void readLineCap();
194  void readLineDash();
195  void readLineJoin();
196  void readTransformation();
197  rendering::ARGBColor readColor();
198  void readFont();
199 
200  void readImage();
201  void readMask();
202  void readLink();
203  void readMaskedImage();
204  void readSoftMaskedImage();
205 };
206 
211 OString lcl_unescapeLineFeeds(std::string_view i_rStr)
212 {
213  const size_t nOrigLen(i_rStr.size());
214  const char* const pOrig(i_rStr.data());
215  std::unique_ptr<char[]> pBuffer(new char[nOrigLen + 1]);
216 
217  const char* pRead(pOrig);
218  char* pWrite(pBuffer.get());
219  const char* pCur(pOrig);
220  while ((pCur = strchr(pCur, '\\')) != nullptr)
221  {
222  const char cNext(pCur[1]);
223  if (cNext == 'n' || cNext == 'r' || cNext == '\\')
224  {
225  const size_t nLen(pCur - pRead);
226  strncpy(pWrite, pRead, nLen);
227  pWrite += nLen;
228  *pWrite = cNext == 'n' ? '\n' : (cNext == 'r' ? '\r' : '\\');
229  ++pWrite;
230  pCur = pRead = pCur + 2;
231  }
232  else
233  {
234  // Just continue on the next character. The current
235  // block will be copied the next time it goes through the
236  // 'if' branch.
237  ++pCur;
238  }
239  }
240  // maybe there are some data to copy yet
241  if (sal::static_int_cast<size_t>(pRead - pOrig) < nOrigLen)
242  {
243  const size_t nLen(nOrigLen - (pRead - pOrig));
244  strncpy(pWrite, pRead, nLen);
245  pWrite += nLen;
246  }
247  *pWrite = '\0';
248 
249  OString aResult(pBuffer.get());
250  return aResult;
251 }
252 
253 std::string_view LineParser::readNextToken()
254 {
255  if (m_nCharIndex == std::string_view::npos) {
256  SAL_WARN("sdext.pdfimport", "insufficient input");
257  return {};
258  }
259  return o3tl::getToken(m_aLine,' ',m_nCharIndex);
260 }
261 
262 void LineParser::readInt32( sal_Int32& o_Value )
263 {
264  std::string_view tok = readNextToken();
265  sal_Int64 n = rtl_str_toInt64_WithLength(tok.data(), 10, tok.size());
266  if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
267  n = 0;
268  o_Value = n;
269 }
270 
271 sal_Int32 LineParser::readInt32()
272 {
273  std::string_view tok = readNextToken();
274  sal_Int64 n =rtl_str_toInt64_WithLength(tok.data(), 10, tok.size());
275  if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
276  n = 0;
277  return n;
278 }
279 
280 void LineParser::readInt64( sal_Int64& o_Value )
281 {
282  std::string_view tok = readNextToken();
283  o_Value = rtl_str_toInt64_WithLength(tok.data(), 10, tok.size());
284 }
285 
286 void LineParser::readDouble( double& o_Value )
287 {
288  std::string_view tok = readNextToken();
289  o_Value = rtl_math_stringToDouble(tok.data(), tok.data() + tok.size(), '.', 0,
290  nullptr, nullptr);
291 }
292 
293 double LineParser::readDouble()
294 {
295  std::string_view tok = readNextToken();
296  return rtl_math_stringToDouble(tok.data(), tok.data() + tok.size(), '.', 0,
297  nullptr, nullptr);
298 }
299 
300 void LineParser::readBinaryData( uno::Sequence<sal_Int8>& rBuf )
301 {
302  sal_Int32 nFileLen( rBuf.getLength() );
303  sal_Int8* pBuf( rBuf.getArray() );
304  sal_uInt64 nBytesRead(0);
305  oslFileError nRes=osl_File_E_None;
306  while( nFileLen )
307  {
308  nRes = osl_readFile( m_parser.m_pErr, pBuf, nFileLen, &nBytesRead );
309  if (osl_File_E_None != nRes )
310  break;
311  pBuf += nBytesRead;
312  nFileLen -= sal::static_int_cast<sal_Int32>(nBytesRead);
313  }
314 
315  OSL_PRECOND(nRes==osl_File_E_None, "inconsistent data");
316 }
317 
318 uno::Reference<rendering::XPolyPolygon2D> LineParser::readPath()
319 {
320  static const std::string_view aSubPathMarker( "subpath" );
321 
322  if( readNextToken() != aSubPathMarker )
323  OSL_PRECOND(false, "broken path");
324 
325  basegfx::B2DPolyPolygon aResult;
326  while( m_nCharIndex != std::string_view::npos )
327  {
328  basegfx::B2DPolygon aSubPath;
329 
330  sal_Int32 nClosedFlag;
331  readInt32( nClosedFlag );
332  aSubPath.setClosed( nClosedFlag != 0 );
333 
334  sal_Int32 nContiguousControlPoints(0);
335 
336  while( m_nCharIndex != std::string_view::npos )
337  {
338  std::size_t nDummy=m_nCharIndex;
339  if (o3tl::getToken(m_aLine,' ',nDummy) == aSubPathMarker) {
340  break;
341  }
342 
343  sal_Int32 nCurveFlag;
344  double nX, nY;
345  readDouble( nX );
346  readDouble( nY );
347  readInt32( nCurveFlag );
348 
349  aSubPath.append(basegfx::B2DPoint(nX,nY));
350  if( nCurveFlag )
351  {
352  ++nContiguousControlPoints;
353  }
354  else if( nContiguousControlPoints )
355  {
356  OSL_PRECOND(nContiguousControlPoints==2,"broken bezier path");
357 
358  // have two control points before us. the current one
359  // is a normal point - thus, convert previous points
360  // into bezier segment
361  const sal_uInt32 nPoints( aSubPath.count() );
362  const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) );
363  const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) );
364  const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) );
365  aSubPath.remove(nPoints-3, 3);
366  aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd);
367 
368  nContiguousControlPoints=0;
369  }
370  }
371 
372  aResult.append( aSubPath );
373  if( m_nCharIndex != std::string_view::npos )
374  readNextToken();
375  }
376 
377  return static_cast<rendering::XLinePolyPolygon2D*>(
378  new basegfx::unotools::UnoPolyPolygon(aResult));
379 }
380 
381 void LineParser::readChar()
382 {
383  double fontSize;
384  geometry::Matrix2D aUnoMatrix;
385  geometry::RealRectangle2D aRect;
386 
387  readDouble(aRect.X1);
388  readDouble(aRect.Y1);
389  readDouble(aRect.X2);
390  readDouble(aRect.Y2);
391  readDouble(aUnoMatrix.m00);
392  readDouble(aUnoMatrix.m01);
393  readDouble(aUnoMatrix.m10);
394  readDouble(aUnoMatrix.m11);
395  readDouble(fontSize);
396 
397  OString aChars;
398 
399  if (m_nCharIndex != std::string_view::npos)
400  aChars = lcl_unescapeLineFeeds( m_aLine.subView( m_nCharIndex ) );
401 
402  // chars gobble up rest of line
403  m_nCharIndex = std::string_view::npos;
404 
405  m_parser.m_pSink->drawGlyphs(OStringToOUString(aChars, RTL_TEXTENCODING_UTF8),
406  aRect, aUnoMatrix, fontSize);
407 }
408 
409 void LineParser::readLineCap()
410 {
411  sal_Int8 nCap(rendering::PathCapType::BUTT);
412  switch( readInt32() )
413  {
414  default:
415  case 0: nCap = rendering::PathCapType::BUTT; break;
416  case 1: nCap = rendering::PathCapType::ROUND; break;
417  case 2: nCap = rendering::PathCapType::SQUARE; break;
418  }
419  m_parser.m_pSink->setLineCap(nCap);
420 }
421 
422 void LineParser::readLineDash()
423 {
424  if( m_nCharIndex == std::string_view::npos )
425  {
426  m_parser.m_pSink->setLineDash( uno::Sequence<double>(), 0.0 );
427  return;
428  }
429 
430  const double nOffset(readDouble());
431  const sal_Int32 nLen(readInt32());
432 
433  uno::Sequence<double> aDashArray(nLen);
434  double* pArray=aDashArray.getArray();
435  for( sal_Int32 i=0; i<nLen; ++i )
436  *pArray++ = readDouble();
437 
438  m_parser.m_pSink->setLineDash( aDashArray, nOffset );
439 }
440 
441 void LineParser::readLineJoin()
442 {
443  sal_Int8 nJoin(rendering::PathJoinType::MITER);
444  switch( readInt32() )
445  {
446  default:
447  case 0: nJoin = rendering::PathJoinType::MITER; break;
448  case 1: nJoin = rendering::PathJoinType::ROUND; break;
449  case 2: nJoin = rendering::PathJoinType::BEVEL; break;
450  }
451  m_parser.m_pSink->setLineJoin(nJoin);
452 }
453 
454 void LineParser::readTransformation()
455 {
456  geometry::AffineMatrix2D aMat;
457  readDouble(aMat.m00);
458  readDouble(aMat.m10);
459  readDouble(aMat.m01);
460  readDouble(aMat.m11);
461  readDouble(aMat.m02);
462  readDouble(aMat.m12);
463  m_parser.m_pSink->setTransformation( aMat );
464 }
465 
466 rendering::ARGBColor LineParser::readColor()
467 {
468  rendering::ARGBColor aRes;
469  readDouble(aRes.Red);
470  readDouble(aRes.Green);
471  readDouble(aRes.Blue);
472  readDouble(aRes.Alpha);
473  return aRes;
474 }
475 
476 /* Parse and convert the font family name (passed from xpdfimport) to correct font names
477 e.g. TimesNewRomanPSMT -> TimesNewRoman
478  TimesNewRomanPS-BoldMT -> TimesNewRoman
479  TimesNewRomanPS-BoldItalicMT -> TimesNewRoman
480 During the conversion, also apply the font features (bold italic etc) to the result.
481 
482 TODO: Further convert the font names to real font names in the system rather than the PS names.
483 e.g., TimesNewRoman -> Times New Roman
484 */
485 void LineParser::parseFontFamilyName( FontAttributes& rResult )
486 {
487  SAL_INFO("sdext.pdfimport", "Processing " << rResult.familyName << " ---");
488  rResult.familyName = rResult.familyName.trim();
489  for (const OUString& fontAttributesSuffix: fontAttributesSuffixes)
490  {
491  if ( rResult.familyName.endsWith(fontAttributesSuffix) )
492  {
493  rResult.familyName = rResult.familyName.replaceAll(fontAttributesSuffix, "");
494  SAL_INFO("sdext.pdfimport", rResult.familyName);
495  if (fontAttributesSuffix == u"Bold")
496  {
497  rResult.fontWeight = u"bold";
498  }
499  else if (fontAttributesSuffix == u"Semibold")
500  {
501  rResult.fontWeight = u"600";
502  }
503  else if (fontAttributesSuffix == u"Light")
504  {
505  rResult.fontWeight = u"300";
506  }
507 
508  if ( (fontAttributesSuffix == "Italic") or (fontAttributesSuffix == "Oblique") )
509  {
510  rResult.isItalic = true;
511  }
512  }
513  }
514 }
515 
516 void LineParser::readFont()
517 {
518  /*
519  xpdf line is like (separated by space):
520  updateFont <FontID> <isEmbedded> <maFontWeight> <isItalic> <isUnderline> <TransformedFontSize> <nEmbedSize> <FontName>
521  updateFont 14 1 4 0 0 1200.000000 23068 TimesNewRomanPSMT
522 
523  If nEmbedSize > 0, then a fontFile is followed as a stream.
524  */
525  sal_Int64 nFontID;
526  sal_Int32 nIsEmbedded;
527  sal_Int32 nFontWeight;
528  sal_Int32 nIsItalic;
529  sal_Int32 nIsUnderline;
530  double nSize;
531  sal_Int32 nFileLen;
532  OString aFontName;
533 
534  readInt64(nFontID); // read FontID
535  readInt32(nIsEmbedded); // read isEmbedded
536  readInt32(nFontWeight); // read maFontWeight, see GfxFont enum Weight
537  readInt32(nIsItalic); // read isItalic
538  readInt32(nIsUnderline);// read isUnderline
539  readDouble(nSize); // read TransformedFontSize
540  readInt32(nFileLen); // read nEmbedSize
541 
542  nSize = nSize < 0.0 ? -nSize : nSize;
543  // Read FontName. From the current position to the end (any white spaces will be included).
544  aFontName = lcl_unescapeLineFeeds(m_aLine.subView(m_nCharIndex));
545 
546  // name gobbles up rest of line
547  m_nCharIndex = std::string_view::npos;
548 
549  // Check if this font is already in our font map list.
550  // If yes, update the font size and skip.
551  Parser::FontMapType::const_iterator pFont( m_parser.m_aFontMap.find(nFontID) );
552  if( pFont != m_parser.m_aFontMap.end() )
553  {
554  OSL_PRECOND(nFileLen==0,"font data for known font");
555  FontAttributes aRes(pFont->second);
556  aRes.size = nSize;
557  m_parser.m_pSink->setFont( aRes );
558 
559  return;
560  }
561 
562  // The font is not yet in the map list - get info and add to map
563  OUString sFontWeight; // font weight name per ODF specifications
564  if (nFontWeight == 0 or nFontWeight == 4) // WeightNotDefined or W400, map to normal font
565  sFontWeight = u"normal";
566  else if (nFontWeight == 1) // W100, Thin
567  sFontWeight = u"100";
568  else if (nFontWeight == 2) // W200, Extra-Light
569  sFontWeight = u"200";
570  else if (nFontWeight == 3) // W300, Light
571  sFontWeight = u"300";
572  else if (nFontWeight == 5) // W500, Medium. Is this supported by ODF?
573  sFontWeight = u"500";
574  else if (nFontWeight == 6) // W600, Semi-Bold
575  sFontWeight = u"600";
576  else if (nFontWeight == 7) // W700, Bold
577  sFontWeight = u"bold";
578  else if (nFontWeight == 8) // W800, Extra-Bold
579  sFontWeight = u"800";
580  else if (nFontWeight == 9) // W900, Black
581  sFontWeight = u"900";
582  SAL_INFO("sdext.pdfimport", "Font weight passed from xpdfimport is: " << sFontWeight);
583 
584  FontAttributes aResult( OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ),
585  sFontWeight,
586  nIsItalic != 0,
587  nIsUnderline != 0,
588  nSize,
589  1.0);
590 
591  /* The above font attributes (fontName, fontWeight, italic) are based on
592  xpdf line output and may not be reliable. To get correct attributes,
593  we do the following:
594  1. Read the embedded font file and determine the attributes based on the
595  font file.
596  2. If we failed to read the font file, or empty result is returned, then
597  determine the font attributes from the font name.
598  3. If all these attempts have failed, then use a fallback font.
599  */
600  if (nFileLen > 0)
601  {
602  uno::Sequence<sal_Int8> aFontFile(nFileLen);
603  readBinaryData(aFontFile); // Read fontFile.
604 
605  vcl::Font aFontReadResult = vcl::Font::identifyFont(aFontFile.getArray(), nFileLen);
606  SAL_INFO("sdext.pdfimport", "familyName: " << aFontReadResult.GetFamilyName());
607 
608  if (!aFontReadResult.GetFamilyName().isEmpty()) // font detection successful
609  {
610  // Family name
611  aResult.familyName = aFontReadResult.GetFamilyName();
612  SAL_INFO("sdext.pdfimport", aResult.familyName);
613  // tdf#143959: there are cases when the family name returned by font descriptor
614  // is like "AAAAAA+TimesNewRoman,Bold". In this case, use the font name
615  // determined by parseFontFamilyName instead, but still determine the font
616  // attributes (bold italic etc) from the font descriptor.
617  if (aResult.familyName.getLength() > 7 and aResult.familyName.indexOf(u"+", 6) == 6)
618  {
619  aResult.familyName = aResult.familyName.copy(7, aResult.familyName.getLength() - 7);
620  parseFontFamilyName(aResult);
621  }
622 
623  // Font weight
624  if (aFontReadResult.GetWeight() == WEIGHT_THIN)
625  aResult.fontWeight = u"100";
626  else if (aFontReadResult.GetWeight() == WEIGHT_ULTRALIGHT)
627  aResult.fontWeight = u"200";
628  else if (aFontReadResult.GetWeight() == WEIGHT_LIGHT)
629  aResult.fontWeight = u"300";
630  else if (aFontReadResult.GetWeight() == WEIGHT_SEMILIGHT)
631  aResult.fontWeight = u"350";
632  // no need to check "normal" here as this is default in nFontWeight above
633  else if (aFontReadResult.GetWeight() == WEIGHT_SEMIBOLD)
634  aResult.fontWeight = u"600";
635  else if (aFontReadResult.GetWeight() == WEIGHT_BOLD)
636  aResult.fontWeight = u"bold";
637  else if (aFontReadResult.GetWeight() == WEIGHT_ULTRABOLD)
638  aResult.fontWeight = u"800";
639  else if (aFontReadResult.GetWeight() == WEIGHT_BLACK)
640  aResult.fontWeight = u"900";
641  SAL_INFO("sdext.pdfimport", aResult.fontWeight);
642 
643  // Italic
644  aResult.isItalic = (aFontReadResult.GetItalic() == ITALIC_OBLIQUE ||
645  aFontReadResult.GetItalic() == ITALIC_NORMAL);
646  } else // font detection failed
647  {
648  SAL_WARN("sdext.pdfimport",
649  "Font detection from fontFile returned empty result. Guessing font info from font name.");
650  parseFontFamilyName(aResult);
651  }
652 
653  } else // no embedded font file - guess font attributes from font name
654  {
655  parseFontFamilyName(aResult);
656  }
657 
658  // last fallback
659  if (aResult.familyName.isEmpty())
660  {
661  SAL_WARN("sdext.pdfimport", "Failed to determine the font, using a fallback font Arial.");
662  aResult.familyName = "Arial";
663  }
664 
665  if (!m_parser.m_xDev)
666  m_parser.m_xDev.disposeAndReset(VclPtr<VirtualDevice>::Create());
667 
668  vcl::Font font(aResult.familyName, Size(0, 1000));
669  m_parser.m_xDev->SetFont(font);
670  FontMetric metric(m_parser.m_xDev->GetFontMetric());
671  aResult.ascent = metric.GetAscent() / 1000.0;
672 
673  m_parser.m_aFontMap[nFontID] = aResult;
674 
675  aResult.size = nSize;
676  m_parser.m_pSink->setFont(aResult);
677 }
678 
679 uno::Sequence<beans::PropertyValue> LineParser::readImageImpl()
680 {
681  std::string_view aToken = readNextToken();
682  const sal_Int32 nImageSize( readInt32() );
683 
684  OUString aFileName;
685  if( aToken == "PNG" )
686  aFileName = "DUMMY.PNG";
687  else if( aToken == "JPEG" )
688  aFileName = "DUMMY.JPEG";
689  else if( aToken == "PBM" )
690  aFileName = "DUMMY.PBM";
691  else
692  {
693  SAL_WARN_IF(aToken != "PPM","sdext.pdfimport","Invalid bitmap format");
694  aFileName = "DUMMY.PPM";
695  }
696 
697  uno::Sequence<sal_Int8> aDataSequence(nImageSize);
698  readBinaryData( aDataSequence );
699 
700  uno::Sequence< uno::Any > aStreamCreationArgs{ uno::Any(aDataSequence) };
701 
702  uno::Reference< uno::XComponentContext > xContext( m_parser.m_xContext, uno::UNO_SET_THROW );
703  uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
704  uno::Reference< io::XInputStream > xDataStream(
705  xFactory->createInstanceWithArgumentsAndContext( "com.sun.star.io.SequenceInputStream", aStreamCreationArgs, m_parser.m_xContext ),
706  uno::UNO_QUERY_THROW );
707 
708  uno::Sequence<beans::PropertyValue> aSequence( comphelper::InitPropertySequence({
709  { "URL", uno::makeAny(aFileName) },
710  { "InputStream", uno::makeAny( xDataStream ) },
711  { "InputSequence", uno::makeAny(aDataSequence) }
712  }));
713 
714  return aSequence;
715 }
716 
717 void LineParser::readImage()
718 {
719  sal_Int32 nWidth, nHeight,nMaskColors;
720  readInt32(nWidth);
721  readInt32(nHeight);
722  readInt32(nMaskColors);
723 
724  uno::Sequence<beans::PropertyValue> aImg( readImageImpl() );
725 
726  if( nMaskColors )
727  {
728  uno::Sequence<sal_Int8> aDataSequence(nMaskColors);
729  readBinaryData( aDataSequence );
730 
731  uno::Sequence<double> aMinRange(nMaskColors/2);
732  auto pMinRange = aMinRange.getArray();
733  uno::Sequence<double> aMaxRange(nMaskColors/2);
734  auto pMaxRange = aMaxRange.getArray();
735  for( sal_Int32 i=0; i<nMaskColors/2; ++i )
736  {
737  pMinRange[i] = aDataSequence[i] / 255.0;
738  pMaxRange[i] = aDataSequence[i+nMaskColors/2] / 255.0;
739  }
740 
741  uno::Sequence<uno::Any> aMaskRanges{ uno::Any(aMinRange), uno::Any(aMaxRange) };
742  m_parser.m_pSink->drawColorMaskedImage( aImg, aMaskRanges );
743  }
744  else
745  m_parser.m_pSink->drawImage( aImg );
746 }
747 
748 void LineParser::readMask()
749 {
750  sal_Int32 nWidth, nHeight, nInvert;
751  readInt32(nWidth);
752  readInt32(nHeight);
753  readInt32(nInvert);
754 
755  m_parser.m_pSink->drawMask( readImageImpl(), nInvert != 0);
756 }
757 
758 void LineParser::readLink()
759 {
760  geometry::RealRectangle2D aBounds;
761  readDouble(aBounds.X1);
762  readDouble(aBounds.Y1);
763  readDouble(aBounds.X2);
764  readDouble(aBounds.Y2);
765 
766  m_parser.m_pSink->hyperLink( aBounds,
767  OStringToOUString( lcl_unescapeLineFeeds(
768  m_aLine.subView(m_nCharIndex) ),
769  RTL_TEXTENCODING_UTF8 ) );
770  // name gobbles up rest of line
771  m_nCharIndex = std::string_view::npos;
772 }
773 
774 void LineParser::readMaskedImage()
775 {
776  sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight, nMaskInvert;
777  readInt32(nWidth);
778  readInt32(nHeight);
779  readInt32(nMaskWidth);
780  readInt32(nMaskHeight);
781  readInt32(nMaskInvert);
782 
783  const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
784  const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
785  m_parser.m_pSink->drawMaskedImage( aImage, aMask, nMaskInvert != 0 );
786 }
787 
788 void LineParser::readSoftMaskedImage()
789 {
790  sal_Int32 nWidth, nHeight, nMaskWidth, nMaskHeight;
791  readInt32(nWidth);
792  readInt32(nHeight);
793  readInt32(nMaskWidth);
794  readInt32(nMaskHeight);
795 
796  const uno::Sequence<beans::PropertyValue> aImage( readImageImpl() );
797  const uno::Sequence<beans::PropertyValue> aMask ( readImageImpl() );
798  m_parser.m_pSink->drawAlphaMaskedImage( aImage, aMask );
799 }
800 
801 void Parser::parseLine( const OString& rLine )
802 {
803  OSL_PRECOND( m_pSink, "Invalid sink" );
804  OSL_PRECOND( m_pErr, "Invalid filehandle" );
805  OSL_PRECOND( m_xContext.is(), "Invalid service factory" );
806 
807  LineParser lp(*this, rLine);
808  const std::string_view rCmd = lp.readNextToken();
809  const hash_entry* pEntry = PdfKeywordHash::in_word_set( rCmd.data(),
810  rCmd.size() );
811  OSL_ASSERT(pEntry);
812  switch( pEntry->eKey )
813  {
814  case CLIPPATH:
815  m_pSink->intersectClip(lp.readPath()); break;
816  case DRAWCHAR:
817  lp.readChar(); break;
818  case DRAWIMAGE:
819  lp.readImage(); break;
820  case DRAWLINK:
821  lp.readLink(); break;
822  case DRAWMASK:
823  lp.readMask(); break;
824  case DRAWMASKEDIMAGE:
825  lp.readMaskedImage(); break;
826  case DRAWSOFTMASKEDIMAGE:
827  lp.readSoftMaskedImage(); break;
828  case ENDPAGE:
829  m_pSink->endPage(); break;
830  case ENDTEXTOBJECT:
831  m_pSink->endText(); break;
832  case EOCLIPPATH:
833  m_pSink->intersectEoClip(lp.readPath()); break;
834  case EOFILLPATH:
835  m_pSink->eoFillPath(lp.readPath()); break;
836  case FILLPATH:
837  m_pSink->fillPath(lp.readPath()); break;
838  case RESTORESTATE:
839  m_pSink->popState(); break;
840  case SAVESTATE:
841  m_pSink->pushState(); break;
842  case SETPAGENUM:
843  m_pSink->setPageNum( lp.readInt32() ); break;
844  case STARTPAGE:
845  {
846  const double nWidth ( lp.readDouble() );
847  const double nHeight( lp.readDouble() );
848  m_pSink->startPage( geometry::RealSize2D( nWidth, nHeight ) );
849  break;
850  }
851  case STROKEPATH:
852  m_pSink->strokePath(lp.readPath()); break;
853  case UPDATECTM:
854  lp.readTransformation(); break;
855  case UPDATEFILLCOLOR:
856  m_pSink->setFillColor( lp.readColor() ); break;
857  case UPDATEFLATNESS:
858  m_pSink->setFlatness( lp.readDouble( ) ); break;
859  case UPDATEFONT:
860  lp.readFont(); break;
861  case UPDATELINECAP:
862  lp.readLineCap(); break;
863  case UPDATELINEDASH:
864  lp.readLineDash(); break;
865  case UPDATELINEJOIN:
866  lp.readLineJoin(); break;
867  case UPDATELINEWIDTH:
868  m_pSink->setLineWidth( lp.readDouble() );break;
869  case UPDATEMITERLIMIT:
870  m_pSink->setMiterLimit( lp.readDouble() ); break;
871  case UPDATESTROKECOLOR:
872  m_pSink->setStrokeColor( lp.readColor() ); break;
873  case UPDATESTROKEOPACITY:
874  break;
875  case SETTEXTRENDERMODE:
876  m_pSink->setTextRenderMode( lp.readInt32() ); break;
877 
878  case NONE:
879  default:
880  OSL_PRECOND(false,"Unknown input");
881  break;
882  }
883 
884  // all consumed?
885  SAL_WARN_IF(
886  lp.m_nCharIndex!=std::string_view::npos, "sdext.pdfimport", "leftover scanner input");
887 }
888 
889 } // namespace
890 
891 static bool checkEncryption( std::u16string_view i_rPath,
892  const uno::Reference< task::XInteractionHandler >& i_xIHdl,
893  OUString& io_rPwd,
894  bool& o_rIsEncrypted,
895  const OUString& i_rDocName
896  )
897 {
898  bool bSuccess = false;
899  OString aPDFFile = OUStringToOString( i_rPath, osl_getThreadTextEncoding() );
900 
901  std::unique_ptr<pdfparse::PDFEntry> pEntry( pdfparse::PDFReader::read( aPDFFile.getStr() ));
902  if( pEntry )
903  {
904  pdfparse::PDFFile* pPDFFile = dynamic_cast<pdfparse::PDFFile*>(pEntry.get());
905  if( pPDFFile )
906  {
907  o_rIsEncrypted = pPDFFile->isEncrypted();
908  if( o_rIsEncrypted )
909  {
910  if( pPDFFile->usesSupportedEncryptionFormat() )
911  {
912  bool bAuthenticated = false;
913  if( !io_rPwd.isEmpty() )
914  {
915  OString aIsoPwd = OUStringToOString( io_rPwd,
916  RTL_TEXTENCODING_ISO_8859_1 );
917  bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
918  }
919  if( bAuthenticated )
920  bSuccess = true;
921  else
922  {
923  if( i_xIHdl.is() )
924  {
925  bool bEntered = false;
926  do
927  {
928  bEntered = getPassword( i_xIHdl, io_rPwd, ! bEntered, i_rDocName );
929  OString aIsoPwd = OUStringToOString( io_rPwd,
930  RTL_TEXTENCODING_ISO_8859_1 );
931  bAuthenticated = pPDFFile->setupDecryptionData( aIsoPwd.getStr() );
932  } while( bEntered && ! bAuthenticated );
933  }
934 
935  bSuccess = bAuthenticated;
936  }
937  }
938  else if( i_xIHdl.is() )
939  {
941  //TODO: this should either be handled further down the
942  // call stack, or else information that this has already
943  // been handled should be passed down the call stack, so
944  // that SfxBaseModel::load does not show an additional
945  // "General Error" message box
946  }
947  }
948  else
949  bSuccess = true;
950  }
951  }
952  return bSuccess;
953 }
954 
955 namespace {
956 
957 class Buffering
958 {
959  static const int SIZE = 64*1024;
960  std::unique_ptr<char[]> aBuffer;
961  oslFileHandle& pOut;
962  size_t pos;
963  sal_uInt64 left;
964 
965 public:
966  explicit Buffering(oslFileHandle& out) : aBuffer(new char[SIZE]), pOut(out), pos(0), left(0) {}
967 
968  oslFileError read(char *pChar, short count, sal_uInt64* pBytesRead)
969  {
970  oslFileError nRes = osl_File_E_None;
971  sal_uInt64 nBytesRead = 0;
972  while (count > 0)
973  {
974  if (left == 0)
975  {
976  nRes = osl_readFile(pOut, aBuffer.get(), SIZE, &left);
977  if (nRes != osl_File_E_None || left == 0)
978  {
979  *pBytesRead = nBytesRead;
980  return nRes;
981  }
982  pos = 0;
983  }
984  *pChar = aBuffer.get()[pos];
985  --count;
986  ++pos;
987  --left;
988  ++pChar;
989  ++nBytesRead;
990  }
991  *pBytesRead = nBytesRead;
992  return osl_File_E_None;
993  }
994 };
995 
996 }
997 
998 bool xpdf_ImportFromFile(const OUString& rURL,
999  const ContentSinkSharedPtr& rSink,
1000  const uno::Reference<task::XInteractionHandler>& xIHdl,
1001  const OUString& rPwd,
1002  const uno::Reference<uno::XComponentContext>& xContext,
1003  const OUString& rFilterOptions)
1004 {
1005  OSL_ASSERT(rSink);
1006 
1007  OUString aSysUPath;
1008  if( osl_getSystemPathFromFileURL( rURL.pData, &aSysUPath.pData ) != osl_File_E_None )
1009  {
1010  SAL_WARN(
1011  "sdext.pdfimport",
1012  "getSystemPathFromFileURL(" << rURL << ") failed");
1013  return false;
1014  }
1015  OUString aDocName( rURL.copy( rURL.lastIndexOf( '/' )+1 ) );
1016 
1017  // check for encryption, if necessary get password
1018  OUString aPwd( rPwd );
1019  bool bIsEncrypted = false;
1020  if( !checkEncryption( aSysUPath, xIHdl, aPwd, bIsEncrypted, aDocName ) )
1021  {
1022  SAL_INFO(
1023  "sdext.pdfimport",
1024  "checkEncryption(" << aSysUPath << ") failed");
1025  return false;
1026  }
1027 
1028  // Determine xpdfimport executable URL:
1029  OUString converterURL("$BRAND_BASE_DIR/" LIBO_BIN_FOLDER "/xpdfimport");
1030  rtl::Bootstrap::expandMacros(converterURL); //TODO: detect failure
1031 
1032  // Determine pathname of xpdfimport_err.pdf:
1033  OUString errPathname("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/xpdfimport/xpdfimport_err.pdf");
1034  rtl::Bootstrap::expandMacros(errPathname); //TODO: detect failure
1035  if (osl::FileBase::getSystemPathFromFileURL(errPathname, errPathname)
1036  != osl::FileBase::E_None)
1037  {
1038  SAL_WARN(
1039  "sdext.pdfimport",
1040  "getSystemPathFromFileURL(" << errPathname << ") failed");
1041  return false;
1042  }
1043 
1044  // spawn separate process to keep LGPL/GPL code apart.
1045 
1046  OUString aOptFlag("-o");
1047  rtl_uString* args[] = { aSysUPath.pData, errPathname.pData,
1048  aOptFlag.pData, rFilterOptions.pData };
1049  sal_Int32 nArgs = rFilterOptions.isEmpty() ? 2 : 4;
1050 
1051  oslProcess aProcess;
1052  oslFileHandle pIn = nullptr;
1053  oslFileHandle pOut = nullptr;
1054  oslFileHandle pErr = nullptr;
1055  oslSecurity pSecurity = osl_getCurrentSecurity ();
1056  oslProcessError eErr =
1057  osl_executeProcess_WithRedirectedIO(converterURL.pData,
1058  args,
1059  nArgs,
1060  osl_Process_SEARCHPATH|osl_Process_HIDDEN,
1061  pSecurity,
1062  nullptr, nullptr, 0,
1063  &aProcess, &pIn, &pOut, &pErr);
1064  osl_freeSecurityHandle(pSecurity);
1065 
1066  bool bRet=true;
1067  try
1068  {
1069  if( eErr!=osl_Process_E_None )
1070  {
1071  SAL_WARN(
1072  "sdext.pdfimport",
1073  "executeProcess of " << converterURL << " failed with "
1074  << +eErr);
1075  return false;
1076  }
1077 
1078  if( pIn )
1079  {
1080  OStringBuffer aBuf(256);
1081  if( bIsEncrypted )
1082  aBuf.append( OUStringToOString( aPwd, RTL_TEXTENCODING_ISO_8859_1 ) );
1083  aBuf.append( '\n' );
1084 
1085  sal_uInt64 nWritten = 0;
1086  osl_writeFile( pIn, aBuf.getStr(), sal_uInt64(aBuf.getLength()), &nWritten );
1087  }
1088 
1089  if( pOut && pErr )
1090  {
1091  // read results of PDF parser. One line - one call to
1092  // OutputDev. stderr is used for alternate streams, like
1093  // embedded fonts and bitmaps
1094  Parser aParser(rSink,pErr,xContext);
1095  Buffering aBuffering(pOut);
1096  OStringBuffer line;
1097  for( ;; )
1098  {
1099  char aChar('\n');
1100  sal_uInt64 nBytesRead;
1101  oslFileError nRes;
1102 
1103  // skip garbage \r \n at start of line
1104  for (;;)
1105  {
1106  nRes = aBuffering.read(&aChar, 1, &nBytesRead);
1107  if (osl_File_E_None != nRes || nBytesRead != 1 || (aChar != '\n' && aChar != '\r') )
1108  break;
1109  }
1110  if ( osl_File_E_None != nRes )
1111  break;
1112 
1113  if( aChar != '\n' && aChar != '\r' )
1114  line.append( aChar );
1115 
1116  for (;;)
1117  {
1118  nRes = aBuffering.read(&aChar, 1, &nBytesRead);
1119  if ( osl_File_E_None != nRes || nBytesRead != 1 || aChar == '\n' || aChar == '\r' )
1120  break;
1121  line.append( aChar );
1122  }
1123  if ( osl_File_E_None != nRes )
1124  break;
1125  if ( line.isEmpty() )
1126  break;
1127 
1128  aParser.parseLine(line.makeStringAndClear());
1129  }
1130  }
1131  }
1132  catch( uno::Exception& )
1133  {
1134  // crappy C file interface. need manual resource dealloc
1135  bRet = false;
1136  }
1137 
1138  if( pIn )
1139  osl_closeFile(pIn);
1140  if( pOut )
1141  osl_closeFile(pOut);
1142  if( pErr )
1143  osl_closeFile(pErr);
1144  eErr = osl_joinProcess(aProcess);
1145  if (eErr == osl_Process_E_None)
1146  {
1147  oslProcessInfo info;
1148  info.Size = sizeof info;
1149  eErr = osl_getProcessInfo(aProcess, osl_Process_EXITCODE, &info);
1150  if (eErr == osl_Process_E_None)
1151  {
1152  if (info.Code != 0)
1153  {
1154  SAL_WARN(
1155  "sdext.pdfimport",
1156  "getProcessInfo of " << converterURL
1157  << " failed with exit code " << info.Code);
1158  bRet = false;
1159  }
1160  }
1161  else
1162  {
1163  SAL_WARN(
1164  "sdext.pdfimport",
1165  "getProcessInfo of " << converterURL << " failed with "
1166  << +eErr);
1167  bRet = false;
1168  }
1169  }
1170  else
1171  {
1172  SAL_WARN(
1173  "sdext.pdfimport",
1174  "joinProcess of " << converterURL << " failed with " << +eErr);
1175  bRet = false;
1176  }
1177  osl_freeProcessHandle(aProcess);
1178  return bRet;
1179 }
1180 
1181 
1182 bool xpdf_ImportFromStream( const uno::Reference< io::XInputStream >& xInput,
1183  const ContentSinkSharedPtr& rSink,
1184  const uno::Reference<task::XInteractionHandler >& xIHdl,
1185  const OUString& rPwd,
1186  const uno::Reference< uno::XComponentContext >& xContext,
1187  const OUString& rFilterOptions )
1188 {
1189  OSL_ASSERT(xInput.is());
1190  OSL_ASSERT(rSink);
1191 
1192  // convert XInputStream to local temp file
1193  oslFileHandle aFile = nullptr;
1194  OUString aURL;
1195  if( osl_createTempFile( nullptr, &aFile, &aURL.pData ) != osl_File_E_None )
1196  return false;
1197 
1198  // copy content, buffered...
1199  const sal_uInt32 nBufSize = 4096;
1200  uno::Sequence<sal_Int8> aBuf( nBufSize );
1201  sal_uInt64 nBytes = 0;
1202  sal_uInt64 nWritten = 0;
1203  bool bSuccess = true;
1204  do
1205  {
1206  try
1207  {
1208  nBytes = xInput->readBytes( aBuf, nBufSize );
1209  }
1210  catch( css::uno::Exception& )
1211  {
1212  osl_closeFile( aFile );
1213  throw;
1214  }
1215  if( nBytes > 0 )
1216  {
1217  osl_writeFile( aFile, aBuf.getConstArray(), nBytes, &nWritten );
1218  if( nWritten != nBytes )
1219  {
1220  bSuccess = false;
1221  break;
1222  }
1223  }
1224  }
1225  while( nBytes == nBufSize );
1226 
1227  osl_closeFile( aFile );
1228 
1229  if ( bSuccess )
1230  bSuccess = xpdf_ImportFromFile( aURL, rSink, xIHdl, rPwd, xContext, rFilterOptions );
1231  osl_removeFile( aURL.pData );
1232 
1233  return bSuccess;
1234 }
1235 
1236 }
1237 
1238 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tuple line
void reportUnsupportedEncryptionFormat(css::uno::Reference< css::task::XInteractionHandler > const &handler)
static Font identifyFont(const void *pBuffer, sal_uInt32 nLen)
URL aURL
static bool checkEncryption(std::u16string_view i_rPath, const uno::Reference< task::XInteractionHandler > &i_xIHdl, OUString &io_rPwd, bool &o_rIsEncrypted, const OUString &i_rDocName)
Definition: wrapper.cxx:891
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
void remove(sal_uInt32 nIndex, sal_uInt32 nCount=1)
const OUString & GetFamilyName() const
sal_uInt64 left
Definition: wrapper.cxx:963
signed char sal_Int8
static std::unique_ptr< PDFEntry > read(const char *pFileName)
Definition: pdfparse.cxx:608
WEIGHT_THIN
sal_Int64 n
aBuf
WEIGHT_BLACK
void appendBezierSegment(const basegfx::B2DPoint &rNextControlPoint, const basegfx::B2DPoint &rPrevControlPoint, const basegfx::B2DPoint &rPoint)
tuple args
WEIGHT_SEMIBOLD
WEIGHT_LIGHT
NONE
bool xpdf_ImportFromFile(const OUString &rURL, const ContentSinkSharedPtr &rSink, const uno::Reference< task::XInteractionHandler > &xIHdl, const OUString &rPwd, const uno::Reference< uno::XComponentContext > &xContext, const OUString &rFilterOptions)
Definition: wrapper.cxx:998
WEIGHT_BOLD
FontItalic GetItalic()
size_t pos
Definition: wrapper.cxx:962
oslFileHandle & pOut
Definition: wrapper.cxx:961
Parser & m_parser
Definition: wrapper.cxx:170
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
bool usesSupportedEncryptionFormat() const
std::string_view getToken(std::string_view sv, char delimiter, std::size_t &position)
WEIGHT_SEMILIGHT
int i
ITALIC_OBLIQUE
WEIGHT_ULTRALIGHT
float u
bool isEncrypted() const
bool getPassword(const css::uno::Reference< css::task::XInteractionHandler > &xHandler, OUString &rOutPwd, bool bFirstTry, const OUString &rDocName)
retrieve password from user
WEIGHT_ULTRABOLD
static const int SIZE
Definition: wrapper.cxx:959
const OUString fontAttributesSuffixes[]
Definition: wrapper.hxx:56
bool xpdf_ImportFromStream(const uno::Reference< io::XInputStream > &xInput, const ContentSinkSharedPtr &rSink, const uno::Reference< task::XInteractionHandler > &xIHdl, const OUString &rPwd, const uno::Reference< uno::XComponentContext > &xContext, const OUString &rFilterOptions)
Definition: wrapper.cxx:1182
const ContentSinkSharedPtr m_pSink
Definition: wrapper.cxx:152
void append(const B2DPolygon &rPolygon, sal_uInt32 nCount=1)
void setClosed(bool bNew)
std::unique_ptr< char[]> aBuffer
Definition: wrapper.cxx:960
Any makeAny(Color const &value)
#define SAL_WARN_IF(condition, area, stream)
FontWeight GetWeight()
ITALIC_NORMAL
#define SAL_INFO(area, stream)
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
std::size_t m_nCharIndex
Definition: wrapper.cxx:182
#define SAL_WARN(area, stream)
Reference< XSingleServiceFactory > xFactory
const oslFileHandle m_pErr
Definition: wrapper.cxx:153
OString m_aLine
Definition: wrapper.cxx:171
ScopedVclPtr< VirtualDevice > m_xDev
Definition: wrapper.cxx:150
std::shared_ptr< ContentSink > ContentSinkSharedPtr
bool setupDecryptionData(const OString &rPwd) const
FontMapType m_aFontMap
Definition: wrapper.cxx:154
const uno::Reference< uno::XComponentContext > m_xContext
Definition: wrapper.cxx:151
sal_uInt32 count() const
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const