Lines 147-152
Link Here
|
147 |
|
147 |
|
148 |
class Parser |
148 |
class Parser |
149 |
{ |
149 |
{ |
|
|
150 |
// The variable contains value of minimal area that can |
151 |
// be displayed using internal object filling. Sometimes |
152 |
// a problem occurs, when object is to narrow and edges |
153 |
// are close to themselves. It implies small filling area |
154 |
// and objects are not visible then. The solution is to |
155 |
// draw object borders that time. |
156 |
// TODO: this value shouldn't be hardcoded. The user |
157 |
// should be able to choose proper value. |
158 |
const double minAreaThreshold; |
159 |
|
150 |
typedef std::hash_map< sal_Int64, |
160 |
typedef std::hash_map< sal_Int64, |
151 |
FontAttributes > FontMapType; |
161 |
FontAttributes > FontMapType; |
152 |
|
162 |
|
Lines 168-173
Link Here
|
168 |
void readBinaryData( uno::Sequence<sal_Int8>& rBuf ); |
178 |
void readBinaryData( uno::Sequence<sal_Int8>& rBuf ); |
169 |
|
179 |
|
170 |
uno::Reference<rendering::XPolyPolygon2D> readPath(); |
180 |
uno::Reference<rendering::XPolyPolygon2D> readPath(); |
|
|
181 |
/** |
182 |
* \brief Reads path and count the area of the smallest rectangle containing it. |
183 |
* |
184 |
* Function reads path and counts area of it. It's used |
185 |
* when EOFILLPATH occurs to check if the area is big |
186 |
* enough to draw it using internal filling. Otherwise |
187 |
* we need to add object borders by calling strokePath. |
188 |
* The decision is taken by comparing area value to |
189 |
* minAreaThreshold variable. |
190 |
* |
191 |
* @param area will contain the value of smallest rectangle |
192 |
* containing the path. |
193 |
* @return reference to the path. |
194 |
**/ |
195 |
uno::Reference<rendering::XPolyPolygon2D> readPath(double & area); |
171 |
|
196 |
|
172 |
void readChar(); |
197 |
void readChar(); |
173 |
void readLineCap(); |
198 |
void readLineCap(); |
Lines 199-205
Link Here
|
199 |
m_aLine(), |
224 |
m_aLine(), |
200 |
m_aFontMap(101), |
225 |
m_aFontMap(101), |
201 |
m_nNextToken(-1), |
226 |
m_nNextToken(-1), |
202 |
m_nCharIndex(-1) |
227 |
m_nCharIndex(-1), |
|
|
228 |
minAreaThreshold(300.0) |
203 |
{} |
229 |
{} |
204 |
|
230 |
|
205 |
void parseLine( const ::rtl::OString& rLine ); |
231 |
void parseLine( const ::rtl::OString& rLine ); |
Lines 265-270
Link Here
|
265 |
return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex); |
291 |
return m_aLine.getToken(m_nNextToken,' ',m_nCharIndex); |
266 |
} |
292 |
} |
267 |
|
293 |
|
|
|
294 |
|
268 |
void Parser::readInt32( sal_Int32& o_Value ) |
295 |
void Parser::readInt32( sal_Int32& o_Value ) |
269 |
{ |
296 |
{ |
270 |
o_Value = readNextToken().toInt32(); |
297 |
o_Value = readNextToken().toInt32(); |
Lines 368-375
Link Here
|
368 |
|
395 |
|
369 |
return static_cast<rendering::XLinePolyPolygon2D*>( |
396 |
return static_cast<rendering::XLinePolyPolygon2D*>( |
370 |
new basegfx::unotools::UnoPolyPolygon(aResult)); |
397 |
new basegfx::unotools::UnoPolyPolygon(aResult)); |
|
|
398 |
} |
399 |
|
400 |
uno::Reference<rendering::XPolyPolygon2D> Parser::readPath(double & area) |
401 |
{ |
402 |
const rtl::OString aSubPathMarker( "subpath" ); |
403 |
|
404 |
if( 0 != readNextToken().compareTo( aSubPathMarker ) ) |
405 |
OSL_PRECOND(false, "broken path"); |
406 |
|
407 |
basegfx::B2DPolyPolygon aResult; |
408 |
|
409 |
double xmax = 0.0; |
410 |
double ymax = 0.0; |
411 |
double xmin = INT_MAX; |
412 |
double ymin = INT_MAX; |
413 |
double width = 0.0; |
414 |
double heigth = 0.0; |
415 |
|
416 |
while( m_nCharIndex != -1 ) |
417 |
{ |
418 |
basegfx::B2DPolygon aSubPath; |
419 |
|
420 |
sal_Int32 nClosedFlag; |
421 |
readInt32( nClosedFlag ); |
422 |
aSubPath.setClosed( nClosedFlag != 0 ); |
423 |
|
424 |
sal_Int32 nContiguousControlPoints(0); |
425 |
sal_Int32 nDummy=m_nCharIndex; |
426 |
rtl::OString aCurrToken( m_aLine.getToken(m_nNextToken,' ',nDummy) ); |
427 |
|
428 |
while( m_nCharIndex != -1 && 0 != aCurrToken.compareTo(aSubPathMarker) ) |
429 |
{ |
430 |
sal_Int32 nCurveFlag; |
431 |
double nX, nY; |
432 |
readDouble( nX ); |
433 |
readDouble( nY ); |
434 |
readInt32( nCurveFlag ); |
435 |
|
436 |
if(nX < xmin) |
437 |
xmin = nX; |
438 |
if(nX > xmax) |
439 |
xmax = nX; |
440 |
if(nY < ymin) |
441 |
ymin = nY; |
442 |
if(nY > ymax) |
443 |
ymax = nY; |
444 |
|
445 |
aSubPath.append(basegfx::B2DPoint(nX,nY)); |
446 |
if( nCurveFlag ) |
447 |
{ |
448 |
++nContiguousControlPoints; |
449 |
} |
450 |
else if( nContiguousControlPoints ) |
451 |
{ |
452 |
OSL_PRECOND(nContiguousControlPoints==2,"broken bezier path"); |
453 |
|
454 |
// have two control points before us. the current one |
455 |
// is a normal point - thus, convert previous points |
456 |
// into bezier segment |
457 |
const sal_uInt32 nPoints( aSubPath.count() ); |
458 |
const basegfx::B2DPoint aCtrlA( aSubPath.getB2DPoint(nPoints-3) ); |
459 |
const basegfx::B2DPoint aCtrlB( aSubPath.getB2DPoint(nPoints-2) ); |
460 |
const basegfx::B2DPoint aEnd( aSubPath.getB2DPoint(nPoints-1) ); |
461 |
aSubPath.remove(nPoints-3, 3); |
462 |
aSubPath.appendBezierSegment(aCtrlA, aCtrlB, aEnd); |
463 |
|
464 |
nContiguousControlPoints=0; |
465 |
} |
466 |
|
467 |
// one token look-ahead (new subpath or more points? |
468 |
nDummy=m_nCharIndex; |
469 |
aCurrToken = m_aLine.getToken(m_nNextToken,' ',nDummy); |
470 |
} |
471 |
|
472 |
aResult.append( aSubPath ); |
473 |
if( m_nCharIndex != -1 ) |
474 |
readNextToken(); |
475 |
} |
476 |
|
477 |
width = xmax - xmin; |
478 |
heigth = ymax - ymin; |
479 |
area = width * heigth; |
480 |
|
481 |
return static_cast<rendering::XLinePolyPolygon2D*>( |
482 |
new basegfx::unotools::UnoPolyPolygon(aResult)); |
371 |
} |
483 |
} |
372 |
|
484 |
|
|
|
485 |
|
373 |
void Parser::readChar() |
486 |
void Parser::readChar() |
374 |
{ |
487 |
{ |
375 |
geometry::Matrix2D aUnoMatrix; |
488 |
geometry::Matrix2D aUnoMatrix; |
Lines 437-443
Link Here
|
437 |
case 0: nJoin = rendering::PathJoinType::MITER; break; |
550 |
case 0: nJoin = rendering::PathJoinType::MITER; break; |
438 |
case 1: nJoin = rendering::PathJoinType::ROUND; break; |
551 |
case 1: nJoin = rendering::PathJoinType::ROUND; break; |
439 |
case 2: nJoin = rendering::PathJoinType::BEVEL; break; |
552 |
case 2: nJoin = rendering::PathJoinType::BEVEL; break; |
440 |
} |
553 |
} |
441 |
m_pSink->setLineJoin(nJoin); |
554 |
m_pSink->setLineJoin(nJoin); |
442 |
} |
555 |
} |
443 |
|
556 |
|
Lines 775-781
Link Here
|
775 |
OSL_PRECOND( m_pSink, "Invalid sink" ); |
888 |
OSL_PRECOND( m_pSink, "Invalid sink" ); |
776 |
OSL_PRECOND( m_pErr, "Invalid filehandle" ); |
889 |
OSL_PRECOND( m_pErr, "Invalid filehandle" ); |
777 |
OSL_PRECOND( m_xContext.is(), "Invalid service factory" ); |
890 |
OSL_PRECOND( m_xContext.is(), "Invalid service factory" ); |
778 |
|
891 |
|
779 |
m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine; |
892 |
m_nNextToken = 0; m_nCharIndex = 0; m_aLine = rLine; |
780 |
uno::Reference<rendering::XPolyPolygon2D> xPoly; |
893 |
uno::Reference<rendering::XPolyPolygon2D> xPoly; |
781 |
const ::rtl::OString& rCmd = readNextToken(); |
894 |
const ::rtl::OString& rCmd = readNextToken(); |
Lines 805-813
Link Here
|
805 |
case EOCLIPPATH: |
918 |
case EOCLIPPATH: |
806 |
m_pSink->intersectEoClip(readPath()); break; |
919 |
m_pSink->intersectEoClip(readPath()); break; |
807 |
case EOFILLPATH: |
920 |
case EOFILLPATH: |
808 |
m_pSink->eoFillPath(readPath()); break; |
921 |
{ |
|
|
922 |
double area; |
923 |
uno::Reference<rendering::XPolyPolygon2D> path = readPath(area); |
924 |
m_pSink->eoFillPath(path); |
925 |
// if area is smaller than required, add borders. |
926 |
if(area < minAreaThreshold) |
927 |
m_pSink->strokePath(path); |
928 |
break; |
929 |
} |
809 |
case FILLPATH: |
930 |
case FILLPATH: |
810 |
m_pSink->fillPath(readPath()); break; |
931 |
m_pSink->fillPath(readPath()); break; |
811 |
case RESTORESTATE: |
932 |
case RESTORESTATE: |
812 |
m_pSink->popState(); break; |
933 |
m_pSink->popState(); break; |
813 |
case SAVESTATE: |
934 |
case SAVESTATE: |