blob: 334f02835ba9afc394d8baa996134e3af6507b27 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include <string.h>
#include <svpm.h>
#define _SV_SALGDI_CXX
#include <tools/debug.hxx>
#include <os2/saldata.hxx>
#include <os2/salgdi.h>
#include <tools/debug.hxx>
#include <os2/salframe.h>
#include <tools/poly.hxx>
#ifndef _RTL_STRINGBUF_HXX
#include <rtl/strbuf.hxx>
#endif
#ifndef __H_FT2LIB
#include <os2/wingdi.h>
#include <ft2lib.h>
#endif
// -----------
// - Defines -
// -----------
// ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern
#define SAL_PRINTER_CLIPPATH 1
// #define SAL_PRINTER_POLYPATH 1
// =======================================================================
void ImplInitSalGDI()
{
}
// -----------------------------------------------------------------------
void ImplFreeSalGDI()
{
SalData* pSalData = GetSalData();
// delete icon cache
SalIcon* pIcon = pSalData->mpFirstIcon;
while( pIcon )
{
SalIcon* pTmp = pIcon->pNext;
WinDestroyPointer( pIcon->hIcon );
delete pIcon;
pIcon = pTmp;
}
}
// =======================================================================
void ImplSalInitGraphics( Os2SalGraphics* pData )
{
GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL );
}
// -----------------------------------------------------------------------
void ImplSalDeInitGraphics( Os2SalGraphics* pData )
{
}
// =======================================================================
Os2SalGraphics::Os2SalGraphics()
{
for( int i = 0; i < MAX_FALLBACK; ++i )
{
mhFonts[ i ] = 0;
mpOs2FontData[ i ] = NULL;
mpOs2FontEntry[ i ] = NULL;
}
mfFontScale = 1.0;
mhPS = 0;
mhDC = 0;
mbLine = FALSE;
mbFill = FALSE;
mbXORMode = FALSE;
mnFontMetricCount = 0;
mpFontMetrics = NULL;
mpClipRectlAry = NULL;
mhDefFont = 0;
mpFontKernPairs = NULL;
mnFontKernPairCount = 0;
mbFontKernInit = FALSE;
}
// -----------------------------------------------------------------------
Os2SalGraphics::~Os2SalGraphics()
{
Ft2DeleteSetId( mhPS, LCID_BASE);
if ( mpFontMetrics )
delete mpFontMetrics;
if ( mpFontKernPairs )
delete mpFontKernPairs;
}
// -----------------------------------------------------------------------
static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
{
SalColor nSalColor;
switch( nROPColor )
{
case SAL_ROP_0:
nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
break;
case SAL_ROP_1:
case SAL_ROP_INVERT:
nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
break;
}
return nSalColor;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
{
// since OOo asks for DPI, I will query FONT_RES, which seems to be
// more correct than _RESOLUTION fields (on my wide screen lcd)
// and does not require conversion
long nDPIX = 72, nDPIY = 72;
DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &nDPIX );
DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &nDPIY );
rDPIX = nDPIX;
rDPIY = nDPIY;
}
// -----------------------------------------------------------------------
USHORT Os2SalGraphics::GetBitCount()
{
LONG nBitCount;
DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount );
return (USHORT)nBitCount;
}
// -----------------------------------------------------------------------
long Os2SalGraphics::GetGraphicsWidth() const
{
if( mhWnd )
{
Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd );
if( pFrame )
{
if( pFrame->maGeometry.nWidth )
return pFrame->maGeometry.nWidth;
else
{
// TODO: perhaps not needed, maGeometry should always be up-to-date
RECTL aRect;
WinQueryWindowRect( mhWnd, &aRect );
return aRect.xRight;
}
}
}
return 0;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::ResetClipRegion()
{
#ifdef SAL_PRINTER_CLIPPATH
if ( mbPrinter )
GpiSetClipPath( mhPS, 0, SCP_RESET );
else
#endif
{
HRGN hOldRegion;
GpiSetClipRegion( mhPS, NULL, &hOldRegion );
if ( hOldRegion )
GpiDestroyRegion( mhPS, hOldRegion );
}
}
// -----------------------------------------------------------------------
bool Os2SalGraphics::setClipRegion( const Region& i_rClip )
{
RectangleVector aRectangles;
i_rClip.GetRegionRectangles(aRectangles);
mnClipElementCount = aRectangles.size();
mpClipRectlAry = 0;
if(mnClipElementCount)
{
mpClipRectlAry = new RECTL[mnClipElementCount];
for(sal_uInt32 a(0); a < mnClipElementCount; a++)
{
const Rectangle& rRect = aRectangles[a];
RECTL* pClipRect = &mpClipRectlAry[a];
pClipRect->xLeft = rRect.Left();
pClipRect->yTop = mnHeight - rRect.Top();
pClipRect->xRight = rRect.Right() + 1; // nX + nW -> L + ((R - L) + 1) -> R + 1
pClipRect->yBottom = mnHeight - (rRect.Bottom() + 1); // same for height
}
}
// ULONG nCount = i_rClip.GetRectCount();
//
// mpClipRectlAry = new RECTL[ nCount ];
// mnClipElementCount = 0;
//
// ImplRegionInfo aInfo;
// long nX, nY, nW, nH;
// bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
// while( bRegionRect )
// {
// if ( nW && nH )
// {
// RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ];
// pClipRect->xLeft = nX;
// pClipRect->yTop = mnHeight - nY;
// pClipRect->xRight = nX + nW;
// pClipRect->yBottom = mnHeight - (nY + nH);
// mnClipElementCount++;
// }
// bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
// }
#ifdef SAL_PRINTER_CLIPPATH
if ( mbPrinter )
{
GpiSetClipPath( mhPS, 0, SCP_RESET );
GpiBeginPath( mhPS, 1L );
for( int i = 0; i < mnClipElementCount; i++ )
{
POINTL aPt;
RECTL* pClipRect = &mpClipRectlAry[ i ];
aPt.x = pClipRect->xLeft;
aPt.y = pClipRect->yTop-1;
Ft2Move( mhPS, &aPt );
aPt.x = pClipRect->xRight-1;
aPt.y = pClipRect->yBottom;
Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
}
GpiEndPath( mhPS );
GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND );
}
else
#endif
{
HRGN hClipRegion = GpiCreateRegion( mhPS,
mnClipElementCount,
mpClipRectlAry );
HRGN hOldRegion;
GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion );
if( hOldRegion )
GpiDestroyRegion( mhPS, hOldRegion );
}
delete [] mpClipRectlAry;
return true;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetLineColor()
{
// don't draw line!
mbLine = FALSE;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetLineColor( SalColor nSalColor )
{
LINEBUNDLE lb;
// set color
lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
SALCOLOR_GREEN( nSalColor ),
SALCOLOR_BLUE( nSalColor ) );
Ft2SetAttrs( mhPS,
PRIM_LINE,
LBB_COLOR,
0,
&lb );
// draw line!
mbLine = TRUE;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetFillColor()
{
// don't fill area!
mbFill = FALSE;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetFillColor( SalColor nSalColor )
{
AREABUNDLE ab;
// set color
ab.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
SALCOLOR_GREEN( nSalColor ),
SALCOLOR_BLUE( nSalColor ) );
Ft2SetAttrs( mhPS,
PRIM_AREA,
ABB_COLOR,
0,
&ab );
// fill area!
mbFill = TRUE;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetXORMode( bool bSet, bool )
{
mbXORMode = bSet;
LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT;
// set mix mode for lines
LINEBUNDLE lb;
lb.usMixMode = nMixMode;
Ft2SetAttrs( mhPS,
PRIM_LINE,
LBB_MIX_MODE,
0,
&lb );
// set mix mode for areas
AREABUNDLE ab;
ab.usMixMode = nMixMode;
Ft2SetAttrs( mhPS,
PRIM_AREA,
ABB_MIX_MODE,
0,
&ab );
// set mix mode for text
CHARBUNDLE cb;
cb.usMixMode = nMixMode;
Ft2SetAttrs( mhPS,
PRIM_CHAR,
CBB_MIX_MODE,
0,
&cb );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor )
{
SetLineColor( ImplGetROPSalColor( nROPColor ) );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor )
{
SetFillColor( ImplGetROPSalColor( nROPColor ) );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawPixel( long nX, long nY )
{
POINTL aPt;
aPt.x = nX;
aPt.y = TY( nY );
// set color
Ft2SetPel( mhPS, &aPt );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
{
// save old color
LINEBUNDLE oldLb;
GpiQueryAttrs( mhPS,
PRIM_LINE,
LBB_COLOR,
&oldLb );
// set new color
LINEBUNDLE lb;
lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
SALCOLOR_GREEN( nSalColor ),
SALCOLOR_BLUE( nSalColor ) );
Ft2SetAttrs( mhPS,
PRIM_LINE,
LBB_COLOR,
0,
&lb );
// set color of pixel
POINTL aPt;
aPt.x = nX;
aPt.y = TY( nY );
Ft2SetPel( mhPS, &aPt );
// restore old color
Ft2SetAttrs( mhPS,
PRIM_LINE,
LBB_COLOR,
0,
&oldLb );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
{
// OS2 zeichnet den Endpunkt mit
POINTL aPt;
aPt.x = nX1;
aPt.y = TY( nY1 );
Ft2Move( mhPS, &aPt );
aPt.x = nX2;
aPt.y = TY( nY2 );
GpiLine( mhPS, &aPt );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
{
POINTL aPt;
long lControl;
if ( mbFill )
{
if ( mbLine )
lControl = DRO_OUTLINEFILL;
else
lControl = DRO_FILL;
}
else
{
if ( mbLine )
lControl = DRO_OUTLINE;
else
return;
}
aPt.x = nX;
aPt.y = TY( nY );
Ft2Move( mhPS, &aPt );
aPt.x = nX + nWidth - 1;
aPt.y = TY( nY + nHeight - 1 );
Ft2Box( mhPS, lControl, &aPt, 0, 0 );
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
{
// convert all points to sys orientation
POINTL* pOS2PtAry = new POINTL[ nPoints ];
POINTL* pTempOS2PtAry = pOS2PtAry;
const SalPoint* pTempPtAry = pPtAry;
sal_uInt32 nTempPoints = nPoints;
long nHeight = mnHeight - 1;
while( nTempPoints-- )
{
(*pTempOS2PtAry).x = (*pTempPtAry).mnX;
(*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
pTempOS2PtAry++;
pTempPtAry++;
}
Ft2Move( mhPS, pOS2PtAry );
GpiPolyLine( mhPS, nPoints, pOS2PtAry );
delete [] pOS2PtAry;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
{
PM_POLYGON aPolygon;
// create polygon
aPolygon.aPointl = new POINTL[ nPoints ];
aPolygon.ulPoints = nPoints;
// convert all points to sys orientation
POINTL* pTempOS2PtAry = aPolygon.aPointl;
const SalPoint* pTempPtAry = pPtAry;
sal_uInt32 nTempPoints = nPoints;
long nHeight = mnHeight - 1;
while( nTempPoints-- )
{
(*pTempOS2PtAry).x = (*pTempPtAry).mnX;
(*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
pTempOS2PtAry++;
pTempPtAry++;
}
// Innenleben zeichnen
if ( mbFill )
{
#ifdef SAL_PRINTER_POLYPATH
if ( mbPrinter )
{
Ft2BeginPath( mhPS, 1 );
Ft2Move( mhPS, aPolygon.aPointl );
Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
Ft2EndPath( mhPS );
Ft2FillPath( mhPS, 1, 0 );
if ( mbLine )
{
Ft2Move( mhPS, aPolygon.aPointl );
Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
}
}
else
#endif
{
ULONG nOptions = POLYGON_ALTERNATE;
if ( mbLine )
nOptions |= POLYGON_BOUNDARY;
else
nOptions |= POLYGON_NOBOUNDARY;
Ft2Move( mhPS, aPolygon.aPointl );
GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL );
}
}
else
{
if ( mbLine )
{
Ft2Move( mhPS, aPolygon.aPointl );
GpiPolyLine( mhPS, nPoints, aPolygon.aPointl );
}
}
delete [] aPolygon.aPointl;
}
// -----------------------------------------------------------------------
void Os2SalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
PCONSTSALPOINT* pPtAry )
{
ULONG i;
long nHeight = mnHeight - 1;
PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ];
for( i = 0; i < nPoly; i++ )
{
const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ];
// create polygon
ULONG nTempPoints = pPoints[ i ];
POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ];
// convert all points to sys orientation
aPolygonAry[ i ].ulPoints = nTempPoints;
aPolygonAry[ i ].aPointl = pTempOS2PtAry;
while( nTempPoints-- )
{
(*pTempOS2PtAry).x = (*pTempPtAry).mnX;
(*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
pTempOS2PtAry++;
pTempPtAry++;
}
}
// Innenleben zeichnen
if ( mbFill )
{
#ifdef SAL_PRINTER_POLYPATH
if ( mbPrinter )
{
Ft2BeginPath( mhPS, 1 );
for ( i = 0; i < nPoly; i++ )
{
Ft2Move( mhPS, aPolygonAry[i].aPointl );
Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl );
}
Ft2EndPath( mhPS );
Ft2FillPath( mhPS, 1, 0 );
}
else
#endif
{
ULONG nOptions = POLYGON_ALTERNATE;
if ( mbLine )
nOptions |= POLYGON_BOUNDARY;
else
nOptions |= POLYGON_NOBOUNDARY;
Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl );
GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL );
}
}
else
{
if ( mbLine )
{
for( i = 0; i < nPoly; i++ )
{
Ft2Move( mhPS, aPolygonAry[ i ].aPointl );
GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl );
}
}
}
// cleanup
for( i = 0; i < nPoly; i++ )
delete [] aPolygonAry[ i ].aPointl;
delete [] aPolygonAry;
}
// -----------------------------------------------------------------------
bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
{
// TODO: implement and advertise OutDevSupport_B2DDraw support
return false;
}
// -----------------------------------------------------------------------
bool Os2SalGraphics::drawPolyLine(
const basegfx::B2DPolygon& /*rPolygon*/,
double /*fTransparency*/,
const basegfx::B2DVector& /*rLineWidths*/,
basegfx::B2DLineJoin /*eLineJoin*/,
com::sun::star::drawing::LineCap /*eLineCap*/)
{
// TODO: implement
return false;
}
// -----------------------------------------------------------------------
sal_Bool Os2SalGraphics::drawPolyLineBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
{
return sal_False;
}
// -----------------------------------------------------------------------
sal_Bool Os2SalGraphics::drawPolygonBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
{
return sal_False;
}
// -----------------------------------------------------------------------
sal_Bool Os2SalGraphics::drawPolyPolygonBezier( sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/,
const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry )
{
return sal_False;
}
// =======================================================================
// MAXIMUM BUFSIZE EQ 0xFFFF
#define POSTSCRIPT_BUFSIZE 0x4000
// we only try to get the BoundingBox in the first 4096 PM_BYTEs
#define POSTSCRIPT_BOUNDINGSEARCH 0x1000
static PM_BYTE* ImplSearchEntry( PM_BYTE* pSource, PM_BYTE* pDest, ULONG nComp, ULONG nSize )
{
while ( nComp-- >= nSize )
{
ULONG i;
for ( i = 0; i < nSize; i++ )
{
if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
break;
}
if ( i == nSize )
return pSource;
pSource++;
}
return NULL;
}
static PM_BOOL ImplGetBoundingBox( double* nNumb, PM_BYTE* pSource, ULONG nSize )
{
PM_BOOL bRetValue = FALSE;
PM_BYTE* pDest = ImplSearchEntry( pSource, (PM_BYTE*)"%%BoundingBox:", nSize, 14 );
if ( pDest )
{
nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
pDest += 14;
int nSizeLeft = nSize - ( pDest - pSource );
if ( nSizeLeft > 100 )
nSizeLeft = 100; // only 100 PM_BYTEs following the bounding box will be checked
int i;
for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
{
int nDivision = 1;
PM_BOOL bDivision = FALSE;
PM_BOOL bNegative = FALSE;
PM_BOOL bValid = TRUE;
while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
PM_BYTE nPM_BYTE = *pDest;
while ( nSizeLeft && ( nPM_BYTE != ' ' ) && ( nPM_BYTE != 0x9 ) && ( nPM_BYTE != 0xd ) && ( nPM_BYTE != 0xa ) )
{
switch ( nPM_BYTE )
{
case '.' :
if ( bDivision )
bValid = FALSE;
else
bDivision = TRUE;
break;
case '-' :
bNegative = TRUE;
break;
default :
if ( ( nPM_BYTE < '0' ) || ( nPM_BYTE > '9' ) )
nSizeLeft = 1; // error parsing the bounding box values
else if ( bValid )
{
if ( bDivision )
nDivision*=10;
nNumb[i] *= 10;
nNumb[i] += nPM_BYTE - '0';
}
break;
}
nSizeLeft--;
nPM_BYTE = *(++pDest);
}
if ( bNegative )
nNumb[i] = -nNumb[i];
if ( bDivision && ( nDivision != 1 ) )
nNumb[i] /= nDivision;
}
if ( i == 4 )
bRetValue = TRUE;
}
return bRetValue;
}
#if 0
static void ImplWriteDouble( PM_BYTE** pBuf, double nNumber )
{
// *pBuf += sprintf( (char*)*pBuf, "%f", nNumber );
if ( nNumber < 0 )
{
*(*pBuf)++ = (PM_BYTE)'-';
nNumber = -nNumber;
}
ULONG nTemp = (ULONG)nNumber;
const String aNumber1( nTemp );
ULONG nLen = aNumber1.Len();
for ( USHORT n = 0; n < nLen; n++ )
*(*pBuf)++ = aNumber1[ n ];
nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 );
if ( nTemp )
{
*(*pBuf)++ = (PM_BYTE)'.';
const String aNumber2( nTemp );
ULONG nLen = aNumber2.Len();
if ( nLen < 8 )
{
for ( n = 0; n < ( 5 - nLen ); n++ )
{
*(*pBuf)++ = (PM_BYTE)'0';
}
}
for ( USHORT n = 0; n < nLen; n++ )
{
*(*pBuf)++ = aNumber2[ n ];
}
}
*(*pBuf)++ = ' ';
}
#endif
inline void ImplWriteString( PM_BYTE** pBuf, const char* sString )
{
strcpy( (char*)*pBuf, sString );
*pBuf += strlen( sString );
}
sal_Bool Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize )
{
if ( !mbPrinter )
return FALSE;
PM_BOOL bRet = FALSE;
LONG nLong = 0;
if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) &&
(CAPS_TECH_POSTSCRIPT == nLong)) )
return FALSE;
PM_BYTE* pBuf = new PM_BYTE[ POSTSCRIPT_BUFSIZE ];
double nBoundingBox[4];
if ( pBuf && ImplGetBoundingBox( nBoundingBox, (PM_BYTE*)pPtr, nSize ) )
{
LONG pOS2DXAry[4]; // hack -> print always 2 white space
POINTL aPt;
aPt.x = 0;
aPt.y = 0;
PCH pStr = (PCH) " ";
for( long i = 0; i < 4; i++ )
pOS2DXAry[i] = i;
Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] );
OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
// reserve place for a USHORT
aBuf.append( "aa" );
// #107797# Write out EPS encapsulation header
// ----------------------------------------------------------------------------------
// directly taken from the PLRM 3.0, p. 726. Note:
// this will definitely cause problems when
// recursively creating and embedding PostScript files
// in OOo, since we use statically-named variables
// here (namely, b4_Inc_state_salWin, dict_count_salWin and
// op_count_salWin). Currently, I have no idea on how to
// work around that, except from scanning and
// interpreting the EPS for unused identifiers.
// append the real text
aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
"/dict_count_salWin countdictstack def\n"
"/op_count_salWin count 1 sub def\n"
"userdict begin\n"
"/showpage {} def\n"
"0 setgray 0 setlinecap\n"
"1 setlinewidth 0 setlinejoin\n"
"10 setmiterlimit [] 0 setdash newpath\n"
"/languagelevel where\n"
"{\n"
" pop languagelevel\n"
" 1 ne\n"
" {\n"
" false setstrokeadjust false setoverprint\n"
" } if\n"
"} if\n\n" );
#if 0
// #i10737# Apply clipping manually
// ----------------------------------------------------------------------------------
// Windows seems to ignore any clipping at the HDC,
// when followed by a POSTSCRIPT_PASSTHROUGH
// Check whether we've got a clipping, consisting of
// exactly one rect (other cases should be, but aren't
// handled currently)
// TODO: Handle more than one rectangle here (take
// care, the buffer can handle only POSTSCRIPT_BUFSIZE
// characters!)
if ( mhRegion != 0 &&
mpStdClipRgnData != NULL &&
mpClipRgnData == mpStdClipRgnData &&
mpClipRgnData->rdh.nCount == 1 )
{
RECT* pRect = &(mpClipRgnData->rdh.rcBound);
aBuf.append( "\nnewpath\n" );
aBuf.append( pRect->left );
aBuf.append( " " );
aBuf.append( pRect->top );
aBuf.append( " moveto\n" );
aBuf.append( pRect->right );
aBuf.append( " " );
aBuf.append( pRect->top );
aBuf.append( " lineto\n" );
aBuf.append( pRect->right );
aBuf.append( " " );
aBuf.append( pRect->bottom );
aBuf.append( " lineto\n" );
aBuf.append( pRect->left );
aBuf.append( " " );
aBuf.append( pRect->bottom );
aBuf.append( " lineto\n"
"closepath\n"
"clip\n"
"newpath\n" );
}
#endif
// #107797# Write out buffer
// ----------------------------------------------------------------------------------
*((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
//Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
(PM_BYTE*)aBuf.getStr(), 0, NULL );
double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) );
// reserve a USHORT again
aBuf.setLength( 2 );
aBuf.append( "\n\n[" );
aBuf.append( dM11 );
aBuf.append( " 0 0 " );
aBuf.append( dM22 );
aBuf.append( ' ' );
aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
aBuf.append( ' ' );
aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
aBuf.append( "] concat\n"
"%%BeginDocument:\n" );
*((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
(PM_BYTE*)aBuf.getStr(), 0, NULL );
#if 0
PM_BYTE* pTemp = pBuf;
ImplWriteString( &pTemp, "save\n[ " );
ImplWriteDouble( &pTemp, dM11 );
ImplWriteDouble( &pTemp, 0 );
ImplWriteDouble( &pTemp, 0 );
ImplWriteDouble( &pTemp, dM22 );
ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) );
ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) );
ImplWriteString( &pTemp, "] concat /showpage {} def\n" );
if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf,
(PM_BYTE*)pBuf, 0, NULL ) == DEV_OK )
#endif //
{
sal_uInt32 nToDo = nSize;
sal_uInt32 nDoNow;
bRet = TRUE;
while( nToDo && bRet )
{
nDoNow = 0x4000;
if ( nToDo < nDoNow )
nDoNow = nToDo;
if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PM_BYTE*)pPtr + nSize - nToDo,
0, NULL ) == -1 )
bRet = FALSE;
nToDo -= nDoNow;
}
if ( bRet )
{
strcpy ( (char*)pBuf, "\nrestore\n" );
if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PM_BYTE*)pBuf,
0, NULL ) == DEV_OK ) bRet = TRUE;
}
// #107797# Write out EPS encapsulation footer
// ----------------------------------------------------------------------------------
// reserve a USHORT again
aBuf.setLength( 2 );
aBuf.append( "%%EndDocument\n"
"count op_count_salWin sub {pop} repeat\n"
"countdictstack dict_count_salWin sub {end} repeat\n"
"b4_Inc_state_salWin restore\n\n" );
*((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
(PM_BYTE*)aBuf.getStr(), 0, NULL );
bRet = TRUE;
}
}
delete [] pBuf;
return bRet;
}
/*
* IsNativeControlSupported()
*
* Returns TRUE if the platform supports native
* drawing of the control defined by nPart
*/
sal_Bool Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
{
return( FALSE );
}
// -----------------------------------------------------------------------
SystemGraphicsData Os2SalGraphics::GetGraphicsData() const
{
SystemGraphicsData aRes;
aRes.nSize = sizeof(aRes);
#if 0
aRes.hDC = mhDC;
#endif
return aRes;
}
// -----------------------------------------------------------------------