| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <rtl/strbuf.hxx> |
| #include <tools/svwin.h> |
| #include <tools/debug.hxx> |
| #include <tools/poly.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <basegfx/polygon/b2dpolypolygontools.hxx> |
| #include <win/wincomp.hxx> |
| #include <win/saldata.hxx> |
| #include <win/salgdi.h> |
| #include <win/salframe.h> |
| #include <basegfx/matrix/b2dhommatrixtools.hxx> |
| |
| using namespace rtl; |
| |
| // ======================================================================= |
| |
| // comment out to prevent use of beziers on GDI functions |
| #define USE_GDI_BEZIERS |
| |
| // ======================================================================= |
| |
| #define DITHER_PAL_DELTA 51 |
| #define DITHER_PAL_STEPS 6 |
| #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS) |
| #define DITHER_MAX_SYSCOLOR 16 |
| #define DITHER_EXTRA_COLORS 1 |
| #define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal]) |
| |
| // ======================================================================= |
| |
| struct SysColorEntry |
| { |
| DWORD nRGB; |
| SysColorEntry* pNext; |
| }; |
| |
| // ======================================================================= |
| |
| static SysColorEntry* pFirstSysColor = NULL; |
| static SysColorEntry* pActSysColor = NULL; |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Blue7 |
| static PALETTEENTRY aImplExtraColor1 = |
| { |
| 0, 184, 255, 0 |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| |
| static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] = |
| { |
| { 0, 0, 0, 0 }, |
| { 0, 0, 0x80, 0 }, |
| { 0, 0x80, 0, 0 }, |
| { 0, 0x80, 0x80, 0 }, |
| { 0x80, 0, 0, 0 }, |
| { 0x80, 0, 0x80, 0 }, |
| { 0x80, 0x80, 0, 0 }, |
| { 0x80, 0x80, 0x80, 0 }, |
| { 0xC0, 0xC0, 0xC0, 0 }, |
| { 0, 0, 0xFF, 0 }, |
| { 0, 0xFF, 0, 0 }, |
| { 0, 0xFF, 0xFF, 0 }, |
| { 0xFF, 0, 0, 0 }, |
| { 0xFF, 0, 0xFF, 0 }, |
| { 0xFF, 0xFF, 0, 0 }, |
| { 0xFF, 0xFF, 0xFF, 0 } |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| |
| static BYTE aOrdDither8Bit[8][8] = |
| { |
| 0, 38, 9, 48, 2, 40, 12, 50, |
| 25, 12, 35, 22, 28, 15, 37, 24, |
| 6, 44, 3, 41, 8, 47, 5, 44, |
| 32, 19, 28, 16, 34, 21, 31, 18, |
| 1, 40, 11, 49, 0, 39, 10, 48, |
| 27, 14, 36, 24, 26, 13, 36, 23, |
| 8, 46, 4, 43, 7, 45, 4, 42, |
| 33, 20, 30, 17, 32, 20, 29, 16 |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| |
| static BYTE aOrdDither16Bit[8][8] = |
| { |
| 0, 6, 1, 7, 0, 6, 1, 7, |
| 4, 2, 5, 3, 4, 2, 5, 3, |
| 1, 7, 0, 6, 1, 7, 0, 6, |
| 5, 3, 4, 2, 5, 3, 4, 2, |
| 0, 6, 1, 7, 0, 6, 1, 7, |
| 4, 2, 5, 3, 4, 2, 5, 3, |
| 1, 7, 0, 6, 1, 7, 0, 6, |
| 5, 3, 4, 2, 5, 3, 4, 2 |
| }; |
| |
| // ======================================================================= |
| |
| // Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte |
| // viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und |
| // eine komplexe ClipRegion gesetzt ist |
| #define GSL_PEN_WIDTH 1 |
| |
| // ======================================================================= |
| |
| #define SAL_POLYPOLYCOUNT_STACKBUF 8 |
| #define SAL_POLYPOLYPOINTS_STACKBUF 64 |
| |
| // ======================================================================= |
| |
| void ImplInitSalGDI() |
| { |
| SalData* pSalData = GetSalData(); |
| |
| // init stock brushes |
| pSalData->maStockPenColorAry[0] = PALETTERGB( 0, 0, 0 ); |
| pSalData->maStockPenColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); |
| pSalData->maStockPenColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); |
| pSalData->maStockPenColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); |
| pSalData->mhStockPenAry[0] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[0] ); |
| pSalData->mhStockPenAry[1] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[1] ); |
| pSalData->mhStockPenAry[2] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[2] ); |
| pSalData->mhStockPenAry[3] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[3] ); |
| pSalData->mnStockPenCount = 4; |
| |
| pSalData->maStockBrushColorAry[0] = PALETTERGB( 0, 0, 0 ); |
| pSalData->maStockBrushColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); |
| pSalData->maStockBrushColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); |
| pSalData->maStockBrushColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); |
| pSalData->mhStockBrushAry[0] = CreateSolidBrush( pSalData->maStockBrushColorAry[0] ); |
| pSalData->mhStockBrushAry[1] = CreateSolidBrush( pSalData->maStockBrushColorAry[1] ); |
| pSalData->mhStockBrushAry[2] = CreateSolidBrush( pSalData->maStockBrushColorAry[2] ); |
| pSalData->mhStockBrushAry[3] = CreateSolidBrush( pSalData->maStockBrushColorAry[3] ); |
| pSalData->mnStockBrushCount = 4; |
| |
| // initialize cache of device contexts |
| pSalData->mpHDCCache = new HDCCache[ CACHESIZE_HDC ]; |
| memset( pSalData->mpHDCCache, 0, CACHESIZE_HDC * sizeof( HDCCache ) ); |
| |
| // initialize temporary font list |
| pSalData->mpTempFontItem = NULL; |
| |
| // support palettes for 256 color displays |
| HDC hDC = GetDC( 0 ); |
| int nBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); |
| int nPlanes = GetDeviceCaps( hDC, PLANES ); |
| int nRasterCaps = GetDeviceCaps( hDC, RASTERCAPS ); |
| int nBitCount = nBitsPixel * nPlanes; |
| |
| if ( (nBitCount > 8) && (nBitCount < 24) ) |
| { |
| // test, if we have to dither |
| HDC hMemDC = ::CreateCompatibleDC( hDC ); |
| HBITMAP hMemBmp = ::CreateCompatibleBitmap( hDC, 8, 8 ); |
| HBITMAP hBmpOld = (HBITMAP) ::SelectObject( hMemDC, hMemBmp ); |
| HBRUSH hMemBrush = ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) ); |
| HBRUSH hBrushOld = (HBRUSH) ::SelectObject( hMemDC, hMemBrush ); |
| sal_Bool bDither16 = TRUE; |
| |
| ::PatBlt( hMemDC, 0, 0, 8, 8, PATCOPY ); |
| const COLORREF aCol( ::GetPixel( hMemDC, 0, 0 ) ); |
| |
| for( int nY = 0; ( nY < 8 ) && bDither16; nY++ ) |
| for( int nX = 0; ( nX < 8 ) && bDither16; nX++ ) |
| if( ::GetPixel( hMemDC, nX, nY ) != aCol ) |
| bDither16 = FALSE; |
| |
| ::SelectObject( hMemDC, hBrushOld ), ::DeleteObject( hMemBrush ); |
| ::SelectObject( hMemDC, hBmpOld ), ::DeleteObject( hMemBmp ); |
| ::DeleteDC( hMemDC ); |
| |
| if( bDither16 ) |
| { |
| // create DIBPattern for 16Bit dithering |
| long n; |
| |
| pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, sizeof( BITMAPINFOHEADER ) + 192 ); |
| pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); |
| pSalData->mpDitherDiff = new long[ 256 ]; |
| pSalData->mpDitherLow = new BYTE[ 256 ]; |
| pSalData->mpDitherHigh = new BYTE[ 256 ]; |
| pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ); |
| memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); |
| |
| BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; |
| |
| pBIH->biSize = sizeof( BITMAPINFOHEADER ); |
| pBIH->biWidth = 8; |
| pBIH->biHeight = 8; |
| pBIH->biPlanes = 1; |
| pBIH->biBitCount = 24; |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherDiff[ n ] = n - ( n & 248L ); |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherLow[ n ] = (BYTE) ( n & 248 ); |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherHigh[ n ] = (BYTE) Min( pSalData->mpDitherLow[ n ] + 8L, 255L ); |
| } |
| } |
| else if ( (nRasterCaps & RC_PALETTE) && (nBitCount == 8) ) |
| { |
| BYTE nRed, nGreen, nBlue; |
| BYTE nR, nG, nB; |
| PALETTEENTRY* pPalEntry; |
| LOGPALETTE* pLogPal; |
| const sal_uInt16 nDitherPalCount = DITHER_PAL_COUNT; |
| sal_uLong nTotalCount = DITHER_MAX_SYSCOLOR + nDitherPalCount + DITHER_EXTRA_COLORS; |
| |
| // create logical palette |
| pLogPal = (LOGPALETTE*) new char[ sizeof( LOGPALETTE ) + ( nTotalCount * sizeof( PALETTEENTRY ) ) ]; |
| pLogPal->palVersion = 0x0300; |
| pLogPal->palNumEntries = (sal_uInt16) nTotalCount; |
| pPalEntry = pLogPal->palPalEntry; |
| |
| // Standard colors |
| memcpy( pPalEntry, aImplSalSysPalEntryAry, DITHER_MAX_SYSCOLOR * sizeof( PALETTEENTRY ) ); |
| pPalEntry += DITHER_MAX_SYSCOLOR; |
| |
| // own palette (6/6/6) |
| for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA ) |
| { |
| for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA ) |
| { |
| for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA ) |
| { |
| pPalEntry->peRed = nRed; |
| pPalEntry->peGreen = nGreen; |
| pPalEntry->peBlue = nBlue; |
| pPalEntry->peFlags = 0; |
| pPalEntry++; |
| } |
| } |
| } |
| |
| // insert special 'Blue' as standard drawing color |
| *pPalEntry++ = aImplExtraColor1; |
| |
| // create palette |
| pSalData->mhDitherPal = CreatePalette( pLogPal ); |
| delete[] (char*) pLogPal; |
| |
| if( pSalData->mhDitherPal ) |
| { |
| // create DIBPattern for 8Bit dithering |
| long nSize = sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ) + 64; |
| long n; |
| |
| pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, nSize ); |
| pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); |
| pSalData->mpDitherDiff = new long[ 256 ]; |
| pSalData->mpDitherLow = new BYTE[ 256 ]; |
| pSalData->mpDitherHigh = new BYTE[ 256 ]; |
| pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ); |
| memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); |
| |
| BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; |
| short* pColors = (short*) ( pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) ); |
| |
| pBIH->biSize = sizeof( BITMAPINFOHEADER ); |
| pBIH->biWidth = 8; |
| pBIH->biHeight = 8; |
| pBIH->biPlanes = 1; |
| pBIH->biBitCount = 8; |
| |
| for( n = 0; n < nDitherPalCount; n++ ) |
| pColors[ n ] = (short)( n + DITHER_MAX_SYSCOLOR ); |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherDiff[ n ] = n % 51L; |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherLow[ n ] = (BYTE) ( n / 51L ); |
| |
| for( n = 0; n < 256L; n++ ) |
| pSalData->mpDitherHigh[ n ] = (BYTE)Min( pSalData->mpDitherLow[ n ] + 1, 5 ); |
| } |
| |
| // get system color entries |
| ImplUpdateSysColorEntries(); |
| } |
| |
| ReleaseDC( 0, hDC ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplFreeSalGDI() |
| { |
| SalData* pSalData = GetSalData(); |
| |
| // destroy stock objects |
| int i; |
| for ( i = 0; i < pSalData->mnStockPenCount; i++ ) |
| DeletePen( pSalData->mhStockPenAry[i] ); |
| for ( i = 0; i < pSalData->mnStockBrushCount; i++ ) |
| DeleteBrush( pSalData->mhStockBrushAry[i] ); |
| |
| // 50% Brush loeschen |
| if ( pSalData->mh50Brush ) |
| { |
| DeleteBrush( pSalData->mh50Brush ); |
| pSalData->mh50Brush = 0; |
| } |
| |
| // 50% Bitmap loeschen |
| if ( pSalData->mh50Bmp ) |
| { |
| DeleteBitmap( pSalData->mh50Bmp ); |
| pSalData->mh50Bmp = 0; |
| } |
| |
| ImplClearHDCCache( pSalData ); |
| delete[] pSalData->mpHDCCache; |
| |
| // Ditherpalette loeschen, wenn vorhanden |
| if ( pSalData->mhDitherPal ) |
| { |
| DeleteObject( pSalData->mhDitherPal ); |
| pSalData->mhDitherPal = 0; |
| } |
| |
| // delete buffers for dithering DIB patterns, if neccessary |
| if ( pSalData->mhDitherDIB ) |
| { |
| GlobalUnlock( pSalData->mhDitherDIB ); |
| GlobalFree( pSalData->mhDitherDIB ); |
| pSalData->mhDitherDIB = 0; |
| delete[] pSalData->mpDitherDiff; |
| delete[] pSalData->mpDitherLow; |
| delete[] pSalData->mpDitherHigh; |
| } |
| |
| // delete SysColorList |
| SysColorEntry* pEntry = pFirstSysColor; |
| while( pEntry ) |
| { |
| SysColorEntry* pTmp = pEntry->pNext; |
| delete pEntry; |
| pEntry = pTmp; |
| } |
| pFirstSysColor = NULL; |
| |
| // delete icon cache |
| SalIcon* pIcon = pSalData->mpFirstIcon; |
| pSalData->mpFirstIcon = NULL; |
| while( pIcon ) |
| { |
| SalIcon* pTmp = pIcon->pNext; |
| DestroyIcon( pIcon->hIcon ); |
| DestroyIcon( pIcon->hSmallIcon ); |
| delete pIcon; |
| pIcon = pTmp; |
| } |
| |
| // delete temporary font list |
| ImplReleaseTempFonts( *pSalData ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue ) |
| { |
| // dither color? |
| if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) ) |
| return TRUE; |
| |
| PALETTEENTRY* pPalEntry = aImplSalSysPalEntryAry; |
| |
| // standard palette color? |
| for ( sal_uInt16 i = 0; i < DITHER_MAX_SYSCOLOR; i++, pPalEntry++ ) |
| { |
| if( pPalEntry->peRed == nRed && pPalEntry->peGreen == nGreen && pPalEntry->peBlue == nBlue ) |
| return TRUE; |
| } |
| |
| // extra color? |
| if ( aImplExtraColor1.peRed == nRed && |
| aImplExtraColor1.peGreen == nGreen && |
| aImplExtraColor1.peBlue == nBlue ) |
| { |
| return TRUE; |
| } |
| |
| return FALSE; |
| } |
| |
| // ======================================================================= |
| |
| int ImplIsSysColorEntry( SalColor nSalColor ) |
| { |
| SysColorEntry* pEntry = pFirstSysColor; |
| const DWORD nTestRGB = (DWORD)RGB( SALCOLOR_RED( nSalColor ), |
| SALCOLOR_GREEN( nSalColor ), |
| SALCOLOR_BLUE( nSalColor ) ); |
| |
| while ( pEntry ) |
| { |
| if ( pEntry->nRGB == nTestRGB ) |
| return TRUE; |
| pEntry = pEntry->pNext; |
| } |
| |
| return FALSE; |
| } |
| |
| // ======================================================================= |
| |
| static void ImplInsertSysColorEntry( int nSysIndex ) |
| { |
| const DWORD nRGB = GetSysColor( nSysIndex ); |
| |
| if ( !ImplIsPaletteEntry( GetRValue( nRGB ), GetGValue( nRGB ), GetBValue( nRGB ) ) ) |
| { |
| if ( !pFirstSysColor ) |
| { |
| pActSysColor = pFirstSysColor = new SysColorEntry; |
| pFirstSysColor->nRGB = nRGB; |
| pFirstSysColor->pNext = NULL; |
| } |
| else |
| { |
| pActSysColor = pActSysColor->pNext = new SysColorEntry; |
| pActSysColor->nRGB = nRGB; |
| pActSysColor->pNext = NULL; |
| } |
| } |
| } |
| |
| // ======================================================================= |
| |
| void ImplUpdateSysColorEntries() |
| { |
| // delete old SysColorList |
| SysColorEntry* pEntry = pFirstSysColor; |
| while( pEntry ) |
| { |
| SysColorEntry* pTmp = pEntry->pNext; |
| delete pEntry; |
| pEntry = pTmp; |
| } |
| pActSysColor = pFirstSysColor = NULL; |
| |
| // create new sys color list |
| ImplInsertSysColorEntry( COLOR_ACTIVEBORDER ); |
| ImplInsertSysColorEntry( COLOR_INACTIVEBORDER ); |
| if( aSalShlData.mnVersion >= 410 ) |
| { |
| ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION ); |
| ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION ); |
| } |
| ImplInsertSysColorEntry( COLOR_3DFACE ); |
| ImplInsertSysColorEntry( COLOR_3DHILIGHT ); |
| ImplInsertSysColorEntry( COLOR_3DLIGHT ); |
| ImplInsertSysColorEntry( COLOR_3DSHADOW ); |
| ImplInsertSysColorEntry( COLOR_3DDKSHADOW ); |
| ImplInsertSysColorEntry( COLOR_INFOBK ); |
| ImplInsertSysColorEntry( COLOR_INFOTEXT ); |
| ImplInsertSysColorEntry( COLOR_BTNTEXT ); |
| ImplInsertSysColorEntry( COLOR_WINDOW ); |
| ImplInsertSysColorEntry( COLOR_WINDOWTEXT ); |
| ImplInsertSysColorEntry( COLOR_HIGHLIGHT ); |
| ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT ); |
| ImplInsertSysColorEntry( COLOR_MENU ); |
| ImplInsertSysColorEntry( COLOR_MENUTEXT ); |
| ImplInsertSysColorEntry( COLOR_ACTIVECAPTION ); |
| ImplInsertSysColorEntry( COLOR_CAPTIONTEXT ); |
| ImplInsertSysColorEntry( COLOR_INACTIVECAPTION ); |
| ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) |
| { |
| SalColor nSalColor; |
| if ( nROPColor == SAL_ROP_0 ) |
| nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); |
| else |
| nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); |
| return nSalColor; |
| } |
| |
| // ======================================================================= |
| |
| void ImplSalInitGraphics( WinSalGraphics* pData ) |
| { |
| // Beim Printer berechnen wir die minimale Linienstaerke |
| if ( pData->mbPrinter ) |
| { |
| int nDPIX = GetDeviceCaps( pData->getHDC(), LOGPIXELSX ); |
| if ( nDPIX <= 300 ) |
| pData->mnPenWidth = 0; |
| else |
| pData->mnPenWidth = nDPIX/300; |
| } |
| |
| ::SetTextAlign( pData->getHDC(), TA_BASELINE | TA_LEFT | TA_NOUPDATECP ); |
| ::SetBkMode( pData->getHDC(), TRANSPARENT ); |
| ::SetROP2( pData->getHDC(), R2_COPYPEN ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void ImplSalDeInitGraphics( WinSalGraphics* pData ) |
| { |
| // clear clip region |
| SelectClipRgn( pData->getHDC(), 0 ); |
| // select default objects |
| if ( pData->mhDefPen ) |
| SelectPen( pData->getHDC(), pData->mhDefPen ); |
| if ( pData->mhDefBrush ) |
| SelectBrush( pData->getHDC(), pData->mhDefBrush ); |
| if ( pData->mhDefFont ) |
| SelectFont( pData->getHDC(), pData->mhDefFont ); |
| } |
| |
| // ======================================================================= |
| |
| HDC ImplGetCachedDC( sal_uLong nID, HBITMAP hBmp ) |
| { |
| SalData* pSalData = GetSalData(); |
| HDCCache* pC = &pSalData->mpHDCCache[ nID ]; |
| |
| if( !pC->mhDC ) |
| { |
| HDC hDC = GetDC( 0 ); |
| |
| // neuen DC mit DefaultBitmap anlegen |
| pC->mhDC = CreateCompatibleDC( hDC ); |
| |
| if( pSalData->mhDitherPal ) |
| { |
| pC->mhDefPal = SelectPalette( pC->mhDC, pSalData->mhDitherPal, TRUE ); |
| RealizePalette( pC->mhDC ); |
| } |
| |
| pC->mhSelBmp = CreateCompatibleBitmap( hDC, CACHED_HDC_DEFEXT, CACHED_HDC_DEFEXT ); |
| pC->mhDefBmp = (HBITMAP) SelectObject( pC->mhDC, pC->mhSelBmp ); |
| |
| ReleaseDC( 0, hDC ); |
| } |
| |
| if ( hBmp ) |
| SelectObject( pC->mhDC, pC->mhActBmp = hBmp ); |
| else |
| pC->mhActBmp = 0; |
| |
| return pC->mhDC; |
| } |
| |
| // ======================================================================= |
| |
| void ImplReleaseCachedDC( sal_uLong nID ) |
| { |
| SalData* pSalData = GetSalData(); |
| HDCCache* pC = &pSalData->mpHDCCache[ nID ]; |
| |
| if ( pC->mhActBmp ) |
| SelectObject( pC->mhDC, pC->mhSelBmp ); |
| } |
| |
| // ======================================================================= |
| |
| void ImplClearHDCCache( SalData* pData ) |
| { |
| for( sal_uLong i = 0; i < CACHESIZE_HDC; i++ ) |
| { |
| HDCCache* pC = &pData->mpHDCCache[ i ]; |
| |
| if( pC->mhDC ) |
| { |
| SelectObject( pC->mhDC, pC->mhDefBmp ); |
| |
| if( pC->mhDefPal ) |
| SelectPalette( pC->mhDC, pC->mhDefPal, TRUE ); |
| |
| DeleteDC( pC->mhDC ); |
| DeleteObject( pC->mhSelBmp ); |
| } |
| } |
| } |
| |
| // ======================================================================= |
| |
| // #100127# Fill point and flag memory from array of points which |
| // might also contain bezier control points for the PolyDraw() GDI method |
| // Make sure pWinPointAry and pWinFlagAry are big enough |
| void ImplPreparePolyDraw( bool bCloseFigures, |
| sal_uLong nPoly, |
| const sal_uLong* pPoints, |
| const SalPoint* const* pPtAry, |
| const BYTE* const* pFlgAry, |
| POINT* pWinPointAry, |
| BYTE* pWinFlagAry ) |
| { |
| sal_uLong nCurrPoly; |
| for( nCurrPoly=0; nCurrPoly<nPoly; ++nCurrPoly ) |
| { |
| const POINT* pCurrPoint = reinterpret_cast<const POINT*>( *pPtAry++ ); |
| const BYTE* pCurrFlag = *pFlgAry++; |
| const sal_uLong nCurrPoints = *pPoints++; |
| const bool bHaveFlagArray( pCurrFlag ); |
| sal_uLong nCurrPoint; |
| |
| if( nCurrPoints ) |
| { |
| // start figure |
| *pWinPointAry++ = *pCurrPoint++; |
| *pWinFlagAry++ = PT_MOVETO; |
| ++pCurrFlag; |
| |
| for( nCurrPoint=1; nCurrPoint<nCurrPoints; ) |
| { |
| // #102067# Check existence of flag array |
| if( bHaveFlagArray && |
| ( nCurrPoint + 2 ) < nCurrPoints ) |
| { |
| BYTE P4( pCurrFlag[ 2 ] ); |
| |
| if( ( POLY_CONTROL == pCurrFlag[ 0 ] ) && |
| ( POLY_CONTROL == pCurrFlag[ 1 ] ) && |
| ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) ) |
| { |
| // control point one |
| *pWinPointAry++ = *pCurrPoint++; |
| *pWinFlagAry++ = PT_BEZIERTO; |
| |
| // control point two |
| *pWinPointAry++ = *pCurrPoint++; |
| *pWinFlagAry++ = PT_BEZIERTO; |
| |
| // end point |
| *pWinPointAry++ = *pCurrPoint++; |
| *pWinFlagAry++ = PT_BEZIERTO; |
| |
| nCurrPoint += 3; |
| pCurrFlag += 3; |
| continue; |
| } |
| } |
| |
| // regular line point |
| *pWinPointAry++ = *pCurrPoint++; |
| *pWinFlagAry++ = PT_LINETO; |
| ++pCurrFlag; |
| ++nCurrPoint; |
| } |
| |
| // end figure? |
| if( bCloseFigures ) |
| pWinFlagAry[-1] |= PT_CLOSEFIGURE; |
| } |
| } |
| } |
| |
| // ======================================================================= |
| |
| // #100127# draw an array of points which might also contain bezier control points |
| void ImplRenderPath( HDC hdc, sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) |
| { |
| if( nPoints ) |
| { |
| sal_uInt16 i; |
| // TODO: profile whether the following options are faster: |
| // a) look ahead and draw consecutive bezier or line segments by PolyBezierTo/PolyLineTo resp. |
| // b) convert our flag array to window's and use PolyDraw |
| |
| MoveToEx( hdc, pPtAry->mnX, pPtAry->mnY, NULL ); |
| ++pPtAry; ++pFlgAry; |
| |
| for( i=1; i<nPoints; ++i, ++pPtAry, ++pFlgAry ) |
| { |
| if( *pFlgAry != POLY_CONTROL ) |
| { |
| LineTo( hdc, pPtAry->mnX, pPtAry->mnY ); |
| } |
| else if( nPoints - i > 2 ) |
| { |
| PolyBezierTo( hdc, reinterpret_cast<const POINT*>(pPtAry), 3 ); |
| i += 2; pPtAry += 2; pFlgAry += 2; |
| } |
| } |
| } |
| } |
| |
| // ======================================================================= |
| |
| WinSalGraphics::WinSalGraphics() |
| { |
| for( int i = 0; i < MAX_FALLBACK; ++i ) |
| { |
| mhFonts[ i ] = 0; |
| mpWinFontData[ i ] = NULL; |
| mpWinFontEntry[ i ] = NULL; |
| } |
| |
| mfFontScale = 1.0; |
| |
| mhLocalDC = 0; |
| mhPen = 0; |
| mhBrush = 0; |
| mhRegion = 0; |
| mhDefPen = 0; |
| mhDefBrush = 0; |
| mhDefFont = 0; |
| mhDefPal = 0; |
| mpStdClipRgnData = NULL; |
| mpLogFont = NULL; |
| mpFontCharSets = NULL; |
| mpFontAttrCache = NULL; |
| mnFontCharSetCount = 0; |
| mpFontKernPairs = NULL; |
| mnFontKernPairCount = 0; |
| mbFontKernInit = FALSE; |
| mbXORMode = FALSE; |
| mnPenWidth = GSL_PEN_WIDTH; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| WinSalGraphics::~WinSalGraphics() |
| { |
| // free obsolete GDI objekts |
| ReleaseFonts(); |
| |
| if ( mhPen ) |
| { |
| if ( !mbStockPen ) |
| DeletePen( mhPen ); |
| } |
| if ( mhBrush ) |
| { |
| if ( !mbStockBrush ) |
| DeleteBrush( mhBrush ); |
| } |
| |
| if ( mhRegion ) |
| { |
| DeleteRegion( mhRegion ); |
| mhRegion = 0; |
| } |
| |
| // Cache-Daten zerstoeren |
| if ( mpStdClipRgnData ) |
| delete [] mpStdClipRgnData; |
| |
| if ( mpLogFont ) |
| delete mpLogFont; |
| |
| if ( mpFontCharSets ) |
| delete mpFontCharSets; |
| |
| if ( mpFontKernPairs ) |
| delete mpFontKernPairs; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) |
| { |
| rDPIX = GetDeviceCaps( getHDC(), LOGPIXELSX ); |
| rDPIY = GetDeviceCaps( getHDC(), LOGPIXELSY ); |
| |
| // #111139# this fixes the symptom of div by zero on startup |
| // however, printing will fail most likely as communication with |
| // the printer seems not to work in this case |
| if( !rDPIX || !rDPIY ) |
| rDPIX = rDPIY = 600; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_uInt16 WinSalGraphics::GetBitCount() |
| { |
| return (sal_uInt16)GetDeviceCaps( getHDC(), BITSPIXEL ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| long WinSalGraphics::GetGraphicsWidth() const |
| { |
| if( mhWnd && IsWindow( mhWnd ) ) |
| { |
| WinSalFrame* pFrame = GetWindowPtr( mhWnd ); |
| if( pFrame ) |
| { |
| if( pFrame->maGeometry.nWidth ) |
| return pFrame->maGeometry.nWidth; |
| else |
| { |
| // TODO: perhaps not needed, maGeometry should always be up-to-date |
| RECT aRect; |
| GetClientRect( mhWnd, &aRect ); |
| return aRect.right; |
| } |
| } |
| } |
| |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::ResetClipRegion() |
| { |
| if ( mhRegion ) |
| { |
| DeleteRegion( mhRegion ); |
| mhRegion = 0; |
| } |
| |
| SelectClipRgn( getHDC(), 0 ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| bool WinSalGraphics::setClipRegion( const Region& i_rClip ) |
| { |
| if ( mhRegion ) |
| { |
| DeleteRegion( mhRegion ); |
| mhRegion = 0; |
| } |
| |
| bool bUsePolygon(i_rClip.HasPolyPolygonOrB2DPolyPolygon()); |
| static bool bTryToAvoidPolygon(true); |
| |
| // #122149# try to avoid usage of PolyPolygon ClipRegions when PolyPolygon is no curve |
| // and only contains horizontal/vertical edges. In that case, use the fallback |
| // in GetRegionRectangles which will use Region::GetAsRegionBand() which will do |
| // the correct polygon-to-RegionBand transformation. |
| // Background is that when using the same Rectangle as rectangle or as Polygon |
| // clip region will lead to different results; the polygon-based one will be |
| // one pixel less to the right and down (see GDI docu for CreatePolygonRgn). This |
| // again is because of the polygon-nature and it's classic handling when filling. |
| // This also means that all cases which use a 'true' polygon-based incarnation of |
| // a Region should know what they do - it may lead to repaint errors. |
| if(bUsePolygon && bTryToAvoidPolygon) |
| { |
| const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() ); |
| |
| if(!aPolyPolygon.areControlPointsUsed()) |
| { |
| if(basegfx::tools::containsOnlyHorizontalAndVerticalEdges(aPolyPolygon)) |
| { |
| bUsePolygon = false; |
| } |
| } |
| } |
| |
| if(bUsePolygon) |
| { |
| // #122149# check the comment above to know that this may lead to potentioal repaint |
| // problems. It may be solved (if needed) by scaling the polygon by one in X |
| // and Y. Currently the workaround to only use it if really unavoidable will |
| // solve most cases. When someone is really using polygon-based Regions he |
| // should know what he is doing. |
| // Added code to do that scaling to check if it works, testing it. |
| const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() ); |
| const sal_uInt32 nCount(aPolyPolygon.count()); |
| |
| if( nCount ) |
| { |
| std::vector< POINT > aPolyPoints; |
| aPolyPoints.reserve( 1024 ); |
| std::vector< INT > aPolyCounts( nCount, 0 ); |
| basegfx::B2DHomMatrix aExpand; |
| static bool bExpandByOneInXandY(true); |
| |
| if(bExpandByOneInXandY) |
| { |
| const basegfx::B2DRange aRangeS(aPolyPolygon.getB2DRange()); |
| const basegfx::B2DRange aRangeT(aRangeS.getMinimum(), aRangeS.getMaximum() + basegfx::B2DTuple(1.0, 1.0)); |
| aExpand = basegfx::B2DHomMatrix(basegfx::tools::createSourceRangeTargetRangeTransform(aRangeS, aRangeT)); |
| } |
| |
| for(sal_uInt32 a(0); a < nCount; a++) |
| { |
| const basegfx::B2DPolygon aPoly( |
| basegfx::tools::adaptiveSubdivideByDistance( |
| aPolyPolygon.getB2DPolygon(a), |
| 1)); |
| const sal_uInt32 nPoints(aPoly.count()); |
| aPolyCounts[a] = nPoints; |
| |
| for( sal_uInt32 b = 0; b < nPoints; b++ ) |
| { |
| basegfx::B2DPoint aPt(aPoly.getB2DPoint(b)); |
| |
| if(bExpandByOneInXandY) |
| { |
| aPt = aExpand * aPt; |
| } |
| |
| POINT aPOINT; |
| // #122149# do correct rounding |
| aPOINT.x = basegfx::fround(aPt.getX()); |
| aPOINT.y = basegfx::fround(aPt.getY()); |
| aPolyPoints.push_back( aPOINT ); |
| } |
| } |
| |
| mhRegion = CreatePolyPolygonRgn( &aPolyPoints[0], &aPolyCounts[0], nCount, ALTERNATE ); |
| } |
| } |
| else |
| { |
| RectangleVector aRectangles; |
| i_rClip.GetRegionRectangles(aRectangles); |
| |
| //ULONG nRectCount = i_rClip.GetRectCount(); |
| ULONG nRectBufSize = sizeof(RECT)*aRectangles.size(); |
| if ( aRectangles.size() < SAL_CLIPRECT_COUNT ) |
| { |
| if ( !mpStdClipRgnData ) |
| mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))]; |
| mpClipRgnData = mpStdClipRgnData; |
| } |
| else |
| mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize]; |
| mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); |
| mpClipRgnData->rdh.iType = RDH_RECTANGLES; |
| mpClipRgnData->rdh.nCount = aRectangles.size(); |
| mpClipRgnData->rdh.nRgnSize = nRectBufSize; |
| RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound); |
| SetRectEmpty( pBoundRect ); |
| RECT* pNextClipRect = (RECT*)(&(mpClipRgnData->Buffer)); |
| bool bFirstClipRect = true; |
| |
| for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) |
| { |
| const long nW(aRectIter->GetWidth()); |
| const long nH(aRectIter->GetHeight()); |
| |
| if(nW && nH) |
| { |
| const long nRight(aRectIter->Left() + nW); |
| const long nBottom(aRectIter->Top() + nH); |
| |
| if(bFirstClipRect) |
| { |
| pBoundRect->left = aRectIter->Left(); |
| pBoundRect->top = aRectIter->Top(); |
| pBoundRect->right = nRight; |
| pBoundRect->bottom = nBottom; |
| bFirstClipRect = false; |
| } |
| else |
| { |
| if(aRectIter->Left() < pBoundRect->left) |
| { |
| pBoundRect->left = (int)aRectIter->Left(); |
| } |
| |
| if(aRectIter->Top() < pBoundRect->top) |
| { |
| pBoundRect->top = (int)aRectIter->Top(); |
| } |
| |
| if(nRight > pBoundRect->right) |
| { |
| pBoundRect->right = (int)nRight; |
| } |
| |
| if(nBottom > pBoundRect->bottom) |
| { |
| pBoundRect->bottom = (int)nBottom; |
| } |
| } |
| |
| pNextClipRect->left = (int)aRectIter->Left(); |
| pNextClipRect->top = (int)aRectIter->Top(); |
| pNextClipRect->right = (int)nRight; |
| pNextClipRect->bottom = (int)nBottom; |
| pNextClipRect++; |
| } |
| else |
| { |
| mpClipRgnData->rdh.nCount--; |
| mpClipRgnData->rdh.nRgnSize -= sizeof( RECT ); |
| } |
| } |
| |
| // create clip region from ClipRgnData |
| if(0 == mpClipRgnData->rdh.nCount) |
| { |
| // #123585# region is empty; this may happen when e.g. a PolyPolygon is given |
| // that contains no polygons or only empty ones (no width/height). This is |
| // perfectly fine and we are done, except setting it (see end of method) |
| } |
| else if(1 == mpClipRgnData->rdh.nCount) |
| { |
| RECT* pRect = &(mpClipRgnData->rdh.rcBound); |
| mhRegion = CreateRectRgn( pRect->left, pRect->top, |
| pRect->right, pRect->bottom ); |
| } |
| else if(mpClipRgnData->rdh.nCount > 1) |
| { |
| ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); |
| mhRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData ); |
| |
| // if ExtCreateRegion(...) is not supported |
| if( !mhRegion ) |
| { |
| RGNDATAHEADER* pHeader = (RGNDATAHEADER*) mpClipRgnData; |
| |
| if( pHeader->nCount ) |
| { |
| RECT* pRect = (RECT*) mpClipRgnData->Buffer; |
| mhRegion = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); |
| pRect++; |
| |
| for( ULONG n = 1; n < pHeader->nCount; n++, pRect++ ) |
| { |
| HRGN hRgn = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); |
| CombineRgn( mhRegion, mhRegion, hRgn, RGN_OR ); |
| DeleteRegion( hRgn ); |
| } |
| } |
| } |
| |
| if ( mpClipRgnData != mpStdClipRgnData ) |
| delete [] mpClipRgnData; |
| } |
| } |
| |
| if( mhRegion ) |
| { |
| SelectClipRgn( getHDC(), mhRegion ); |
| |
| // debug code if you weant to check range of the newly applied ClipRegion |
| //RECT aBound; |
| //const int aRegionType = GetRgnBox(mhRegion, &aBound); |
| // |
| //bool bBla = true; |
| } |
| else |
| { |
| // #123585# See above, this is a valid case, execute it |
| SelectClipRgn( getHDC(), 0 ); |
| } |
| |
| // #123585# retval no longer dependent of mhRegion, see TaskId comments above |
| return true; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetLineColor() |
| { |
| // create and select new pen |
| HPEN hNewPen = GetStockPen( NULL_PEN ); |
| HPEN hOldPen = SelectPen( getHDC(), hNewPen ); |
| |
| // destory or save old pen |
| if ( mhPen ) |
| { |
| if ( !mbStockPen ) |
| DeletePen( mhPen ); |
| } |
| else |
| mhDefPen = hOldPen; |
| |
| // set new data |
| mhPen = hNewPen; |
| mbPen = FALSE; |
| mbStockPen = TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetLineColor( SalColor nSalColor ) |
| { |
| maLineColor = nSalColor; |
| COLORREF nPenColor = PALETTERGB( SALCOLOR_RED( nSalColor ), |
| SALCOLOR_GREEN( nSalColor ), |
| SALCOLOR_BLUE( nSalColor ) ); |
| HPEN hNewPen = 0; |
| sal_Bool bStockPen = FALSE; |
| |
| // search for stock pen (only screen, because printer have problems, |
| // when we use stock objects) |
| if ( !mbPrinter ) |
| { |
| SalData* pSalData = GetSalData(); |
| for ( sal_uInt16 i = 0; i < pSalData->mnStockPenCount; i++ ) |
| { |
| if ( nPenColor == pSalData->maStockPenColorAry[i] ) |
| { |
| hNewPen = pSalData->mhStockPenAry[i]; |
| bStockPen = TRUE; |
| break; |
| } |
| } |
| } |
| |
| // create new pen |
| if ( !hNewPen ) |
| { |
| if ( !mbPrinter ) |
| { |
| if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) ) |
| nPenColor = PALRGB_TO_RGB( nPenColor ); |
| } |
| |
| hNewPen = CreatePen( PS_SOLID, mnPenWidth, nPenColor ); |
| bStockPen = FALSE; |
| } |
| |
| // select new pen |
| HPEN hOldPen = SelectPen( getHDC(), hNewPen ); |
| |
| // destory or save old pen |
| if ( mhPen ) |
| { |
| if ( !mbStockPen ) |
| DeletePen( mhPen ); |
| } |
| else |
| mhDefPen = hOldPen; |
| |
| // set new data |
| mnPenColor = nPenColor; |
| mhPen = hNewPen; |
| mbPen = TRUE; |
| mbStockPen = bStockPen; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetFillColor() |
| { |
| // create and select new brush |
| HBRUSH hNewBrush = GetStockBrush( NULL_BRUSH ); |
| HBRUSH hOldBrush = SelectBrush( getHDC(), hNewBrush ); |
| |
| // destory or save old brush |
| if ( mhBrush ) |
| { |
| if ( !mbStockBrush ) |
| DeleteBrush( mhBrush ); |
| } |
| else |
| mhDefBrush = hOldBrush; |
| |
| // set new data |
| mhBrush = hNewBrush; |
| mbBrush = FALSE; |
| mbStockBrush = TRUE; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetFillColor( SalColor nSalColor ) |
| { |
| maFillColor = nSalColor; |
| SalData* pSalData = GetSalData(); |
| BYTE nRed = SALCOLOR_RED( nSalColor ); |
| BYTE nGreen = SALCOLOR_GREEN( nSalColor ); |
| BYTE nBlue = SALCOLOR_BLUE( nSalColor ); |
| COLORREF nBrushColor = PALETTERGB( nRed, nGreen, nBlue ); |
| HBRUSH hNewBrush = 0; |
| sal_Bool bStockBrush = FALSE; |
| |
| // search for stock brush (only screen, because printer have problems, |
| // when we use stock objects) |
| if ( !mbPrinter ) |
| { |
| for ( sal_uInt16 i = 0; i < pSalData->mnStockBrushCount; i++ ) |
| { |
| if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] ) |
| { |
| hNewBrush = pSalData->mhStockBrushAry[i]; |
| bStockBrush = TRUE; |
| break; |
| } |
| } |
| } |
| |
| // create new brush |
| if ( !hNewBrush ) |
| { |
| if ( mbPrinter || !pSalData->mhDitherDIB ) |
| hNewBrush = CreateSolidBrush( nBrushColor ); |
| else |
| { |
| if ( 24 == ((BITMAPINFOHEADER*)pSalData->mpDitherDIB)->biBitCount ) |
| { |
| BYTE* pTmp = pSalData->mpDitherDIBData; |
| long* pDitherDiff = pSalData->mpDitherDiff; |
| BYTE* pDitherLow = pSalData->mpDitherLow; |
| BYTE* pDitherHigh = pSalData->mpDitherHigh; |
| |
| for( long nY = 0L; nY < 8L; nY++ ) |
| { |
| for( long nX = 0L; nX < 8L; nX++ ) |
| { |
| const long nThres = aOrdDither16Bit[ nY ][ nX ]; |
| *pTmp++ = DMAP( nBlue, nThres ); |
| *pTmp++ = DMAP( nGreen, nThres ); |
| *pTmp++ = DMAP( nRed, nThres ); |
| } |
| } |
| |
| hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_RGB_COLORS ); |
| } |
| else if ( ImplIsSysColorEntry( nSalColor ) ) |
| { |
| nBrushColor = PALRGB_TO_RGB( nBrushColor ); |
| hNewBrush = CreateSolidBrush( nBrushColor ); |
| } |
| else if ( ImplIsPaletteEntry( nRed, nGreen, nBlue ) ) |
| hNewBrush = CreateSolidBrush( nBrushColor ); |
| else |
| { |
| BYTE* pTmp = pSalData->mpDitherDIBData; |
| long* pDitherDiff = pSalData->mpDitherDiff; |
| BYTE* pDitherLow = pSalData->mpDitherLow; |
| BYTE* pDitherHigh = pSalData->mpDitherHigh; |
| |
| for ( long nY = 0L; nY < 8L; nY++ ) |
| { |
| for ( long nX = 0L; nX < 8L; nX++ ) |
| { |
| const long nThres = aOrdDither8Bit[ nY ][ nX ]; |
| *pTmp = DMAP( nRed, nThres ) + DMAP( nGreen, nThres ) * 6 + DMAP( nBlue, nThres ) * 36; |
| pTmp++; |
| } |
| } |
| |
| hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS ); |
| } |
| } |
| |
| bStockBrush = FALSE; |
| } |
| |
| // select new brush |
| HBRUSH hOldBrush = SelectBrush( getHDC(), hNewBrush ); |
| |
| // destory or save old brush |
| if ( mhBrush ) |
| { |
| if ( !mbStockBrush ) |
| DeleteBrush( mhBrush ); |
| } |
| else |
| mhDefBrush = hOldBrush; |
| |
| // set new data |
| mnBrushColor = nBrushColor; |
| mhBrush = hNewBrush; |
| mbBrush = TRUE; |
| mbStockBrush = bStockBrush; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetXORMode( bool bSet, bool ) |
| { |
| mbXORMode = bSet; |
| ::SetROP2( getHDC(), bSet ? R2_XORPEN : R2_COPYPEN ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor ) |
| { |
| SetLineColor( ImplGetROPSalColor( nROPColor ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor ) |
| { |
| SetFillColor( ImplGetROPSalColor( nROPColor ) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawPixel( long nX, long nY ) |
| { |
| if ( mbXORMode ) |
| { |
| HBRUSH hBrush = CreateSolidBrush( mnPenColor ); |
| HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); |
| PatBlt( getHDC(), (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); |
| SelectBrush( getHDC(), hOldBrush ); |
| DeleteBrush( hBrush ); |
| } |
| else |
| SetPixel( getHDC(), (int)nX, (int)nY, mnPenColor ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) |
| { |
| COLORREF nCol = PALETTERGB( SALCOLOR_RED( nSalColor ), |
| SALCOLOR_GREEN( nSalColor ), |
| SALCOLOR_BLUE( nSalColor ) ); |
| |
| if ( !mbPrinter && |
| GetSalData()->mhDitherPal && |
| ImplIsSysColorEntry( nSalColor ) ) |
| nCol = PALRGB_TO_RGB( nCol ); |
| |
| if ( mbXORMode ) |
| { |
| HBRUSH hBrush = CreateSolidBrush( nCol ); |
| HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); |
| PatBlt( getHDC(), (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); |
| SelectBrush( getHDC(), hOldBrush ); |
| DeleteBrush( hBrush ); |
| } |
| else |
| ::SetPixel( getHDC(), (int)nX, (int)nY, nCol ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) |
| { |
| MoveToEx( getHDC(), (int)nX1, (int)nY1, NULL ); |
| |
| // we must paint the endpoint |
| int bPaintEnd = TRUE; |
| if ( nX1 == nX2 ) |
| { |
| bPaintEnd = FALSE; |
| if ( nY1 <= nY2 ) |
| nY2++; |
| else |
| nY2--; |
| } |
| if ( nY1 == nY2 ) |
| { |
| bPaintEnd = FALSE; |
| if ( nX1 <= nX2 ) |
| nX2++; |
| else |
| nX2--; |
| } |
| |
| LineTo( getHDC(), (int)nX2, (int)nY2 ); |
| |
| if ( bPaintEnd && !mbPrinter ) |
| { |
| if ( mbXORMode ) |
| { |
| HBRUSH hBrush = CreateSolidBrush( mnPenColor ); |
| HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); |
| PatBlt( getHDC(), (int)nX2, (int)nY2, (int)1, (int)1, PATINVERT ); |
| SelectBrush( getHDC(), hOldBrush ); |
| DeleteBrush( hBrush ); |
| } |
| else |
| SetPixel( getHDC(), (int)nX2, (int)nY2, mnPenColor ); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) |
| { |
| if ( !mbPen ) |
| { |
| if ( !mbPrinter ) |
| { |
| PatBlt( getHDC(), (int)nX, (int)nY, (int)nWidth, (int)nHeight, |
| mbXORMode ? PATINVERT : PATCOPY ); |
| } |
| else |
| { |
| RECT aWinRect; |
| aWinRect.left = nX; |
| aWinRect.top = nY; |
| aWinRect.right = nX+nWidth; |
| aWinRect.bottom = nY+nHeight; |
| ::FillRect( getHDC(), &aWinRect, mhBrush ); |
| } |
| } |
| else |
| WIN_Rectangle( getHDC(), (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry ) |
| { |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" ); |
| |
| POINT* pWinPtAry = (POINT*)pPtAry; |
| // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl |
| // von Punkten |
| if ( !Polyline( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) |
| Polyline( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ) |
| { |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolygon(): POINT != SalPoint" ); |
| |
| POINT* pWinPtAry = (POINT*)pPtAry; |
| // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl |
| // von Punkten |
| if ( !WIN_Polygon( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) |
| WIN_Polygon( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, |
| PCONSTSALPOINT* pPtAry ) |
| { |
| UINT aWinPointAry[SAL_POLYPOLYCOUNT_STACKBUF]; |
| UINT* pWinPointAry; |
| UINT nPolyPolyPoints = 0; |
| UINT nPoints; |
| UINT i; |
| |
| if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF ) |
| pWinPointAry = aWinPointAry; |
| else |
| pWinPointAry = new UINT[nPoly]; |
| |
| for ( i = 0; i < (UINT)nPoly; i++ ) |
| { |
| nPoints = (UINT)pPoints[i]+1; |
| pWinPointAry[i] = nPoints; |
| nPolyPolyPoints += nPoints; |
| } |
| |
| POINT aWinPointAryAry[SAL_POLYPOLYPOINTS_STACKBUF]; |
| POINT* pWinPointAryAry; |
| if ( nPolyPolyPoints <= SAL_POLYPOLYPOINTS_STACKBUF ) |
| pWinPointAryAry = aWinPointAryAry; |
| else |
| pWinPointAryAry = new POINT[nPolyPolyPoints]; |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" ); |
| const SalPoint* pPolyAry; |
| UINT n = 0; |
| for ( i = 0; i < (UINT)nPoly; i++ ) |
| { |
| nPoints = pWinPointAry[i]; |
| pPolyAry = pPtAry[i]; |
| memcpy( pWinPointAryAry+n, pPolyAry, (nPoints-1)*sizeof(POINT) ); |
| pWinPointAryAry[n+nPoints-1] = pWinPointAryAry[n]; |
| n += nPoints; |
| } |
| |
| if ( !WIN_PolyPolygon( getHDC(), pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) && |
| (nPolyPolyPoints > MAX_64KSALPOINTS) ) |
| { |
| nPolyPolyPoints = 0; |
| nPoly = 0; |
| do |
| { |
| nPolyPolyPoints += pWinPointAry[(UINT)nPoly]; |
| nPoly++; |
| } |
| while ( nPolyPolyPoints < MAX_64KSALPOINTS ); |
| nPoly--; |
| if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS ) |
| pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS; |
| if ( nPoly == 1 ) |
| WIN_Polygon( getHDC(), pWinPointAryAry, *pWinPointAry ); |
| else |
| WIN_PolyPolygon( getHDC(), pWinPointAryAry, (int*)pWinPointAry, nPoly ); |
| } |
| |
| if ( pWinPointAry != aWinPointAry ) |
| delete [] pWinPointAry; |
| if ( pWinPointAryAry != aWinPointAryAry ) |
| delete [] pWinPointAryAry; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| #define SAL_POLY_STACKBUF 32 |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalGraphics::drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) |
| { |
| #ifdef USE_GDI_BEZIERS |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" ); |
| |
| ImplRenderPath( getHDC(), nPoints, pPtAry, pFlgAry ); |
| |
| return sal_True; |
| #else |
| return sal_False; |
| #endif |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalGraphics::drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) |
| { |
| #ifdef USE_GDI_BEZIERS |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" ); |
| |
| POINT aStackAry1[SAL_POLY_STACKBUF]; |
| BYTE aStackAry2[SAL_POLY_STACKBUF]; |
| POINT* pWinPointAry; |
| BYTE* pWinFlagAry; |
| if( nPoints > SAL_POLY_STACKBUF ) |
| { |
| pWinPointAry = new POINT[ nPoints ]; |
| pWinFlagAry = new BYTE[ nPoints ]; |
| } |
| else |
| { |
| pWinPointAry = aStackAry1; |
| pWinFlagAry = aStackAry2; |
| } |
| |
| ImplPreparePolyDraw(true, 1, &nPoints, &pPtAry, &pFlgAry, pWinPointAry, pWinFlagAry); |
| |
| sal_Bool bRet( sal_False ); |
| |
| if( BeginPath( getHDC() ) ) |
| { |
| PolyDraw(getHDC(), pWinPointAry, pWinFlagAry, nPoints); |
| |
| if( EndPath( getHDC() ) ) |
| { |
| if( StrokeAndFillPath( getHDC() ) ) |
| bRet = sal_True; |
| } |
| } |
| |
| if( pWinPointAry != aStackAry1 ) |
| { |
| delete [] pWinPointAry; |
| delete [] pWinFlagAry; |
| } |
| |
| return bRet; |
| #else |
| return sal_False; |
| #endif |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, |
| const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ) |
| { |
| #ifdef USE_GDI_BEZIERS |
| // Unter NT koennen wir das Array direkt weiterreichen |
| DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), |
| "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" ); |
| |
| sal_uLong nCurrPoly, nTotalPoints; |
| const sal_uLong* pCurrPoints = pPoints; |
| for( nCurrPoly=0, nTotalPoints=0; nCurrPoly<nPoly; ++nCurrPoly ) |
| nTotalPoints += *pCurrPoints++; |
| |
| POINT aStackAry1[SAL_POLY_STACKBUF]; |
| BYTE aStackAry2[SAL_POLY_STACKBUF]; |
| POINT* pWinPointAry; |
| BYTE* pWinFlagAry; |
| if( nTotalPoints > SAL_POLY_STACKBUF ) |
| { |
| pWinPointAry = new POINT[ nTotalPoints ]; |
| pWinFlagAry = new BYTE[ nTotalPoints ]; |
| } |
| else |
| { |
| pWinPointAry = aStackAry1; |
| pWinFlagAry = aStackAry2; |
| } |
| |
| ImplPreparePolyDraw(true, nPoly, pPoints, pPtAry, pFlgAry, pWinPointAry, pWinFlagAry); |
| |
| sal_Bool bRet( sal_False ); |
| |
| if( BeginPath( getHDC() ) ) |
| { |
| PolyDraw(getHDC(), pWinPointAry, pWinFlagAry, nTotalPoints); |
| |
| if( EndPath( getHDC() ) ) |
| { |
| if( StrokeAndFillPath( getHDC() ) ) |
| bRet = sal_True; |
| } |
| } |
| |
| if( pWinPointAry != aStackAry1 ) |
| { |
| delete [] pWinPointAry; |
| delete [] pWinFlagAry; |
| } |
| |
| return bRet; |
| #else |
| return sal_False; |
| #endif |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF |
| #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox |
| // in the first 4096 bytes |
| |
| static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, sal_uLong nComp, sal_uLong nSize ) |
| { |
| while ( nComp-- >= nSize ) |
| { |
| sal_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 sal_Bool ImplGetBoundingBox( double* nNumb, BYTE* pSource, sal_uLong nSize ) |
| { |
| sal_Bool bRetValue = FALSE; |
| BYTE* pDest = ImplSearchEntry( pSource, (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 bytes following the bounding box will be checked |
| |
| int i; |
| for ( i = 0; ( i < 4 ) && nSizeLeft; i++ ) |
| { |
| int nDivision = 1; |
| sal_Bool bDivision = FALSE; |
| sal_Bool bNegative = FALSE; |
| sal_Bool bValid = TRUE; |
| |
| while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; |
| BYTE nByte = *pDest; |
| while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) |
| { |
| switch ( nByte ) |
| { |
| case '.' : |
| if ( bDivision ) |
| bValid = FALSE; |
| else |
| bDivision = TRUE; |
| break; |
| case '-' : |
| bNegative = TRUE; |
| break; |
| default : |
| if ( ( nByte < '0' ) || ( nByte > '9' ) ) |
| nSizeLeft = 1; // error parsing the bounding box values |
| else if ( bValid ) |
| { |
| if ( bDivision ) |
| nDivision*=10; |
| nNumb[i] *= 10; |
| nNumb[i] += nByte - '0'; |
| } |
| break; |
| } |
| nSizeLeft--; |
| nByte = *(++pDest); |
| } |
| if ( bNegative ) |
| nNumb[i] = -nNumb[i]; |
| if ( bDivision && ( nDivision != 1 ) ) |
| nNumb[i] /= nDivision; |
| } |
| if ( i == 4 ) |
| bRetValue = TRUE; |
| } |
| return bRetValue; |
| } |
| |
| sal_Bool WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ) |
| { |
| sal_Bool bRetValue = FALSE; |
| |
| if ( mbPrinter ) |
| { |
| int nEscape = POSTSCRIPT_PASSTHROUGH; |
| |
| if ( Escape( getHDC(), QUERYESCSUPPORT, sizeof( int ), ( LPSTR )&nEscape, 0 ) ) |
| { |
| double nBoundingBox[4]; |
| |
| if ( ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) |
| { |
| OStringBuffer aBuf( POSTSCRIPT_BUFSIZE ); |
| |
| // reserve place for a sal_uInt16 |
| 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" ); |
| |
| |
| // #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" ); |
| } |
| |
| // #107797# Write out buffer |
| // ---------------------------------------------------------------------------------- |
| *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); |
| Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); |
| |
| |
| // #107797# Write out EPS transformation code |
| // ---------------------------------------------------------------------------------- |
| double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); |
| double dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] ); |
| // reserve a sal_uInt16 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" ); |
| *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); |
| Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); |
| |
| |
| // #107797# Write out actual EPS content |
| // ---------------------------------------------------------------------------------- |
| sal_uLong nToDo = nSize; |
| sal_uLong nDoNow; |
| while ( nToDo ) |
| { |
| nDoNow = nToDo; |
| if ( nToDo > POSTSCRIPT_BUFSIZE - 2 ) |
| nDoNow = POSTSCRIPT_BUFSIZE - 2; |
| // the following is based on the string buffer allocation |
| // of size POSTSCRIPT_BUFSIZE at construction time of aBuf |
| *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)nDoNow; |
| memcpy( (void*)(aBuf.getStr() + 2), (BYTE*)pPtr + nSize - nToDo, nDoNow ); |
| sal_uLong nResult = Escape ( getHDC(), nEscape, nDoNow + 2, (LPTSTR)aBuf.getStr(), 0 ); |
| if (!nResult ) |
| break; |
| nToDo -= nResult; |
| } |
| |
| |
| // #107797# Write out EPS encapsulation footer |
| // ---------------------------------------------------------------------------------- |
| // reserve a sal_uInt16 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" ); |
| *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); |
| Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); |
| bRetValue = TRUE; |
| } |
| } |
| } |
| |
| return bRetValue; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| SystemGraphicsData WinSalGraphics::GetGraphicsData() const |
| { |
| SystemGraphicsData aRes; |
| aRes.nSize = sizeof(aRes); |
| aRes.hDC = const_cast< WinSalGraphics* >(this)->getHDC(); |
| return aRes; |
| } |
| |
| // ----------------------------------------------------------------------- |