1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include <string.h>
25 #include <svpm.h>
26
27 #define _SV_SALGDI_CXX
28 #include <tools/debug.hxx>
29 #include <os2/saldata.hxx>
30 #include <os2/salgdi.h>
31 #include <tools/debug.hxx>
32 #include <os2/salframe.h>
33 #include <tools/poly.hxx>
34 #ifndef _RTL_STRINGBUF_HXX
35 #include <rtl/strbuf.hxx>
36 #endif
37
38 #ifndef __H_FT2LIB
39 #include <os2/wingdi.h>
40 #include <ft2lib.h>
41 #endif
42
43 // -----------
44 // - Defines -
45 // -----------
46
47 // ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern
48 #define SAL_PRINTER_CLIPPATH 1
49 // #define SAL_PRINTER_POLYPATH 1
50
51 // =======================================================================
52
ImplInitSalGDI()53 void ImplInitSalGDI()
54 {
55 }
56
57 // -----------------------------------------------------------------------
58
ImplFreeSalGDI()59 void ImplFreeSalGDI()
60 {
61 SalData* pSalData = GetSalData();
62
63 // delete icon cache
64 SalIcon* pIcon = pSalData->mpFirstIcon;
65 while( pIcon )
66 {
67 SalIcon* pTmp = pIcon->pNext;
68 WinDestroyPointer( pIcon->hIcon );
69 delete pIcon;
70 pIcon = pTmp;
71 }
72
73 }
74
75 // =======================================================================
76
ImplSalInitGraphics(Os2SalGraphics * pData)77 void ImplSalInitGraphics( Os2SalGraphics* pData )
78 {
79 GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL );
80 }
81
82 // -----------------------------------------------------------------------
83
ImplSalDeInitGraphics(Os2SalGraphics * pData)84 void ImplSalDeInitGraphics( Os2SalGraphics* pData )
85 {
86 }
87
88 // =======================================================================
89
Os2SalGraphics()90 Os2SalGraphics::Os2SalGraphics()
91 {
92 for( int i = 0; i < MAX_FALLBACK; ++i )
93 {
94 mhFonts[ i ] = 0;
95 mpOs2FontData[ i ] = NULL;
96 mpOs2FontEntry[ i ] = NULL;
97 }
98
99 mfFontScale = 1.0;
100
101 mhPS = 0;
102 mhDC = 0;
103 mbLine = FALSE;
104 mbFill = FALSE;
105 mbXORMode = FALSE;
106 mnFontMetricCount = 0;
107 mpFontMetrics = NULL;
108 mpClipRectlAry = NULL;
109
110 mhDefFont = 0;
111 mpFontKernPairs = NULL;
112 mnFontKernPairCount = 0;
113 mbFontKernInit = FALSE;
114
115 }
116
117 // -----------------------------------------------------------------------
118
~Os2SalGraphics()119 Os2SalGraphics::~Os2SalGraphics()
120 {
121 Ft2DeleteSetId( mhPS, LCID_BASE);
122
123 if ( mpFontMetrics )
124 delete mpFontMetrics;
125
126 if ( mpFontKernPairs )
127 delete mpFontKernPairs;
128
129 }
130
131 // -----------------------------------------------------------------------
132
ImplGetROPSalColor(SalROPColor nROPColor)133 static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
134 {
135 SalColor nSalColor;
136
137 switch( nROPColor )
138 {
139 case SAL_ROP_0:
140 nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
141 break;
142
143 case SAL_ROP_1:
144 case SAL_ROP_INVERT:
145 nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
146 break;
147 }
148
149 return nSalColor;
150 }
151
152 // -----------------------------------------------------------------------
153
GetResolution(sal_Int32 & rDPIX,sal_Int32 & rDPIY)154 void Os2SalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
155 {
156 // since OOo asks for DPI, I will query FONT_RES, which seems to be
157 // more correct than _RESOLUTION fields (on my wide screen lcd)
158 // and does not require conversion
159 long nDPIX = 72, nDPIY = 72;
160 DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &nDPIX );
161 DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &nDPIY );
162 rDPIX = nDPIX;
163 rDPIY = nDPIY;
164 }
165
166 // -----------------------------------------------------------------------
167
GetBitCount()168 USHORT Os2SalGraphics::GetBitCount()
169 {
170 LONG nBitCount;
171 DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount );
172 return (USHORT)nBitCount;
173 }
174
175 // -----------------------------------------------------------------------
176
GetGraphicsWidth() const177 long Os2SalGraphics::GetGraphicsWidth() const
178 {
179 if( mhWnd )
180 {
181 Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd );
182 if( pFrame )
183 {
184 if( pFrame->maGeometry.nWidth )
185 return pFrame->maGeometry.nWidth;
186 else
187 {
188 // TODO: perhaps not needed, maGeometry should always be up-to-date
189 RECTL aRect;
190 WinQueryWindowRect( mhWnd, &aRect );
191 return aRect.xRight;
192 }
193 }
194 }
195
196 return 0;
197 }
198
199 // -----------------------------------------------------------------------
200
ResetClipRegion()201 void Os2SalGraphics::ResetClipRegion()
202 {
203 #ifdef SAL_PRINTER_CLIPPATH
204 if ( mbPrinter )
205 GpiSetClipPath( mhPS, 0, SCP_RESET );
206 else
207 #endif
208 {
209 HRGN hOldRegion;
210
211 GpiSetClipRegion( mhPS, NULL, &hOldRegion );
212 if ( hOldRegion )
213 GpiDestroyRegion( mhPS, hOldRegion );
214 }
215 }
216
217 // -----------------------------------------------------------------------
218
setClipRegion(const Region & i_rClip)219 bool Os2SalGraphics::setClipRegion( const Region& i_rClip )
220 {
221 RectangleVector aRectangles;
222 i_rClip.GetRegionRectangles(aRectangles);
223 mnClipElementCount = aRectangles.size();
224 mpClipRectlAry = 0;
225
226 if(mnClipElementCount)
227 {
228 mpClipRectlAry = new RECTL[mnClipElementCount];
229
230 for(sal_uInt32 a(0); a < mnClipElementCount; a++)
231 {
232 const Rectangle& rRect = aRectangles[a];
233 RECTL* pClipRect = &mpClipRectlAry[a];
234
235 pClipRect->xLeft = rRect.Left();
236 pClipRect->yTop = mnHeight - rRect.Top();
237 pClipRect->xRight = rRect.Right() + 1; // nX + nW -> L + ((R - L) + 1) -> R + 1
238 pClipRect->yBottom = mnHeight - (rRect.Bottom() + 1); // same for height
239 }
240 }
241
242 // ULONG nCount = i_rClip.GetRectCount();
243 //
244 // mpClipRectlAry = new RECTL[ nCount ];
245 // mnClipElementCount = 0;
246 //
247 // ImplRegionInfo aInfo;
248 // long nX, nY, nW, nH;
249 // bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
250 // while( bRegionRect )
251 // {
252 // if ( nW && nH )
253 // {
254 // RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ];
255 // pClipRect->xLeft = nX;
256 // pClipRect->yTop = mnHeight - nY;
257 // pClipRect->xRight = nX + nW;
258 // pClipRect->yBottom = mnHeight - (nY + nH);
259 // mnClipElementCount++;
260 // }
261 // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
262 // }
263 #ifdef SAL_PRINTER_CLIPPATH
264 if ( mbPrinter )
265 {
266 GpiSetClipPath( mhPS, 0, SCP_RESET );
267 GpiBeginPath( mhPS, 1L );
268
269 for( int i = 0; i < mnClipElementCount; i++ )
270 {
271 POINTL aPt;
272 RECTL* pClipRect = &mpClipRectlAry[ i ];
273
274 aPt.x = pClipRect->xLeft;
275 aPt.y = pClipRect->yTop-1;
276 Ft2Move( mhPS, &aPt );
277
278 aPt.x = pClipRect->xRight-1;
279 aPt.y = pClipRect->yBottom;
280
281 Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
282 }
283
284 GpiEndPath( mhPS );
285 GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND );
286 }
287 else
288 #endif
289 {
290 HRGN hClipRegion = GpiCreateRegion( mhPS,
291 mnClipElementCount,
292 mpClipRectlAry );
293 HRGN hOldRegion;
294
295 GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion );
296 if( hOldRegion )
297 GpiDestroyRegion( mhPS, hOldRegion );
298 }
299
300 delete [] mpClipRectlAry;
301
302 return true;
303 }
304
305 // -----------------------------------------------------------------------
306
SetLineColor()307 void Os2SalGraphics::SetLineColor()
308 {
309 // don't draw line!
310 mbLine = FALSE;
311 }
312
313 // -----------------------------------------------------------------------
314
SetLineColor(SalColor nSalColor)315 void Os2SalGraphics::SetLineColor( SalColor nSalColor )
316 {
317 LINEBUNDLE lb;
318
319 // set color
320 lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
321 SALCOLOR_GREEN( nSalColor ),
322 SALCOLOR_BLUE( nSalColor ) );
323
324 Ft2SetAttrs( mhPS,
325 PRIM_LINE,
326 LBB_COLOR,
327 0,
328 &lb );
329
330 // draw line!
331 mbLine = TRUE;
332 }
333
334 // -----------------------------------------------------------------------
335
SetFillColor()336 void Os2SalGraphics::SetFillColor()
337 {
338 // don't fill area!
339 mbFill = FALSE;
340 }
341
342 // -----------------------------------------------------------------------
343
SetFillColor(SalColor nSalColor)344 void Os2SalGraphics::SetFillColor( SalColor nSalColor )
345 {
346 AREABUNDLE ab;
347
348 // set color
349 ab.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
350 SALCOLOR_GREEN( nSalColor ),
351 SALCOLOR_BLUE( nSalColor ) );
352
353 Ft2SetAttrs( mhPS,
354 PRIM_AREA,
355 ABB_COLOR,
356 0,
357 &ab );
358
359 // fill area!
360 mbFill = TRUE;
361 }
362
363 // -----------------------------------------------------------------------
364
SetXORMode(bool bSet,bool)365 void Os2SalGraphics::SetXORMode( bool bSet, bool )
366 {
367 mbXORMode = bSet;
368 LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT;
369
370 // set mix mode for lines
371 LINEBUNDLE lb;
372 lb.usMixMode = nMixMode;
373 Ft2SetAttrs( mhPS,
374 PRIM_LINE,
375 LBB_MIX_MODE,
376 0,
377 &lb );
378
379 // set mix mode for areas
380 AREABUNDLE ab;
381 ab.usMixMode = nMixMode;
382 Ft2SetAttrs( mhPS,
383 PRIM_AREA,
384 ABB_MIX_MODE,
385 0,
386 &ab );
387
388 // set mix mode for text
389 CHARBUNDLE cb;
390 cb.usMixMode = nMixMode;
391 Ft2SetAttrs( mhPS,
392 PRIM_CHAR,
393 CBB_MIX_MODE,
394 0,
395 &cb );
396 }
397
398 // -----------------------------------------------------------------------
399
SetROPLineColor(SalROPColor nROPColor)400 void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor )
401 {
402 SetLineColor( ImplGetROPSalColor( nROPColor ) );
403 }
404
405 // -----------------------------------------------------------------------
406
SetROPFillColor(SalROPColor nROPColor)407 void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor )
408 {
409 SetFillColor( ImplGetROPSalColor( nROPColor ) );
410 }
411
412 // -----------------------------------------------------------------------
413
drawPixel(long nX,long nY)414 void Os2SalGraphics::drawPixel( long nX, long nY )
415 {
416 POINTL aPt;
417
418 aPt.x = nX;
419 aPt.y = TY( nY );
420
421 // set color
422 Ft2SetPel( mhPS, &aPt );
423 }
424
425 // -----------------------------------------------------------------------
426
drawPixel(long nX,long nY,SalColor nSalColor)427 void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
428 {
429 // save old color
430 LINEBUNDLE oldLb;
431 GpiQueryAttrs( mhPS,
432 PRIM_LINE,
433 LBB_COLOR,
434 &oldLb );
435
436 // set new color
437 LINEBUNDLE lb;
438 lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
439 SALCOLOR_GREEN( nSalColor ),
440 SALCOLOR_BLUE( nSalColor ) );
441 Ft2SetAttrs( mhPS,
442 PRIM_LINE,
443 LBB_COLOR,
444 0,
445 &lb );
446
447 // set color of pixel
448 POINTL aPt;
449 aPt.x = nX;
450 aPt.y = TY( nY );
451 Ft2SetPel( mhPS, &aPt );
452
453 // restore old color
454 Ft2SetAttrs( mhPS,
455 PRIM_LINE,
456 LBB_COLOR,
457 0,
458 &oldLb );
459 }
460
461 // -----------------------------------------------------------------------
462
drawLine(long nX1,long nY1,long nX2,long nY2)463 void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
464 {
465 // OS2 zeichnet den Endpunkt mit
466 POINTL aPt;
467 aPt.x = nX1;
468 aPt.y = TY( nY1 );
469 Ft2Move( mhPS, &aPt );
470 aPt.x = nX2;
471 aPt.y = TY( nY2 );
472 GpiLine( mhPS, &aPt );
473 }
474
475 // -----------------------------------------------------------------------
476
drawRect(long nX,long nY,long nWidth,long nHeight)477 void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
478 {
479 POINTL aPt;
480 long lControl;
481
482 if ( mbFill )
483 {
484 if ( mbLine )
485 lControl = DRO_OUTLINEFILL;
486 else
487 lControl = DRO_FILL;
488 }
489 else
490 {
491 if ( mbLine )
492 lControl = DRO_OUTLINE;
493 else
494 return;
495 }
496
497 aPt.x = nX;
498 aPt.y = TY( nY );
499 Ft2Move( mhPS, &aPt );
500 aPt.x = nX + nWidth - 1;
501 aPt.y = TY( nY + nHeight - 1 );
502 Ft2Box( mhPS, lControl, &aPt, 0, 0 );
503 }
504
505 // -----------------------------------------------------------------------
506
drawPolyLine(sal_uInt32 nPoints,const SalPoint * pPtAry)507 void Os2SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
508 {
509 // convert all points to sys orientation
510 POINTL* pOS2PtAry = new POINTL[ nPoints ];
511 POINTL* pTempOS2PtAry = pOS2PtAry;
512 const SalPoint* pTempPtAry = pPtAry;
513 sal_uInt32 nTempPoints = nPoints;
514 long nHeight = mnHeight - 1;
515
516 while( nTempPoints-- )
517 {
518 (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
519 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
520 pTempOS2PtAry++;
521 pTempPtAry++;
522 }
523
524 Ft2Move( mhPS, pOS2PtAry );
525 GpiPolyLine( mhPS, nPoints, pOS2PtAry );
526 delete [] pOS2PtAry;
527 }
528
529 // -----------------------------------------------------------------------
530
drawPolygon(sal_uInt32 nPoints,const SalPoint * pPtAry)531 void Os2SalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
532 {
533 PM_POLYGON aPolygon;
534
535 // create polygon
536 aPolygon.aPointl = new POINTL[ nPoints ];
537 aPolygon.ulPoints = nPoints;
538
539 // convert all points to sys orientation
540 POINTL* pTempOS2PtAry = aPolygon.aPointl;
541 const SalPoint* pTempPtAry = pPtAry;
542 sal_uInt32 nTempPoints = nPoints;
543 long nHeight = mnHeight - 1;
544
545 while( nTempPoints-- )
546 {
547 (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
548 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
549 pTempOS2PtAry++;
550 pTempPtAry++;
551 }
552
553 // Innenleben zeichnen
554 if ( mbFill )
555 {
556 #ifdef SAL_PRINTER_POLYPATH
557 if ( mbPrinter )
558 {
559 Ft2BeginPath( mhPS, 1 );
560 Ft2Move( mhPS, aPolygon.aPointl );
561 Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
562 Ft2EndPath( mhPS );
563 Ft2FillPath( mhPS, 1, 0 );
564
565 if ( mbLine )
566 {
567 Ft2Move( mhPS, aPolygon.aPointl );
568 Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
569 }
570 }
571 else
572 #endif
573 {
574 ULONG nOptions = POLYGON_ALTERNATE;
575
576 if ( mbLine )
577 nOptions |= POLYGON_BOUNDARY;
578 else
579 nOptions |= POLYGON_NOBOUNDARY;
580
581 Ft2Move( mhPS, aPolygon.aPointl );
582 GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL );
583 }
584 }
585 else
586 {
587 if ( mbLine )
588 {
589 Ft2Move( mhPS, aPolygon.aPointl );
590 GpiPolyLine( mhPS, nPoints, aPolygon.aPointl );
591 }
592 }
593
594 delete [] aPolygon.aPointl;
595 }
596
597 // -----------------------------------------------------------------------
598
drawPolyPolygon(sal_uInt32 nPoly,const sal_uInt32 * pPoints,PCONSTSALPOINT * pPtAry)599 void Os2SalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
600 PCONSTSALPOINT* pPtAry )
601 {
602 ULONG i;
603 long nHeight = mnHeight - 1;
604 PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ];
605
606 for( i = 0; i < nPoly; i++ )
607 {
608 const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ];
609
610 // create polygon
611 ULONG nTempPoints = pPoints[ i ];
612 POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ];
613
614 // convert all points to sys orientation
615 aPolygonAry[ i ].ulPoints = nTempPoints;
616 aPolygonAry[ i ].aPointl = pTempOS2PtAry;
617
618 while( nTempPoints-- )
619 {
620 (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
621 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
622 pTempOS2PtAry++;
623 pTempPtAry++;
624 }
625 }
626
627 // Innenleben zeichnen
628 if ( mbFill )
629 {
630 #ifdef SAL_PRINTER_POLYPATH
631 if ( mbPrinter )
632 {
633 Ft2BeginPath( mhPS, 1 );
634 for ( i = 0; i < nPoly; i++ )
635 {
636 Ft2Move( mhPS, aPolygonAry[i].aPointl );
637 Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl );
638 }
639 Ft2EndPath( mhPS );
640 Ft2FillPath( mhPS, 1, 0 );
641 }
642 else
643 #endif
644 {
645 ULONG nOptions = POLYGON_ALTERNATE;
646
647 if ( mbLine )
648 nOptions |= POLYGON_BOUNDARY;
649 else
650 nOptions |= POLYGON_NOBOUNDARY;
651
652 Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl );
653 GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL );
654 }
655 }
656 else
657 {
658 if ( mbLine )
659 {
660 for( i = 0; i < nPoly; i++ )
661 {
662 Ft2Move( mhPS, aPolygonAry[ i ].aPointl );
663 GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl );
664 }
665 }
666 }
667
668 // cleanup
669 for( i = 0; i < nPoly; i++ )
670 delete [] aPolygonAry[ i ].aPointl;
671 delete [] aPolygonAry;
672 }
673
674 // -----------------------------------------------------------------------
675
drawPolyPolygon(const::basegfx::B2DPolyPolygon &,double)676 bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
677 {
678 // TODO: implement and advertise OutDevSupport_B2DDraw support
679 return false;
680 }
681
682 // -----------------------------------------------------------------------
683
drawPolyLine(const basegfx::B2DPolygon &,double,const basegfx::B2DVector &,basegfx::B2DLineJoin,com::sun::star::drawing::LineCap)684 bool Os2SalGraphics::drawPolyLine(
685 const basegfx::B2DPolygon& /*rPolygon*/,
686 double /*fTransparency*/,
687 const basegfx::B2DVector& /*rLineWidths*/,
688 basegfx::B2DLineJoin /*eLineJoin*/,
689 com::sun::star::drawing::LineCap /*eLineCap*/)
690 {
691 // TODO: implement
692 return false;
693 }
694
695 // -----------------------------------------------------------------------
696
drawPolyLineBezier(sal_uInt32,const SalPoint * pPtAry,const sal_uInt8 * pFlgAry)697 sal_Bool Os2SalGraphics::drawPolyLineBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
698 {
699 return sal_False;
700 }
701
702 // -----------------------------------------------------------------------
703
drawPolygonBezier(sal_uInt32,const SalPoint * pPtAry,const sal_uInt8 * pFlgAry)704 sal_Bool Os2SalGraphics::drawPolygonBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
705 {
706 return sal_False;
707 }
708
709 // -----------------------------------------------------------------------
710
drawPolyPolygonBezier(sal_uInt32,const sal_uInt32 *,const SalPoint * const * pPtAry,const sal_uInt8 * const * pFlgAry)711 sal_Bool Os2SalGraphics::drawPolyPolygonBezier( sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/,
712 const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry )
713 {
714 return sal_False;
715 }
716
717 // =======================================================================
718
719 // MAXIMUM BUFSIZE EQ 0xFFFF
720 #define POSTSCRIPT_BUFSIZE 0x4000
721 // we only try to get the BoundingBox in the first 4096 PM_BYTEs
722 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000
723
ImplSearchEntry(PM_BYTE * pSource,PM_BYTE * pDest,ULONG nComp,ULONG nSize)724 static PM_BYTE* ImplSearchEntry( PM_BYTE* pSource, PM_BYTE* pDest, ULONG nComp, ULONG nSize )
725 {
726 while ( nComp-- >= nSize )
727 {
728 ULONG i;
729 for ( i = 0; i < nSize; i++ )
730 {
731 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
732 break;
733 }
734 if ( i == nSize )
735 return pSource;
736 pSource++;
737 }
738 return NULL;
739 }
740
741
ImplGetBoundingBox(double * nNumb,PM_BYTE * pSource,ULONG nSize)742 static PM_BOOL ImplGetBoundingBox( double* nNumb, PM_BYTE* pSource, ULONG nSize )
743 {
744 PM_BOOL bRetValue = FALSE;
745 PM_BYTE* pDest = ImplSearchEntry( pSource, (PM_BYTE*)"%%BoundingBox:", nSize, 14 );
746 if ( pDest )
747 {
748 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
749 pDest += 14;
750
751 int nSizeLeft = nSize - ( pDest - pSource );
752 if ( nSizeLeft > 100 )
753 nSizeLeft = 100; // only 100 PM_BYTEs following the bounding box will be checked
754
755 int i;
756 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
757 {
758 int nDivision = 1;
759 PM_BOOL bDivision = FALSE;
760 PM_BOOL bNegative = FALSE;
761 PM_BOOL bValid = TRUE;
762
763 while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
764 PM_BYTE nPM_BYTE = *pDest;
765 while ( nSizeLeft && ( nPM_BYTE != ' ' ) && ( nPM_BYTE != 0x9 ) && ( nPM_BYTE != 0xd ) && ( nPM_BYTE != 0xa ) )
766 {
767 switch ( nPM_BYTE )
768 {
769 case '.' :
770 if ( bDivision )
771 bValid = FALSE;
772 else
773 bDivision = TRUE;
774 break;
775 case '-' :
776 bNegative = TRUE;
777 break;
778 default :
779 if ( ( nPM_BYTE < '0' ) || ( nPM_BYTE > '9' ) )
780 nSizeLeft = 1; // error parsing the bounding box values
781 else if ( bValid )
782 {
783 if ( bDivision )
784 nDivision*=10;
785 nNumb[i] *= 10;
786 nNumb[i] += nPM_BYTE - '0';
787 }
788 break;
789 }
790 nSizeLeft--;
791 nPM_BYTE = *(++pDest);
792 }
793 if ( bNegative )
794 nNumb[i] = -nNumb[i];
795 if ( bDivision && ( nDivision != 1 ) )
796 nNumb[i] /= nDivision;
797 }
798 if ( i == 4 )
799 bRetValue = TRUE;
800 }
801 return bRetValue;
802 }
803
804 #if 0
805 static void ImplWriteDouble( PM_BYTE** pBuf, double nNumber )
806 {
807 // *pBuf += sprintf( (char*)*pBuf, "%f", nNumber );
808
809 if ( nNumber < 0 )
810 {
811 *(*pBuf)++ = (PM_BYTE)'-';
812 nNumber = -nNumber;
813 }
814 ULONG nTemp = (ULONG)nNumber;
815 const String aNumber1( nTemp );
816 ULONG nLen = aNumber1.Len();
817
818 for ( USHORT n = 0; n < nLen; n++ )
819 *(*pBuf)++ = aNumber1[ n ];
820
821 nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 );
822 if ( nTemp )
823 {
824 *(*pBuf)++ = (PM_BYTE)'.';
825 const String aNumber2( nTemp );
826
827 ULONG nLen = aNumber2.Len();
828 if ( nLen < 8 )
829 {
830 for ( n = 0; n < ( 5 - nLen ); n++ )
831 {
832 *(*pBuf)++ = (PM_BYTE)'0';
833 }
834 }
835 for ( USHORT n = 0; n < nLen; n++ )
836 {
837 *(*pBuf)++ = aNumber2[ n ];
838 }
839 }
840 *(*pBuf)++ = ' ';
841 }
842 #endif
843
ImplWriteString(PM_BYTE ** pBuf,const char * sString)844 inline void ImplWriteString( PM_BYTE** pBuf, const char* sString )
845 {
846 strcpy( (char*)*pBuf, sString );
847 *pBuf += strlen( sString );
848 }
849
drawEPS(long nX,long nY,long nWidth,long nHeight,void * pPtr,ULONG nSize)850 sal_Bool Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize )
851 {
852 if ( !mbPrinter )
853 return FALSE;
854
855 PM_BOOL bRet = FALSE;
856 LONG nLong = 0;
857 if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) &&
858 (CAPS_TECH_POSTSCRIPT == nLong)) )
859 return FALSE;
860
861 PM_BYTE* pBuf = new PM_BYTE[ POSTSCRIPT_BUFSIZE ];
862 double nBoundingBox[4];
863
864 if ( pBuf && ImplGetBoundingBox( nBoundingBox, (PM_BYTE*)pPtr, nSize ) )
865 {
866 LONG pOS2DXAry[4]; // hack -> print always 2 white space
867 POINTL aPt;
868 aPt.x = 0;
869 aPt.y = 0;
870 PCH pStr = (PCH) " ";
871 for( long i = 0; i < 4; i++ )
872 pOS2DXAry[i] = i;
873 Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] );
874
875 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
876
877 // reserve place for a USHORT
878 aBuf.append( "aa" );
879
880 // #107797# Write out EPS encapsulation header
881 // ----------------------------------------------------------------------------------
882
883 // directly taken from the PLRM 3.0, p. 726. Note:
884 // this will definitely cause problems when
885 // recursively creating and embedding PostScript files
886 // in OOo, since we use statically-named variables
887 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
888 // op_count_salWin). Currently, I have no idea on how to
889 // work around that, except from scanning and
890 // interpreting the EPS for unused identifiers.
891
892 // append the real text
893 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
894 "/dict_count_salWin countdictstack def\n"
895 "/op_count_salWin count 1 sub def\n"
896 "userdict begin\n"
897 "/showpage {} def\n"
898 "0 setgray 0 setlinecap\n"
899 "1 setlinewidth 0 setlinejoin\n"
900 "10 setmiterlimit [] 0 setdash newpath\n"
901 "/languagelevel where\n"
902 "{\n"
903 " pop languagelevel\n"
904 " 1 ne\n"
905 " {\n"
906 " false setstrokeadjust false setoverprint\n"
907 " } if\n"
908 "} if\n\n" );
909
910 #if 0
911 // #i10737# Apply clipping manually
912 // ----------------------------------------------------------------------------------
913
914 // Windows seems to ignore any clipping at the HDC,
915 // when followed by a POSTSCRIPT_PASSTHROUGH
916
917 // Check whether we've got a clipping, consisting of
918 // exactly one rect (other cases should be, but aren't
919 // handled currently)
920
921 // TODO: Handle more than one rectangle here (take
922 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
923 // characters!)
924 if ( mhRegion != 0 &&
925 mpStdClipRgnData != NULL &&
926 mpClipRgnData == mpStdClipRgnData &&
927 mpClipRgnData->rdh.nCount == 1 )
928 {
929 RECT* pRect = &(mpClipRgnData->rdh.rcBound);
930
931 aBuf.append( "\nnewpath\n" );
932 aBuf.append( pRect->left );
933 aBuf.append( " " );
934 aBuf.append( pRect->top );
935 aBuf.append( " moveto\n" );
936 aBuf.append( pRect->right );
937 aBuf.append( " " );
938 aBuf.append( pRect->top );
939 aBuf.append( " lineto\n" );
940 aBuf.append( pRect->right );
941 aBuf.append( " " );
942 aBuf.append( pRect->bottom );
943 aBuf.append( " lineto\n" );
944 aBuf.append( pRect->left );
945 aBuf.append( " " );
946 aBuf.append( pRect->bottom );
947 aBuf.append( " lineto\n"
948 "closepath\n"
949 "clip\n"
950 "newpath\n" );
951 }
952 #endif
953
954 // #107797# Write out buffer
955 // ----------------------------------------------------------------------------------
956 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
957 //Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
958 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
959 (PM_BYTE*)aBuf.getStr(), 0, NULL );
960
961 double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
962 double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) );
963
964 // reserve a USHORT again
965 aBuf.setLength( 2 );
966 aBuf.append( "\n\n[" );
967 aBuf.append( dM11 );
968 aBuf.append( " 0 0 " );
969 aBuf.append( dM22 );
970 aBuf.append( ' ' );
971 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
972 aBuf.append( ' ' );
973 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
974 aBuf.append( "] concat\n"
975 "%%BeginDocument:\n" );
976 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
977 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
978 (PM_BYTE*)aBuf.getStr(), 0, NULL );
979 #if 0
980 PM_BYTE* pTemp = pBuf;
981 ImplWriteString( &pTemp, "save\n[ " );
982 ImplWriteDouble( &pTemp, dM11 );
983 ImplWriteDouble( &pTemp, 0 );
984 ImplWriteDouble( &pTemp, 0 );
985 ImplWriteDouble( &pTemp, dM22 );
986 ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) );
987 ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) );
988 ImplWriteString( &pTemp, "] concat /showpage {} def\n" );
989
990 if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf,
991 (PM_BYTE*)pBuf, 0, NULL ) == DEV_OK )
992 #endif //
993 {
994 sal_uInt32 nToDo = nSize;
995 sal_uInt32 nDoNow;
996 bRet = TRUE;
997 while( nToDo && bRet )
998 {
999 nDoNow = 0x4000;
1000 if ( nToDo < nDoNow )
1001 nDoNow = nToDo;
1002
1003 if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PM_BYTE*)pPtr + nSize - nToDo,
1004 0, NULL ) == -1 )
1005 bRet = FALSE;
1006 nToDo -= nDoNow;
1007 }
1008
1009 if ( bRet )
1010 {
1011 strcpy ( (char*)pBuf, "\nrestore\n" );
1012 if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PM_BYTE*)pBuf,
1013 0, NULL ) == DEV_OK ) bRet = TRUE;
1014 }
1015
1016 // #107797# Write out EPS encapsulation footer
1017 // ----------------------------------------------------------------------------------
1018 // reserve a USHORT again
1019 aBuf.setLength( 2 );
1020 aBuf.append( "%%EndDocument\n"
1021 "count op_count_salWin sub {pop} repeat\n"
1022 "countdictstack dict_count_salWin sub {end} repeat\n"
1023 "b4_Inc_state_salWin restore\n\n" );
1024 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
1025 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
1026 (PM_BYTE*)aBuf.getStr(), 0, NULL );
1027 bRet = TRUE;
1028
1029 }
1030 }
1031 delete [] pBuf;
1032 return bRet;
1033 }
1034
1035 /*
1036 * IsNativeControlSupported()
1037 *
1038 * Returns TRUE if the platform supports native
1039 * drawing of the control defined by nPart
1040 */
IsNativeControlSupported(ControlType nType,ControlPart nPart)1041 sal_Bool Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
1042 {
1043 return( FALSE );
1044 }
1045
1046 // -----------------------------------------------------------------------
1047
GetGraphicsData() const1048 SystemGraphicsData Os2SalGraphics::GetGraphicsData() const
1049 {
1050 SystemGraphicsData aRes;
1051 aRes.nSize = sizeof(aRes);
1052 #if 0
1053 aRes.hDC = mhDC;
1054 #endif
1055 return aRes;
1056 }
1057
1058 // -----------------------------------------------------------------------
1059