mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-04-07 13:55:33 +08:00
2807 lines
75 KiB
C++
2807 lines
75 KiB
C++
#include "stdafx.h"
|
|
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "File.h"
|
|
#include "GlobalParams.h"
|
|
#include "Error.h"
|
|
#include "Object.h"
|
|
#include "GFont.h"
|
|
#include "Link.h"
|
|
#include "CharCodeToUnicode.h"
|
|
#include "EncodingTables.h"
|
|
#include "FontFileTrueType.h"
|
|
#include "SBitmap.h"
|
|
#include "SGlyphBitmap.h"
|
|
#include "SPattern.h"
|
|
#include "SScreen.h"
|
|
#include "SPath.h"
|
|
#include "SState.h"
|
|
#include "SErrorCodes.h"
|
|
#include "SFontEngine.h"
|
|
#include "SFont.h"
|
|
#include "SFontFile.h"
|
|
#include "SFontFileID.h"
|
|
#include "SImage.h"
|
|
#include "ImageOutputDev.h"
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Äåëèì 16-áèòíîå çíà÷åíèå [0, 255*255] íà 255, âîçâðàùàåì 8-áèòíîå çíà÷åíèå.
|
|
static inline unsigned char Div255(int nValue)
|
|
{
|
|
return (unsigned char)( ( nValue + ( nValue >> 8 ) + 0x80 ) >> 8 );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Blend functions
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
static void RGBToHSV(unsigned char unR, unsigned char unG, unsigned char unB, int *pnH, int *pnS, int *pnV)
|
|
{
|
|
int nCmax, nCmid, nCmin, nValue;
|
|
|
|
if ( unR >= unG )
|
|
{
|
|
if ( unG >= unB ) { nValue = 0; nCmax = unR; nCmid = unG; nCmin = unB; }
|
|
else if ( unB >= unR ) { nValue = 4; nCmax = unB; nCmid = unR; nCmin = unG; }
|
|
else { nValue = 5; nCmax = unR; nCmid = unB; nCmin = unG; }
|
|
}
|
|
else
|
|
{
|
|
if ( unR >= unB ) { nValue = 1; nCmax = unG; nCmid = unR; nCmin = unB; }
|
|
else if ( unG >= unB ) { nValue = 2; nCmax = unG; nCmid = unB; nCmin = unR; }
|
|
else { nValue = 3; nCmax = unB; nCmid = unG; nCmin = unR; }
|
|
}
|
|
if ( nCmax == nCmin )
|
|
{
|
|
*pnH = *pnS = 0;
|
|
}
|
|
else
|
|
{
|
|
*pnH = nValue * 60;
|
|
if ( nValue & 1 )
|
|
{
|
|
*pnH += ( ( nCmax - nCmid ) * 60 ) / ( nCmax - nCmin );
|
|
}
|
|
else
|
|
{
|
|
*pnH += ( ( nCmid - nCmin ) * 60 ) / ( nCmax - nCmin );
|
|
}
|
|
*pnS = ( 255 * ( nCmax - nCmin ) ) / nCmax;
|
|
}
|
|
*pnV = nCmax;
|
|
}
|
|
|
|
static void HSVToRGB(int nH, int nS, int nV, unsigned char *punR, unsigned char *punG, unsigned char *punB)
|
|
{
|
|
if ( nS == 0 )
|
|
{
|
|
*punR = *punG = *punB = nV;
|
|
}
|
|
else
|
|
{
|
|
int nInt = nH / 60;
|
|
int nFloat = nH % 60;
|
|
int nCmax = nV, nCmid;
|
|
if ( nInt & 1 )
|
|
{
|
|
nCmid = Div255( nV * 255 - ( ( nS * nFloat ) / 60 ) );
|
|
}
|
|
else
|
|
{
|
|
nCmid = Div255( nV * ( 255 - ( ( nS * ( 60 - nFloat ) ) / 60 ) ) );
|
|
}
|
|
int nCmin = Div255( nV * ( 255 - nS ) );
|
|
switch (nInt)
|
|
{
|
|
case 0: *punR = nCmax; *punG = nCmid; *punB = nCmin; break;
|
|
case 1: *punG = nCmax; *punR = nCmid; *punB = nCmin; break;
|
|
case 2: *punG = nCmax; *punB = nCmid; *punR = nCmin; break;
|
|
case 3: *punB = nCmax; *punG = nCmid; *punR = nCmin; break;
|
|
case 4: *punB = nCmax; *punR = nCmid; *punG = nCmin; break;
|
|
case 5: *punR = nCmax; *punB = nCmid; *punG = nCmin; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void BlendMultiply (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = ( pDst[nIndex] * pSrc[nIndex] ) / 255;
|
|
}
|
|
}
|
|
|
|
static void BlendScreen (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] + pSrc[nIndex] - ( pDst[nIndex] * pSrc[nIndex] ) / 255;
|
|
}
|
|
}
|
|
|
|
static void BlendOverlay (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] < 0x80 ? ( pSrc[nIndex] * 2 * pDst[nIndex] ) / 255 : 255 - 2 * ( ( 255 - pSrc[nIndex] ) * ( 255 - pDst[nIndex] ) ) / 255;
|
|
}
|
|
}
|
|
|
|
static void BlendDarken (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] < pSrc[nIndex] ? pDst[nIndex] : pSrc[nIndex];
|
|
}
|
|
}
|
|
|
|
static void BlendLighten (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] > pSrc[nIndex] ? pDst[nIndex] : pSrc[nIndex];
|
|
}
|
|
}
|
|
|
|
static void BlendColorDodge(SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
if ( pSrc[nIndex] == 255 )
|
|
{
|
|
pBlend[nIndex] = 255;
|
|
}
|
|
else
|
|
{
|
|
int nValue = ( pDst[nIndex] * 255 ) / ( 255 - pSrc[nIndex] );
|
|
pBlend[nIndex] = nValue <= 255 ? nValue : 255;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BlendColorBurn (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
if ( pSrc[nIndex] == 0 )
|
|
{
|
|
pBlend[nIndex] = 0;
|
|
}
|
|
else
|
|
{
|
|
int nValue = ( ( 255 - pDst[nIndex] ) * 255 ) / pSrc[nIndex];
|
|
pBlend[nIndex] = nValue <= 255 ? 255 - nValue : 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BlendHardLight (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pSrc[nIndex] < 0x80 ? ( pDst[nIndex] * 2 * pSrc[nIndex] ) / 255 : 255 - 2 * ( ( 255 - pDst[nIndex] ) * ( 255 - pSrc[nIndex] ) ) / 255;
|
|
}
|
|
}
|
|
|
|
static void BlendSoftLight (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
if ( pSrc[nIndex] < 0x80 )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] - (255 - 2 * pSrc[nIndex]) * pDst[nIndex] * (255 - pDst[nIndex]) / ( 255 * 255 );
|
|
}
|
|
else
|
|
{
|
|
int nValue;
|
|
if ( pDst[nIndex] < 0x40 )
|
|
{
|
|
nValue = ( ( ( ( ( 16 * pDst[nIndex] - 12 * 255 ) * pDst[nIndex] ) / 255 ) + 4 * 255 ) * pDst[nIndex] ) / 255;
|
|
}
|
|
else
|
|
{
|
|
nValue = (int)sqrt( 255.0 * pDst[nIndex] );
|
|
}
|
|
pBlend[nIndex] = pDst[nIndex] + ( 2 * pSrc[nIndex] - 255 ) * ( nValue - pDst[nIndex] ) / 255;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void BlendDifference(SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] < pSrc[nIndex] ? pSrc[nIndex] - pDst[nIndex] : pDst[nIndex] - pSrc[nIndex];
|
|
}
|
|
}
|
|
|
|
static void BlendExclusion (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
for ( int nIndex = 0; nIndex < SColorModeNComps[eColorMode]; ++nIndex )
|
|
{
|
|
pBlend[nIndex] = pDst[nIndex] + pSrc[nIndex] - ( 2 * pDst[nIndex] * pSrc[nIndex] ) / 255;
|
|
}
|
|
}
|
|
|
|
static void BlendHue (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
int nSrcH, nSrcS, nSrcV, nDstH, nDstS, nDstV;
|
|
|
|
switch (eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pBlend[0] = pDst[0];
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
RGBToHSV( pSrc[0], pSrc[1], pSrc[2], &nSrcH, &nSrcS, &nSrcV );
|
|
RGBToHSV( pDst[0], pDst[1], pDst[2], &nDstH, &nDstS, &nDstV );
|
|
HSVToRGB( nSrcH, nDstS, nDstV, &pBlend[0], &pBlend[1], &pBlend[2] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void BlendSaturation(SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
int nSrcH, nSrcS, nSrcV, nDstH, nDstS, nDstV;
|
|
|
|
switch (eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pBlend[0] = pDst[0];
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
RGBToHSV( pSrc[0], pSrc[1], pSrc[2], &nSrcH, &nSrcS, &nSrcV );
|
|
RGBToHSV( pDst[0], pDst[1], pDst[2], &nDstH, &nDstS, &nDstV );
|
|
HSVToRGB( nDstH, nSrcS, nDstV, &pBlend[0], &pBlend[1], &pBlend[2] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void BlendColor (SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
int nSrcH, nSrcS, nSrcV, nDstH, nDstS, nDstV;
|
|
|
|
switch (eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pBlend[0] = pDst[0];
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
RGBToHSV( pSrc[0], pSrc[1], pSrc[2], &nSrcH, &nSrcS, &nSrcV );
|
|
RGBToHSV( pDst[0], pDst[1], pDst[2], &nDstH, &nDstS, &nDstV );
|
|
HSVToRGB( nSrcH, nSrcS, nDstV, &pBlend[0], &pBlend[1], &pBlend[2] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void BlendLuminosity(SColorPointer pSrc, SColorPointer pDst, SColorPointer pBlend, SColorMode eColorMode)
|
|
{
|
|
int nSrcH, nSrcS, nSrcV, nDstH, nDstS, nDstV;
|
|
|
|
switch (eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pBlend[0] = pDst[0];
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
RGBToHSV( pSrc[0], pSrc[1], pSrc[2], &nSrcH, &nSrcS, &nSrcV );
|
|
RGBToHSV( pDst[0], pDst[1], pDst[2], &nDstH, &nDstS, &nDstV );
|
|
HSVToRGB( nDstH, nDstS, nSrcV, &pBlend[0], &pBlend[1], &pBlend[2] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// Äîëæíî ñîâïàäàòü ñ ïåðå÷èñëåíèåì GrBlendMode èç GState.h.
|
|
SBlendFunc c_arrBlendFunctions[] =
|
|
{
|
|
NULL,
|
|
&BlendMultiply,
|
|
&BlendScreen,
|
|
&BlendOverlay,
|
|
&BlendDarken,
|
|
&BlendLighten,
|
|
&BlendColorDodge,
|
|
&BlendColorBurn,
|
|
&BlendHardLight,
|
|
&BlendSoftLight,
|
|
&BlendDifference,
|
|
&BlendExclusion,
|
|
&BlendHue,
|
|
&BlendSaturation,
|
|
&BlendColor,
|
|
&BlendLuminosity
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// Font substitutions
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct SImageOutFontSubst
|
|
{
|
|
char *sName;
|
|
double dAvrWidth;
|
|
};
|
|
|
|
// íóìåðàöèÿ: { symbolic:12, fixed:8, serif:4, sans-serif:0 } + bold * 2 + italic
|
|
static SImageOutFontSubst c_arrSImageOutSubstFonts[16] =
|
|
{
|
|
{"Helvetica", 0.833},
|
|
{"Helvetica-Oblique", 0.833},
|
|
{"Helvetica-Bold", 0.889},
|
|
{"Helvetica-BoldOblique", 0.889},
|
|
{"Times-Roman", 0.788},
|
|
{"Times-Italic", 0.722},
|
|
{"Times-Bold", 0.833},
|
|
{"Times-BoldItalic", 0.778},
|
|
{"Courier", 0.600},
|
|
{"Courier-Oblique", 0.600},
|
|
{"Courier-Bold", 0.600},
|
|
{"Courier-BoldOblique", 0.600},
|
|
{"Symbol", 0.576},
|
|
{"Symbol", 0.576},
|
|
{"Symbol", 0.576},
|
|
{"Symbol", 0.576}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// SImageOutFontFileID
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
class SImageOutFontFileID: public SFontFileID
|
|
{
|
|
public:
|
|
|
|
SImageOutFontFileID(Ref *oRef)
|
|
{
|
|
m_oRef = *oRef;
|
|
m_nSubstIndex = -1;
|
|
}
|
|
|
|
~SImageOutFontFileID()
|
|
{
|
|
}
|
|
|
|
BOOL Matches(SFontFileID *pID)
|
|
{
|
|
return ((SImageOutFontFileID *)pID)->m_oRef.nNum == m_oRef.nNum && ((SImageOutFontFileID *)pID)->m_oRef.nGen == m_oRef.nGen;
|
|
}
|
|
|
|
void SetSubstIndex(int nSubstIndex)
|
|
{
|
|
m_nSubstIndex = nSubstIndex;
|
|
}
|
|
int GetSubstIndex()
|
|
{
|
|
return m_nSubstIndex;
|
|
}
|
|
|
|
private:
|
|
|
|
Ref m_oRef;
|
|
int m_nSubstIndex;
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// T3FontCache
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct T3FontCacheTag
|
|
{
|
|
unsigned short unCode;
|
|
unsigned short unMRU; // Valid bit (0x8000) è íîìåð MRU
|
|
};
|
|
|
|
class T3FontCache
|
|
{
|
|
public:
|
|
|
|
T3FontCache(Ref *pFontID, double dMatrix11, double dMatrix12, double dMatrix21, double dMAtrix22, int nGlyphX, int nGlyphY, int nGlyphWidth, int nGlyphHeight, BOOL bValidBBox, BOOL bAA)
|
|
{
|
|
m_oFontID = *pFontID;
|
|
|
|
m_dMatrix11 = dMatrix11;
|
|
m_dMatrix12 = dMatrix12;
|
|
m_dMatrix21 = dMatrix21;
|
|
m_dMatrix22 = dMAtrix22;
|
|
|
|
m_nGlyphX = nGlyphX;
|
|
m_nGlyphY = nGlyphY;
|
|
m_nGlyphWidth = nGlyphWidth;
|
|
m_nGlyphHeight = nGlyphHeight;
|
|
|
|
m_bValidBBox = bValidBBox;
|
|
if ( bAA )
|
|
{
|
|
m_nGlyphSize = m_nGlyphWidth * m_nGlyphHeight;
|
|
}
|
|
else
|
|
{
|
|
m_nGlyphSize = (( m_nGlyphWidth + 7 ) >> 3) * m_nGlyphHeight;
|
|
}
|
|
m_nCacheAssoc = 8;
|
|
if ( m_nGlyphSize <= 256 )
|
|
{
|
|
m_nCacheSets = 8;
|
|
}
|
|
else if ( m_nGlyphSize <= 512 )
|
|
{
|
|
m_nCacheSets = 4;
|
|
}
|
|
else if ( m_nGlyphSize <= 1024 )
|
|
{
|
|
m_nCacheSets = 2;
|
|
}
|
|
else
|
|
{
|
|
m_nCacheSets = 1;
|
|
}
|
|
m_pCacheData = (unsigned char *)MemUtilsMallocArray( m_nCacheSets * m_nCacheAssoc, m_nGlyphSize );
|
|
m_pCacheTags = (T3FontCacheTag *)MemUtilsMallocArray( m_nCacheSets * m_nCacheAssoc, sizeof(T3FontCacheTag) );
|
|
|
|
for ( int nIndex = 0; nIndex < m_nCacheSets * m_nCacheAssoc; ++nIndex )
|
|
{
|
|
m_pCacheTags[nIndex].unMRU = nIndex & (m_nCacheAssoc - 1);
|
|
}
|
|
}
|
|
~T3FontCache()
|
|
{
|
|
MemUtilsFree( m_pCacheData );
|
|
MemUtilsFree( m_pCacheTags );
|
|
}
|
|
BOOL Matches(Ref *pFontID, double dMatrix11, double dMatrix12, double dMatrix21, double dMAtrix22)
|
|
{
|
|
return m_oFontID.nNum == pFontID->nNum && m_oFontID.nGen == pFontID->nGen && m_dMatrix11 == dMatrix11 && m_dMatrix12 == dMatrix12 && m_dMatrix21 == dMatrix21 && m_dMatrix22 == dMAtrix22;
|
|
}
|
|
|
|
public:
|
|
|
|
Ref m_oFontID; // ID äàííîãî øðèôòà (íîìåðà äàííîãî îáúåêòà â PDF-ôàéëå)
|
|
double m_dMatrix11; //
|
|
double m_dMatrix12; // Ìàòðèöà ïðåîáðàçîâàíèÿ
|
|
double m_dMatrix21; //
|
|
double m_dMatrix22; //
|
|
int m_nGlyphX; // Ñäâèã â ïèêñåëÿõ Glyph Bitmap
|
|
int m_nGlyphY; //
|
|
int m_nGlyphWidth; // Øèðèíà Glyph Bitmap â ïèêñåëÿõ
|
|
int m_nGlyphHeight; // Âûñîòà Glyph Bitmap â ïèêñåëÿõ
|
|
BOOL m_bValidBBox; // False, òîëüêî åñëè BBox áûë [0 0 0 0]
|
|
int m_nGlyphSize; // Ðàçìåð Glyph bitmaps â áàéòàõ
|
|
|
|
int m_nCacheSets; // Êîëè÷åñòâî Sets êýøå
|
|
int m_nCacheAssoc; // Êîëè÷åñòîâ ñèìâîëîâ â îäíîì Set
|
|
|
|
unsigned char *m_pCacheData; // Glyph pixmap
|
|
T3FontCacheTag *m_pCacheTags; // Êîäû ñèìâîëîâ (òýãè)
|
|
};
|
|
|
|
struct T3GlyphStack
|
|
{
|
|
unsigned short unCode; // Êîä ñèìâîëà
|
|
|
|
// Èíôîðìàöèÿ î êýøå
|
|
T3FontCache *pCache; // FontCache äëÿ òåêóùåãî øðèôòà
|
|
T3FontCacheTag *pCacheTag; // Óêàçàòåëü íà ñòðóêòóðó õðàíÿþùóþ òýã äàííîãî ñèìâîëà
|
|
unsigned char *pCacheData; // Óêçàòåëü íà áèòìàï äëÿ äàííîãî ñèìâîëà
|
|
|
|
// Ñîõðàíåííîå ñîñòîÿíèå
|
|
SBitmap *pOriginalBitmap; // Èñêõîäíûé áèòìàï
|
|
SImage *pOriginalSImage; // Èñõîäíûé îáúåêò SImage
|
|
double dOriginalCTM4; // 4-ûé ýëåìåíò â èñõîäíîé ìàòðèöå CTM
|
|
double dOriginalCTM5; // 5-ûé ýëåìåíò â èñõîäíîé ìàòðèöå CTM
|
|
|
|
T3GlyphStack *pNext; // Óêàçàòåëü íà ñëåäóþùèé ýëåìåíò
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// ImageData
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
struct ImageMaskData
|
|
{
|
|
ImageStream *pImageStream;
|
|
BOOL bInvert;
|
|
int nWidth;
|
|
int nHeight;
|
|
int nY;
|
|
};
|
|
|
|
struct MaskedImageData
|
|
{
|
|
ImageStream *pImageStream;
|
|
GrImageColorMap *pColorMap;
|
|
SBitmap *pMask;
|
|
SColorPointer pLookup;
|
|
SColorMode eColorMode;
|
|
int nWidth;
|
|
int nHeight;
|
|
int nY;
|
|
};
|
|
|
|
struct ImageData
|
|
{
|
|
ImageStream *pStream;
|
|
GrImageColorMap *pColorMap;
|
|
SColorPointer pLookup;
|
|
int *pMaskColors;
|
|
SColorMode eColorMode;
|
|
int nWidth;
|
|
int nHeight;
|
|
int nY;
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// SImageTransparencyGroup
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct TransparencyGroup
|
|
{
|
|
int nTransX; // Êîîðäèíàòû ïåðåíîñà
|
|
int nTransY; //
|
|
|
|
SBitmap *pBitmap; // Áèòìàï äëÿ transparency group
|
|
GrColorSpace *pBlendColorSpace;
|
|
BOOL bIsolated;
|
|
|
|
// Ñîõðàíåííîå ñîñòîÿíèå
|
|
SBitmap *pOriginalBitmap; // Èñêõîäíûé áèòìàï
|
|
SImage *pOriginalSImage; // Èñõîäíûé îáúåêò SImage
|
|
|
|
TransparencyGroup *pNext; // Óêàçàòåëü íà ñëåäóþùèé ýëåìåíò
|
|
};
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
// SImageOutputDev
|
|
//-------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
SImageOutputDev::SImageOutputDev(GlobalParams *pGlobalParams, SColorMode eColorMode, int nBitmapRowPad, BOOL bReverseVideo, SColorPointer pPaperColor, BOOL bBitmapTopDown, BOOL bAllowAA)
|
|
{
|
|
m_pGlobalParams = pGlobalParams;
|
|
|
|
m_eColorMode = eColorMode;
|
|
|
|
m_nBitmapRowPad = nBitmapRowPad;
|
|
m_bBitmapTopDown = bBitmapTopDown;
|
|
|
|
m_bAllowAA = bAllowAA;
|
|
|
|
if ( m_pGlobalParams )
|
|
{
|
|
m_bVectorAA = m_bAllowAA && m_pGlobalParams->GetVectorAntialias() && m_eColorMode != colorModeMono1;
|
|
}
|
|
else
|
|
{
|
|
m_bVectorAA = m_bAllowAA && m_eColorMode != colorModeMono1;
|
|
}
|
|
|
|
SetupScreenParams( 72.0, 72.0 );
|
|
|
|
m_bReverseVideo = bReverseVideo;
|
|
ColorCopy( m_pPaperColor, pPaperColor );
|
|
|
|
m_pXref = NULL;
|
|
|
|
m_pBitmap = new SBitmap( 1, 1, m_nBitmapRowPad, m_eColorMode, m_eColorMode != colorModeMono1, m_bBitmapTopDown );
|
|
m_pSImage = new SImage( m_pBitmap, m_bVectorAA, &m_pScreenParams );
|
|
m_pSImage->Clear( m_pPaperColor, 0 );
|
|
|
|
m_pFontEngine = NULL;
|
|
|
|
m_nT3FontsCount = 0;
|
|
m_pT3GlyphStack = NULL;
|
|
|
|
m_pFont = NULL;
|
|
m_bNeedFontUpdate = FALSE;
|
|
m_pTextClipPath = NULL;
|
|
|
|
m_pTranspGroupStack = NULL;
|
|
}
|
|
|
|
void SImageOutputDev::SetupScreenParams(double dHorDPI, double dVerDPI)
|
|
{
|
|
if ( m_pGlobalParams )
|
|
{
|
|
m_pScreenParams.nSize = m_pGlobalParams->GetScreenSize();
|
|
m_pScreenParams.nDotRadius = m_pGlobalParams->GetScreenDotRadius();
|
|
m_pScreenParams.dGamma = (double)m_pGlobalParams->GetScreenGamma();
|
|
m_pScreenParams.dBlackThreshold = (double)m_pGlobalParams->GetScreenBlackThreshold();
|
|
m_pScreenParams.dWhiteThreshold = (double)m_pGlobalParams->GetScreenWhiteThreshold();
|
|
|
|
switch ( m_pGlobalParams->GetScreenType() )
|
|
{
|
|
case screenDispersed:
|
|
m_pScreenParams.eType = sscreenDispersed;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 4;
|
|
}
|
|
break;
|
|
case screenClustered:
|
|
m_pScreenParams.eType = sscreenClustered;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 10;
|
|
}
|
|
break;
|
|
case screenStochasticClustered:
|
|
m_pScreenParams.eType = sscreenStochasticClustered;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 100;
|
|
}
|
|
if ( m_pScreenParams.nDotRadius < 0 )
|
|
{
|
|
m_pScreenParams.nDotRadius = 2;
|
|
}
|
|
break;
|
|
case screenUnset:
|
|
default:
|
|
// Èñïîëüçóåì Clustered Dithering äëÿ ðàçðåøåíèÿ >= 300 dpi
|
|
if ( dHorDPI > 299.9 && dVerDPI > 299.9 )
|
|
{
|
|
m_pScreenParams.eType = sscreenStochasticClustered;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 100;
|
|
}
|
|
if ( m_pScreenParams.nDotRadius < 0 )
|
|
{
|
|
m_pScreenParams.nDotRadius = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pScreenParams.eType = sscreenDispersed;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pScreenParams.nSize = -1;
|
|
m_pScreenParams.nDotRadius = -1;
|
|
m_pScreenParams.dGamma = 1.0;
|
|
m_pScreenParams.dBlackThreshold = 0.0;
|
|
m_pScreenParams.dWhiteThreshold = 1.0;
|
|
|
|
if ( dHorDPI > 299.9 && dVerDPI > 299.9 )
|
|
{
|
|
m_pScreenParams.eType = sscreenStochasticClustered;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 100;
|
|
}
|
|
if ( m_pScreenParams.nDotRadius < 0 )
|
|
{
|
|
m_pScreenParams.nDotRadius = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pScreenParams.eType = sscreenDispersed;
|
|
if ( m_pScreenParams.nSize < 0 )
|
|
{
|
|
m_pScreenParams.nSize = 4;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
SImageOutputDev::~SImageOutputDev()
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nT3FontsCount; ++nIndex )
|
|
{
|
|
if ( m_pT3FontCache[nIndex] )
|
|
delete m_pT3FontCache[nIndex];
|
|
}
|
|
if ( m_pFontEngine )
|
|
{
|
|
delete m_pFontEngine;
|
|
}
|
|
if ( m_pSImage )
|
|
{
|
|
delete m_pSImage;
|
|
}
|
|
if ( m_pBitmap )
|
|
{
|
|
delete m_pBitmap;
|
|
}
|
|
}
|
|
|
|
void SImageOutputDev::NewPDF(XRef *pXref)
|
|
{
|
|
m_pXref = pXref;
|
|
if ( m_pFontEngine )
|
|
{
|
|
delete m_pFontEngine;
|
|
}
|
|
m_pFontEngine = new SFontEngine( ( m_pGlobalParams ? m_pGlobalParams->GetEnableGlyphLib() : FALSE ), m_bAllowAA && m_pGlobalParams->GetAntialias() && m_eColorMode != colorModeMono1 );
|
|
for ( int nIndex = 0; nIndex < m_nT3FontsCount; ++nIndex )
|
|
{
|
|
if ( m_pT3FontCache[nIndex] )
|
|
delete m_pT3FontCache[nIndex];
|
|
}
|
|
m_nT3FontsCount = 0;
|
|
}
|
|
|
|
void SImageOutputDev::StartPage(int nPageIndex, GrState *pGState)
|
|
{
|
|
int nWidth, nHeight;
|
|
|
|
if ( pGState )
|
|
{
|
|
SetupScreenParams( pGState->GetHorDPI(), pGState->GetVerDPI() );
|
|
nWidth = (int)(pGState->GetPageWidth() + 0.5);
|
|
if ( nWidth <= 0 )
|
|
{
|
|
nWidth = 1;
|
|
}
|
|
nHeight = (int)(pGState->GetPageHeight() + 0.5);
|
|
if ( nHeight <= 0 )
|
|
{
|
|
nHeight = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nWidth = nHeight = 1;
|
|
}
|
|
if ( m_pSImage )
|
|
{
|
|
delete m_pSImage;
|
|
}
|
|
if ( !m_pBitmap || nWidth != m_pBitmap->GetWidth() || nHeight != m_pBitmap->GetHeight() )
|
|
{
|
|
if ( m_pBitmap )
|
|
{
|
|
delete m_pBitmap;
|
|
}
|
|
m_pBitmap = new SBitmap( nWidth, nHeight, m_nBitmapRowPad, m_eColorMode, m_eColorMode != colorModeMono1, m_bBitmapTopDown );
|
|
}
|
|
m_pSImage = new SImage( m_pBitmap, m_bVectorAA, &m_pScreenParams );
|
|
|
|
if ( pGState )
|
|
{
|
|
double *pCTM = pGState->GetCTM();
|
|
double arrMatrix[6];
|
|
arrMatrix[0] = (double)pCTM[0];
|
|
arrMatrix[1] = (double)pCTM[1];
|
|
arrMatrix[2] = (double)pCTM[2];
|
|
arrMatrix[3] = (double)pCTM[3];
|
|
arrMatrix[4] = (double)pCTM[4];
|
|
arrMatrix[5] = (double)pCTM[5];
|
|
m_pSImage->SetMatrix( arrMatrix );
|
|
}
|
|
|
|
SColor pColor;
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pColor[0] = 0;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pColor[0] = pColor[1] = pColor[2] = 0;
|
|
break;
|
|
}
|
|
|
|
// Óñòàíàâëèâàåì ñòàíäàðòíûå ïàðàìåòðû
|
|
m_pSImage->SetStrokePattern( new SSolidColor(pColor) );
|
|
m_pSImage->SetFillPattern( new SSolidColor(pColor) );
|
|
m_pSImage->SetLineCap( LineCapButt );
|
|
m_pSImage->SetLineJoin( LineJoinMiter );
|
|
m_pSImage->SetLineDash( NULL, 0, 0 );
|
|
m_pSImage->SetMiterLimit( 10 );
|
|
m_pSImage->SetFlatness( 1 );
|
|
// ïàðàìåòð SA ïî óìîë÷àíèþ äîëæåí áûòü False, íî Acrobat èíîãäà âûñòàâëÿåò åãî True
|
|
m_pSImage->SetStrokeAdjust( ( m_pGlobalParams ? m_pGlobalParams->GetStrokeAdjust() : FALSE ) );
|
|
m_pSImage->Clear( m_pPaperColor, 0 );
|
|
}
|
|
|
|
void SImageOutputDev::EndPage()
|
|
{
|
|
if ( m_eColorMode != colorModeMono1 )
|
|
{
|
|
m_pSImage->CompositeBackground( m_pPaperColor );
|
|
}
|
|
}
|
|
|
|
void SImageOutputDev::SaveGState(GrState *pGState)
|
|
{
|
|
m_pSImage->SaveState();
|
|
}
|
|
|
|
void SImageOutputDev::RestoreGState(GrState *pGState)
|
|
{
|
|
m_pSImage->RestoreState();
|
|
m_bNeedFontUpdate = TRUE;
|
|
}
|
|
|
|
void SImageOutputDev::UpdateAll(GrState *pGState)
|
|
{
|
|
UpdateLineDash( pGState );
|
|
UpdateLineJoin( pGState );
|
|
UpdateLineCap( pGState );
|
|
UpdateLineWidth( pGState );
|
|
UpdateFlatness( pGState );
|
|
UpdateMiterLimit( pGState );
|
|
UpdateStrokeAdjust( pGState );
|
|
UpdateFillColor( pGState );
|
|
UpdateStrokeColor( pGState );
|
|
m_bNeedFontUpdate = TRUE;
|
|
}
|
|
|
|
void SImageOutputDev::UpdateCTM(GrState *pGState, double dMatrix11, double dMatrix12, double dMatrix21, double dMatrix22, double dMatrix31, double dMatrix32)
|
|
{
|
|
double *pCTM = pGState->GetCTM();
|
|
|
|
double arrMatrix[6];
|
|
arrMatrix[0] = (double)pCTM[0];
|
|
arrMatrix[1] = (double)pCTM[1];
|
|
arrMatrix[2] = (double)pCTM[2];
|
|
arrMatrix[3] = (double)pCTM[3];
|
|
arrMatrix[4] = (double)pCTM[4];
|
|
arrMatrix[5] = (double)pCTM[5];
|
|
m_pSImage->SetMatrix( arrMatrix );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateLineDash(GrState *pGState)
|
|
{
|
|
double *pDashPattern;
|
|
int nDashLength;
|
|
double dDashStart;
|
|
double arrDash[20];
|
|
|
|
pGState->GetLineDash( &pDashPattern, &nDashLength, &dDashStart );
|
|
if ( nDashLength > 20 )
|
|
{
|
|
nDashLength = 20;
|
|
}
|
|
for ( int nIndex = 0; nIndex < nDashLength; ++nIndex )
|
|
{
|
|
arrDash[nIndex] = (double)pDashPattern[nIndex];
|
|
if ( arrDash[nIndex] < 0 )
|
|
{
|
|
arrDash[nIndex] = 0;
|
|
}
|
|
}
|
|
m_pSImage->SetLineDash( arrDash, nDashLength, (double)dDashStart );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateFlatness(GrState *pGState)
|
|
{
|
|
m_pSImage->SetFlatness( pGState->GetFlatness() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateLineJoin(GrState *pGState)
|
|
{
|
|
m_pSImage->SetLineJoin( pGState->GetLineJoin() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateLineCap(GrState *pGState)
|
|
{
|
|
m_pSImage->SetLineCap( pGState->GetLineCap() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateMiterLimit(GrState *pGState)
|
|
{
|
|
m_pSImage->SetMiterLimit( pGState->GetMiterLimit() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateLineWidth(GrState *pGState)
|
|
{
|
|
m_pSImage->SetLineWidth( pGState->GetLineWidth() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateStrokeAdjust(GrState *pGState)
|
|
{
|
|
#if 0
|
|
// ïàðàìåòð SA ïî óìîë÷àíèþ äîëæåí áûòü False, íî Acrobat èíîãäà âûñòàâëÿåò åãî True
|
|
m_pSImage->SetStrokeAdjust( pGState->GetStrokeAdjust() );
|
|
#endif
|
|
}
|
|
|
|
void SImageOutputDev::UpdateFillColor(GrState *pGState)
|
|
{
|
|
GrGray oGray;
|
|
GrRGB oRGB;
|
|
|
|
pGState->GetFillGray( &oGray );
|
|
pGState->GetFillRGB( &oRGB );
|
|
m_pSImage->SetFillPattern( GetColor( oGray, &oRGB ) );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateStrokeColor(GrState *pGState)
|
|
{
|
|
GrGray oGray;
|
|
GrRGB oRGB;
|
|
|
|
pGState->GetStrokeGray( &oGray );
|
|
pGState->GetStrokeRGB( &oRGB );
|
|
m_pSImage->SetStrokePattern( GetColor( oGray, &oRGB ) );
|
|
}
|
|
|
|
SPattern *SImageOutputDev::GetColor(GrGray oGray, GrRGB *pRGB)
|
|
{
|
|
GrColorComp nR, nG, nB;
|
|
|
|
if ( m_bReverseVideo )
|
|
{
|
|
oGray = GrColorComp1 - oGray;
|
|
nR = GrColorComp1 - pRGB->r;
|
|
nG = GrColorComp1 - pRGB->g;
|
|
nB = GrColorComp1 - pRGB->b;
|
|
}
|
|
else
|
|
{
|
|
nR = pRGB->r;
|
|
nG = pRGB->g;
|
|
nB = pRGB->b;
|
|
}
|
|
|
|
SPattern *pPattern = NULL;
|
|
SColor pColor;
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pColor[0] = ColorToByte( oGray );
|
|
pPattern = new SSolidColor( pColor );
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pColor[0] = ColorToByte( nR );
|
|
pColor[1] = ColorToByte( nG );
|
|
pColor[2] = ColorToByte( nB );
|
|
pPattern = new SSolidColor( pColor );
|
|
break;
|
|
}
|
|
|
|
return pPattern;
|
|
}
|
|
|
|
void SImageOutputDev::UpdateBlendMode(GrState *pGState)
|
|
{
|
|
m_pSImage->SetBlendFunc( c_arrBlendFunctions[pGState->GetBlendMode()] );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateFillOpacity(GrState *pGState)
|
|
{
|
|
m_pSImage->SetFillAlpha( (double)pGState->GetFillOpacity() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateStrokeOpacity(GrState *pGState)
|
|
{
|
|
m_pSImage->SetStrokeAlpha( (double)pGState->GetStrokeOpacity() );
|
|
}
|
|
|
|
void SImageOutputDev::UpdateFont(GrState *pGState)
|
|
{
|
|
m_bNeedFontUpdate = TRUE;
|
|
}
|
|
|
|
void SImageOutputDev::DoUpdateFont(GrState *pGState)
|
|
{
|
|
m_bNeedFontUpdate = FALSE;
|
|
m_pFont = NULL;
|
|
|
|
CStringW wsTempFileName = _T("");
|
|
|
|
GrFont *pGrFont;
|
|
if ( !( pGrFont = pGState->GetFont() ) )
|
|
{
|
|
return;
|
|
}
|
|
GrFontType eFontType = pGrFont->GetType();
|
|
if ( eFontType == fontType3 ) // Type3-øðèôòû îáðàáàòûâàþòñÿ îòäåëüíîé êîìàíäîé
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Ïðîâåðÿåì, âîçìîæíî íóæíûé FontFile åùå ëåæèò â êýøå
|
|
SImageOutFontFileID *pID = new SImageOutFontFileID( pGrFont->GetID() );
|
|
if ( !pID )
|
|
return;
|
|
|
|
CFontFileTrueType *pTTFontFile = NULL;
|
|
unsigned short *pCodeToGID = NULL;
|
|
int nLen = 0;
|
|
|
|
CStringW wsFileName = _T("");
|
|
DisplayFontParam *pDisplayFontParam = NULL;
|
|
SFontFile *pFontFile = NULL;
|
|
if ( ( pFontFile = m_pFontEngine->GetFontFile( pID ) ) )
|
|
{
|
|
delete pID;
|
|
}
|
|
else
|
|
{
|
|
// Åñëè øðèôò âêëþ÷åí â PDF-ôàéë, çàïèñûâàåì åãî íà äèñê
|
|
Ref oEmbRef;
|
|
if ( pGrFont->GetEmbeddedFontFileRef( &oEmbRef ) )
|
|
{
|
|
FILE *pTempFile = NULL;
|
|
if ( !OpenTempFile( &wsTempFileName, &pTempFile, _T("wb"), NULL, m_pGlobalParams->GetTempFolder() ) )
|
|
{
|
|
// TO DO: Eerror "Couldn't create temporary font file"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
Object oReferenceObject, oStreamObject;
|
|
oReferenceObject.InitRef( oEmbRef.nNum, oEmbRef.nGen );
|
|
oReferenceObject.Fetch( m_pXref, &oStreamObject );
|
|
oReferenceObject.Free();
|
|
if ( !oStreamObject.IsStream() )
|
|
{
|
|
// TO DO: Error "Embedded font object is wrong type"
|
|
oStreamObject.Free();
|
|
fclose( pTempFile );
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
oStreamObject.StreamReset();
|
|
int nChar;
|
|
while ( ( nChar = oStreamObject.StreamGetChar() ) != EOF )
|
|
{
|
|
fputc( nChar, pTempFile );
|
|
}
|
|
oStreamObject.StreamClose();
|
|
oStreamObject.Free();
|
|
fclose( pTempFile );
|
|
wsFileName = wsTempFileName;
|
|
}
|
|
else if ( _T("") == ( wsFileName = pGrFont->GetExternalFontFilePath() ) ) // Åñëè åñòü âíåøíèé FontFile, òîãäà èñïîëüçóåì åãî
|
|
{
|
|
// Èùåì DisplayFont
|
|
if ( pGrFont->IsCIDFont() )
|
|
{
|
|
if ( m_pGlobalParams && ((GrCIDFont *)pGrFont)->GetCollection() )
|
|
{
|
|
pDisplayFontParam = m_pGlobalParams->GetDisplayCIDFont( pGrFont->GetBaseName(), ((GrCIDFont *)pGrFont)->GetCollection() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( m_pGlobalParams && pGrFont->GetBaseName() )
|
|
{
|
|
pDisplayFontParam = m_pGlobalParams->GetDisplayFont( pGrFont->GetBaseName() );
|
|
}
|
|
if ( m_pGlobalParams && !pDisplayFontParam )
|
|
{
|
|
int nSubstIndex = -1;
|
|
|
|
if ( pGrFont->IsFixedWidth() )
|
|
{
|
|
nSubstIndex = 8;
|
|
}
|
|
else if ( pGrFont->IsSerif() )
|
|
{
|
|
nSubstIndex = 4;
|
|
}
|
|
else
|
|
{
|
|
nSubstIndex = 0;
|
|
}
|
|
if ( pGrFont->IsBold() )
|
|
{
|
|
nSubstIndex += 2;
|
|
}
|
|
if ( pGrFont->IsItalic() )
|
|
{
|
|
nSubstIndex += 1;
|
|
}
|
|
StringExt *seSubstName = new StringExt( c_arrSImageOutSubstFonts[nSubstIndex].sName );
|
|
pDisplayFontParam = m_pGlobalParams->GetDisplayFont( seSubstName );
|
|
delete seSubstName;
|
|
pID->SetSubstIndex( nSubstIndex );
|
|
}
|
|
}
|
|
if ( !pDisplayFontParam )
|
|
{
|
|
// TO DO: Error "Couldn't find a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
switch ( pDisplayFontParam->m_eType )
|
|
{
|
|
case displayFontT1:
|
|
wsFileName = *(pDisplayFontParam->m_oT1.pwsFileName);
|
|
eFontType = pGrFont->IsCIDFont() ? fontCIDType0 : fontType1;
|
|
break;
|
|
case displayFontTT:
|
|
wsFileName = *(pDisplayFontParam->m_oTT.pwsFileName);
|
|
eFontType = pGrFont->IsCIDFont() ? fontCIDType2 : fontTrueType;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Çàãðóæàåì FontFile
|
|
switch ( eFontType )
|
|
{
|
|
case fontType1:
|
|
if ( !( pFontFile = m_pFontEngine->LoadType1Font( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName, ((Gr8BitFont *)pGrFont)->GetEncoding() ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontType1C:
|
|
if ( !( pFontFile = m_pFontEngine->LoadType1CFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName, ((Gr8BitFont *)pGrFont)->GetEncoding() ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontType1COT:
|
|
if ( !( pFontFile = m_pFontEngine->LoadOpenTypeT1CFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName, ((Gr8BitFont *)pGrFont)->GetEncoding() ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontTrueType:
|
|
case fontTrueTypeOT:
|
|
if ( ( pTTFontFile = CFontFileTrueType::LoadFromFile( wsFileName.GetBuffer() ) ) )
|
|
{
|
|
pCodeToGID = ((Gr8BitFont *)pGrFont)->GetCodeToGIDMap( pTTFontFile );
|
|
nLen = 256;
|
|
delete pTTFontFile;
|
|
}
|
|
else
|
|
{
|
|
pCodeToGID = NULL;
|
|
nLen = 0;
|
|
}
|
|
if ( !( pFontFile = m_pFontEngine->LoadTrueTypeFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName, pCodeToGID, nLen, m_pGlobalParams->GetTempFolder() ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontCIDType0:
|
|
case fontCIDType0C:
|
|
if ( !( pFontFile = m_pFontEngine->LoadCIDFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontCIDType0COT:
|
|
if ( !( pFontFile = m_pFontEngine->LoadOpenTypeCFFFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
case fontCIDType2:
|
|
case fontCIDType2OT:
|
|
pCodeToGID = NULL;
|
|
nLen = 0;
|
|
if ( pDisplayFontParam )
|
|
{
|
|
// Ñîçäàåì êàðòó CID-to-GID
|
|
CharCodeToUnicode *pCodeToUnicode = NULL;
|
|
if ( ( pCodeToUnicode = ((GrCIDFont *)pGrFont)->GetToUnicode() ) )
|
|
{
|
|
if ( ( pTTFontFile = CFontFileTrueType::LoadFromFile( wsFileName.GetBuffer() ) ) )
|
|
{
|
|
// Èùåì Unicode Cmap
|
|
int nCMapIndex;
|
|
for ( nCMapIndex = 0; nCMapIndex < pTTFontFile->GetCmapsCount(); ++nCMapIndex )
|
|
{
|
|
if ( ( pTTFontFile->GetCmapPlatform(nCMapIndex) == 3 && pTTFontFile->GetCmapEncoding(nCMapIndex) == 1 ) || pTTFontFile->GetCmapPlatform(nCMapIndex) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( nCMapIndex < pTTFontFile->GetCmapsCount() )
|
|
{
|
|
// CID -> Unicode -> GID
|
|
nLen = pCodeToUnicode->GetLength();
|
|
pCodeToGID = (unsigned short *)MemUtilsMallocArray( nLen, sizeof(unsigned short) );
|
|
for ( int nCode = 0; nCode < nLen; ++nCode )
|
|
{
|
|
Unicode arrUnicodeBuffer[8];
|
|
if ( pCodeToUnicode->MapToUnicode( nCode, arrUnicodeBuffer, 8 ) > 0 )
|
|
{
|
|
pCodeToGID[nCode] = pTTFontFile->MapCodeToGID( nCMapIndex, arrUnicodeBuffer[0] );
|
|
}
|
|
else
|
|
{
|
|
pCodeToGID[nCode] = 0;
|
|
}
|
|
}
|
|
}
|
|
delete pTTFontFile;
|
|
}
|
|
pCodeToUnicode->Release();
|
|
}
|
|
else
|
|
{
|
|
// TO DO: Error "Couldn't find a mapping to Unicode"
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ((GrCIDFont *)pGrFont)->GetCIDToGID() )
|
|
{
|
|
nLen = ((GrCIDFont *)pGrFont)->GetCIDToGIDLen();
|
|
pCodeToGID = (unsigned short *)MemUtilsMallocArray( nLen, sizeof(unsigned short));
|
|
memcpy( pCodeToGID, ((GrCIDFont *)pGrFont)->GetCIDToGID(), nLen * sizeof(unsigned short) );
|
|
}
|
|
}
|
|
if ( !( pFontFile = m_pFontEngine->LoadTrueTypeFont( pID, wsFileName.GetBuffer(), wsFileName == wsTempFileName, pCodeToGID, nLen, m_pGlobalParams->GetTempFolder() ) ) )
|
|
{
|
|
// TO DO: Error "Couldn't create a font"
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
// Òàêîãî íå äîëæíî ïðîèçîéòè
|
|
delete pID;
|
|
|
|
if ( _T("") != wsTempFileName )
|
|
{
|
|
_wunlink( wsTempFileName.GetBuffer() );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Ñ÷èòûâàåì ìàòðèöó äàííîãî øðèôòà
|
|
double *pTextMatrix = pGState->GetTextMatrix();
|
|
double dFontSize = pGState->GetFontSize();
|
|
double dMatrix11 = pTextMatrix[0] * dFontSize * pGState->GetHorizScaling();
|
|
double dMatrix12 = pTextMatrix[1] * dFontSize * pGState->GetHorizScaling();
|
|
double dMatrix21 = pTextMatrix[2] * dFontSize;
|
|
double dMatrix22 = pTextMatrix[3] * dFontSize;
|
|
|
|
// Äëÿ Çàìåíÿåìûõ øðèôòîâ: ïðèìåíÿåì ìàòðèöó øðèôòà è ñðàâíèâàåì øèðèíó ñèìâîëà 'm' â èñõîäíîì øðèôòå è â çàìåíåííîì øðèôòå
|
|
int nSubstIndex = ((SImageOutFontFileID *)pFontFile->GetFontFileID())->GetSubstIndex();
|
|
if ( nSubstIndex >= 0 )
|
|
{
|
|
int nCodeM;
|
|
for ( nCodeM = 0; nCodeM < 256; ++nCodeM )
|
|
{
|
|
char *sName = NULL;
|
|
if ( ( sName = ((Gr8BitFont *)pGrFont)->GetCharName(nCodeM)) && sName[0] == 'm' && sName[1] == '\0' )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( nCodeM < 256 )
|
|
{
|
|
double dWidth1 = ((Gr8BitFont *)pGrFont)->GetWidth( nCodeM );
|
|
double dWidth2 = c_arrSImageOutSubstFonts[nSubstIndex].dAvrWidth;
|
|
if ( !pGrFont->IsSymbolic() )
|
|
{
|
|
// Åñëè ðåàëüíûé øðèôò ñóùåñòâåííî óæå, ÷åì øðèôò êîòîðûì ìû åãî çàìåíÿåì, òîãäà óìåíüøàåì øèðèíó áóêâ ñîîòâåòñòâåííî
|
|
if ( dWidth1 > 0.01 && dWidth1 < 0.9 * dWidth2 )
|
|
{
|
|
dWidth1 /= dWidth2;
|
|
dMatrix11 *= dWidth1;
|
|
dMatrix21 *= dWidth1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ñîçäàåì øðèôò
|
|
double arrMatrix[4];
|
|
arrMatrix[0] = dMatrix11; arrMatrix[1] = dMatrix12;
|
|
arrMatrix[2] = dMatrix21; arrMatrix[3] = dMatrix22;
|
|
m_pFont = m_pFontEngine->GetFont( pFontFile, arrMatrix, m_pSImage->GetMatrix() );
|
|
|
|
return;
|
|
}
|
|
|
|
void SImageOutputDev::Stroke(GrState *pGState)
|
|
{
|
|
if ( pGState->GetStrokeColorSpace()->IsNonMarking() )
|
|
{
|
|
return;
|
|
}
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
if ( !pPath )
|
|
return;
|
|
m_pSImage->Stroke( pPath );
|
|
delete pPath;
|
|
}
|
|
|
|
void SImageOutputDev::Fill(GrState *pGState)
|
|
{
|
|
if ( pGState->GetFillColorSpace()->IsNonMarking() )
|
|
{
|
|
return;
|
|
}
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
if ( !pPath )
|
|
return;
|
|
m_pSImage->Fill( pPath, FALSE );
|
|
delete pPath;
|
|
}
|
|
|
|
void SImageOutputDev::EoFill(GrState *pGState)
|
|
{
|
|
if ( pGState->GetFillColorSpace()->IsNonMarking() )
|
|
{
|
|
return;
|
|
}
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
if ( !pPath )
|
|
return;
|
|
m_pSImage->Fill( pPath, TRUE );
|
|
delete pPath;
|
|
}
|
|
|
|
void SImageOutputDev::Clip(GrState *pGState)
|
|
{
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
m_pSImage->ClipToPath( pPath, FALSE );
|
|
delete pPath;
|
|
}
|
|
|
|
void SImageOutputDev::EoClip(GrState *pGState)
|
|
{
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
if ( !pPath )
|
|
return;
|
|
m_pSImage->ClipToPath( pPath, TRUE );
|
|
delete pPath;
|
|
}
|
|
|
|
void SImageOutputDev::ClipToStrokePath(GrState *pGState)
|
|
{
|
|
SPath *pPath = ConvertPath( pGState, pGState->GetPath() );
|
|
SPath *pStrokePath = m_pSImage->MakeStrokePath( pPath );
|
|
if ( !pPath || ! pStrokePath )
|
|
return;
|
|
|
|
delete pPath;
|
|
m_pSImage->ClipToPath( pStrokePath, FALSE );
|
|
delete pStrokePath;
|
|
}
|
|
|
|
SPath *SImageOutputDev::ConvertPath(GrState *pGState, GrPath *pPath)
|
|
{
|
|
SPath *pSPath = new SPath();
|
|
for ( int nSubPathIndex = 0; nSubPathIndex < pPath->GetSubpathsCount(); ++nSubPathIndex )
|
|
{
|
|
GrSubpath *pSubPath = pPath->GetSubpath(nSubPathIndex);
|
|
if ( pSubPath->GetPointsCount() > 0 )
|
|
{
|
|
pSPath->MoveTo( (double)pSubPath->GetX(0), (double)pSubPath->GetY(0) );
|
|
int nPointsIndex = 1;
|
|
while ( nPointsIndex < pSubPath->GetPointsCount() )
|
|
{
|
|
if ( pSubPath->GetCurve(nPointsIndex) )
|
|
{
|
|
pSPath->CurveTo( (double)pSubPath->GetX(nPointsIndex), (double)pSubPath->GetY(nPointsIndex), (double)pSubPath->GetX(nPointsIndex + 1), (double)pSubPath->GetY(nPointsIndex + 1), (double)pSubPath->GetX(nPointsIndex + 2), (double)pSubPath->GetY(nPointsIndex + 2) );
|
|
nPointsIndex += 3;
|
|
}
|
|
else
|
|
{
|
|
pSPath->LineTo( (double)pSubPath->GetX(nPointsIndex), (double)pSubPath->GetY(nPointsIndex) );
|
|
++nPointsIndex;
|
|
}
|
|
}
|
|
if ( pSubPath->IsClosed() )
|
|
{
|
|
pSPath->Close();
|
|
}
|
|
}
|
|
}
|
|
return pSPath;
|
|
}
|
|
|
|
void SImageOutputDev::DrawChar(GrState *pGState, double dX, double dY, double dDx, double dDy, double dOriginX, double dOriginY, CharCode nCode, int nBytesCount, Unicode *pUnicode, int nUnicodeLen)
|
|
{
|
|
// Ïðîâåðÿåì, âîçìîæíî òåêñò äîëæåí áûòü íåâèäèìûì
|
|
int nRenderMode = pGState->GetRenderMode();
|
|
if ( nRenderMode == 3 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Îáíîâëÿåì øðèôò, åñëè íàäî
|
|
if ( m_bNeedFontUpdate )
|
|
{
|
|
DoUpdateFont( pGState );
|
|
}
|
|
if ( !m_pFont )
|
|
{
|
|
return;
|
|
}
|
|
|
|
dX -= dOriginX;
|
|
dY -= dOriginY;
|
|
|
|
// Fill
|
|
if ( !( nRenderMode & 1 ) )
|
|
{
|
|
if ( !pGState->GetFillColorSpace()->IsNonMarking() )
|
|
{
|
|
m_pSImage->FillChar( (double)dX, (double)dY, nCode, m_pFont );
|
|
}
|
|
}
|
|
|
|
// Stroke
|
|
if ( ( nRenderMode & 3 ) == 1 || ( nRenderMode & 3 ) == 2 )
|
|
{
|
|
if ( !pGState->GetStrokeColorSpace()->IsNonMarking() )
|
|
{
|
|
SPath *pPath = NULL;
|
|
if ( ( pPath = m_pFont->GetGlyphPath( nCode ) ) )
|
|
{
|
|
pPath->Offset( (double)dX, (double)dY );
|
|
m_pSImage->Stroke( pPath );
|
|
delete pPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Clip
|
|
if ( nRenderMode & 4 )
|
|
{
|
|
SPath *pPath = NULL;
|
|
if ( ( pPath = m_pFont->GetGlyphPath( nCode ) ) )
|
|
{
|
|
pPath->Offset( (double)dX, (double)dY );
|
|
if ( m_pTextClipPath )
|
|
{
|
|
m_pTextClipPath->Append( pPath );
|
|
delete pPath;
|
|
}
|
|
else
|
|
{
|
|
m_pTextClipPath = pPath;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL SImageOutputDev::BeginType3Char(GrState *pGState, double dX, double dY, double dDx, double dDy, CharCode nCode, Unicode *pUnicode, int nUnicodeLen)
|
|
{
|
|
T3FontCache *pT3Font = NULL;
|
|
|
|
GrFont *pGFront;
|
|
if ( !( pGFront = pGState->GetFont() ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
Ref *pFontID = pGFront->GetID();
|
|
double *pCTM = pGState->GetCTM();
|
|
double dTransX, dTransY;
|
|
pGState->Transform(0, 0, &dTransX, &dTransY);
|
|
|
|
// Ïðîâåðÿåì ïåðâûé ëè ýòî øðèôò èç êýøà(MRU MostRecentUsed)?
|
|
if ( !( m_nT3FontsCount > 0 && m_pT3FontCache[0]->Matches( pFontID, pCTM[0], pCTM[1], pCTM[2], pCTM[3] ) ) )
|
|
{
|
|
// Ïðîâåðÿåì îñòàâøèåñÿ ôîíòû â êýøå?
|
|
int nFontIndex;
|
|
for ( nFontIndex = 1; nFontIndex < m_nT3FontsCount; ++nFontIndex )
|
|
{
|
|
if ( m_pT3FontCache[nFontIndex]->Matches( pFontID, pCTM[0], pCTM[1], pCTM[2], pCTM[3] ) )
|
|
{
|
|
pT3Font = m_pT3FontCache[nFontIndex];
|
|
for ( int nJ = nFontIndex; nJ > 0; --nJ )
|
|
{
|
|
m_pT3FontCache[nJ] = m_pT3FontCache[nJ - 1];
|
|
}
|
|
m_pT3FontCache[0] = pT3Font;
|
|
break;
|
|
}
|
|
}
|
|
if ( nFontIndex >= m_nT3FontsCount )
|
|
{
|
|
// Ñîçäàåì íîâóþ çàïèñü â êýøå
|
|
BOOL bValidBBox = FALSE;
|
|
double dMinX, dMinY, dMaxX, dMaxY;
|
|
if ( m_nT3FontsCount == T3FontCacheSize )
|
|
{
|
|
delete m_pT3FontCache[m_nT3FontsCount - 1];
|
|
--m_nT3FontsCount;
|
|
}
|
|
for ( int nJ = m_nT3FontsCount; nJ > 0; --nJ )
|
|
{
|
|
m_pT3FontCache[nJ] = m_pT3FontCache[nJ - 1];
|
|
}
|
|
++m_nT3FontsCount;
|
|
double *pBBox = pGFront->GetFontBBox();
|
|
if ( pBBox[0] == 0 && pBBox[1] == 0 && pBBox[2] == 0 && pBBox[3] == 0 )
|
|
{
|
|
// BBox íåîïðåäåëåí, ïûòàåìñÿ óãàäàòü åãî :)
|
|
dMinX = dTransX - 5;
|
|
dMaxX = dMinX + 30;
|
|
dMaxY = dTransY + 15;
|
|
dMinY = dMaxY - 45;
|
|
bValidBBox = FALSE;
|
|
}
|
|
else
|
|
{
|
|
double dX1, dY1;
|
|
pGState->Transform( pBBox[0], pBBox[1], &dX1, &dY1);
|
|
dMinX = dMaxX = dX1;
|
|
dMinY = dMaxY = dY1;
|
|
pGState->Transform( pBBox[0], pBBox[3], &dX1, &dY1);
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
pGState->Transform( pBBox[2], pBBox[1], &dX1, &dY1 );
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
pGState->Transform( pBBox[2], pBBox[3], &dX1, &dY1 );
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
bValidBBox = TRUE;
|
|
}
|
|
m_pT3FontCache[0] = new T3FontCache( pFontID, pCTM[0], pCTM[1], pCTM[2], pCTM[3], (int)floor(dMinX - dTransX), (int)floor(dMinY - dTransY), (int)ceil(dMaxX) - (int)floor(dMinX) + 3, (int)ceil(dMaxY) - (int)floor(dMinY) + 3, bValidBBox, m_eColorMode != colorModeMono1 );
|
|
}
|
|
}
|
|
pT3Font = m_pT3FontCache[0];
|
|
|
|
// Ïðîâåðÿåì, âîçìîæíî äàííûé ñèìâîë óæå åñòü â êýøå.
|
|
int nSetIndex = (nCode & (pT3Font->m_nCacheSets - 1)) * pT3Font->m_nCacheAssoc;
|
|
for ( int nGlyphIndex = 0; nGlyphIndex < pT3Font->m_nCacheAssoc; ++nGlyphIndex )
|
|
{
|
|
if ( ( pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unMRU & 0x8000 ) && pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unCode == nCode )
|
|
{
|
|
DrawType3Glyph( pT3Font, &pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex], pT3Font->m_pCacheData + (nSetIndex + nGlyphIndex) * pT3Font->m_nGlyphSize );
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Äîáàâëÿåì íîâûé Type3-ñèìâîë â ñòåê
|
|
T3GlyphStack *pT3GlyphStack = new T3GlyphStack();
|
|
pT3GlyphStack->pNext = m_pT3GlyphStack;
|
|
m_pT3GlyphStack = pT3GlyphStack;
|
|
m_pT3GlyphStack->unCode = nCode;
|
|
m_pT3GlyphStack->pCache = pT3Font;
|
|
m_pT3GlyphStack->pCacheTag = NULL;
|
|
m_pT3GlyphStack->pCacheData = NULL;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void SImageOutputDev::EndType3Char(GrState *pGState)
|
|
{
|
|
if ( m_pT3GlyphStack->pCacheTag )
|
|
{
|
|
memcpy( m_pT3GlyphStack->pCacheData, m_pBitmap->GetData(), m_pT3GlyphStack->pCache->m_nGlyphSize );
|
|
delete m_pBitmap;
|
|
delete m_pSImage;
|
|
m_pBitmap = m_pT3GlyphStack->pOriginalBitmap;
|
|
m_pSImage = m_pT3GlyphStack->pOriginalSImage;
|
|
double *pCTM = pGState->GetCTM();
|
|
pGState->SetCTM( pCTM[0], pCTM[1], pCTM[2], pCTM[3], m_pT3GlyphStack->dOriginalCTM4, m_pT3GlyphStack->dOriginalCTM5 );
|
|
UpdateCTM( pGState, 0, 0, 0, 0, 0, 0 );
|
|
DrawType3Glyph( m_pT3GlyphStack->pCache, m_pT3GlyphStack->pCacheTag, m_pT3GlyphStack->pCacheData );
|
|
}
|
|
T3GlyphStack *pT3GlyphStack = m_pT3GlyphStack;
|
|
m_pT3GlyphStack = pT3GlyphStack->pNext;
|
|
delete pT3GlyphStack;
|
|
}
|
|
|
|
void SImageOutputDev::Type3D0(GrState *pGState, double dWx, double dWy)
|
|
{
|
|
}
|
|
|
|
void SImageOutputDev::Type3D1(GrState *pGState, double dWx, double dWy, double dBLx, double dBLy, double dTRx, double dTRy)
|
|
{
|
|
T3FontCache *pT3Font = m_pT3GlyphStack->pCache;
|
|
|
|
// Ïðîâåðÿåì êîððåêòíîñòü BBox
|
|
double dTransX, dTransY;
|
|
pGState->Transform( 0, 0, &dTransX, &dTransY );
|
|
double dX1, dY1;
|
|
pGState->Transform( dBLx, dBLy, &dX1, &dY1 );
|
|
double dMinX = dX1, dMaxX = dX1, dMinY = dY1, dMaxY = dY1;
|
|
pGState->Transform( dBLx, dTRy, &dX1, &dY1);
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
pGState->Transform( dTRx, dBLy, &dX1, &dY1);
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
pGState->Transform( dTRx, dTRy, &dX1, &dY1 );
|
|
if ( dX1 < dMinX )
|
|
{
|
|
dMinX = dX1;
|
|
}
|
|
else if ( dX1 > dMaxX )
|
|
{
|
|
dMaxX = dX1;
|
|
}
|
|
if ( dY1 < dMinY )
|
|
{
|
|
dMinY = dY1;
|
|
}
|
|
else if ( dY1 > dMaxY )
|
|
{
|
|
dMaxY = dY1;
|
|
}
|
|
if ( dMinX - dTransX < pT3Font->m_nGlyphX || dMinY - dTransY < pT3Font->m_nGlyphY || dMaxX - dTransX > pT3Font->m_nGlyphX + pT3Font->m_nGlyphWidth || dMaxY - dTransY > pT3Font->m_nGlyphY + pT3Font->m_nGlyphHeight )
|
|
{
|
|
if ( pT3Font->m_bValidBBox )
|
|
{
|
|
// TO DO: Error "Bad bounding box in Type 3 glyph"
|
|
}
|
|
return;
|
|
}
|
|
|
|
int nSetIndex = ( m_pT3GlyphStack->unCode & (pT3Font->m_nCacheSets - 1)) * pT3Font->m_nCacheAssoc;
|
|
for ( int nGlyphIndex = 0; nGlyphIndex < pT3Font->m_nCacheAssoc; ++nGlyphIndex )
|
|
{
|
|
if ( (pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unMRU & 0x7fff) == pT3Font->m_nCacheAssoc - 1 )
|
|
{
|
|
pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unMRU = 0x8000;
|
|
pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unCode = m_pT3GlyphStack->unCode;
|
|
m_pT3GlyphStack->pCacheTag = &pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex];
|
|
m_pT3GlyphStack->pCacheData = pT3Font->m_pCacheData + (nSetIndex + nGlyphIndex) * pT3Font->m_nGlyphSize;
|
|
}
|
|
else
|
|
{
|
|
++pT3Font->m_pCacheTags[nSetIndex + nGlyphIndex].unMRU;
|
|
}
|
|
}
|
|
|
|
// Ñîõðàíÿåì ñîñòîÿíèå
|
|
m_pT3GlyphStack->pOriginalBitmap = m_pBitmap;
|
|
m_pT3GlyphStack->pOriginalSImage = m_pSImage;
|
|
double *pCTM = pGState->GetCTM();
|
|
m_pT3GlyphStack->dOriginalCTM4 = pCTM[4];
|
|
m_pT3GlyphStack->dOriginalCTM5 = pCTM[5];
|
|
|
|
// Ñîçäàåì âðåìåííûé áèòìàï
|
|
SColor pColor;
|
|
if ( m_eColorMode == colorModeMono1 )
|
|
{
|
|
m_pBitmap = new SBitmap( pT3Font->m_nGlyphWidth, pT3Font->m_nGlyphHeight, 1, colorModeMono1, FALSE );
|
|
m_pSImage = new SImage ( m_pBitmap, FALSE, m_pT3GlyphStack->pOriginalSImage->GetScreen() );
|
|
pColor[0] = 0;
|
|
m_pSImage->Clear( pColor );
|
|
pColor[0] = 1;
|
|
}
|
|
else
|
|
{
|
|
m_pBitmap = new SBitmap( pT3Font->m_nGlyphWidth, pT3Font->m_nGlyphHeight, 1, colorModeMono8, FALSE );
|
|
m_pSImage = new SImage ( m_pBitmap, m_bVectorAA, m_pT3GlyphStack->pOriginalSImage->GetScreen() );
|
|
pColor[0] = 0x00;
|
|
m_pSImage->Clear( pColor );
|
|
pColor[0] = 0xff;
|
|
}
|
|
m_pSImage->SetFillPattern( new SSolidColor( pColor ) );
|
|
m_pSImage->SetStrokePattern( new SSolidColor( pColor ) );
|
|
|
|
pGState->SetCTM( pCTM[0], pCTM[1], pCTM[2], pCTM[3], -pT3Font->m_nGlyphX, -pT3Font->m_nGlyphY );
|
|
UpdateCTM( pGState, 0, 0, 0, 0, 0, 0 );
|
|
}
|
|
|
|
void SImageOutputDev::DrawType3Glyph(T3FontCache *pT3Font, T3FontCacheTag *pT3Tag, unsigned char *pData)
|
|
{
|
|
SGlyphBitmap oGlyphBitmap;
|
|
|
|
oGlyphBitmap.nX = -pT3Font->m_nGlyphX;
|
|
oGlyphBitmap.nY = -pT3Font->m_nGlyphY;
|
|
oGlyphBitmap.nWidth = pT3Font->m_nGlyphWidth;
|
|
oGlyphBitmap.nHeight = pT3Font->m_nGlyphHeight;
|
|
oGlyphBitmap.bAA = m_eColorMode != colorModeMono1;
|
|
oGlyphBitmap.pData = pData;
|
|
oGlyphBitmap.bFreeData = FALSE;
|
|
|
|
m_pSImage->FillGlyph( 0, 0, &oGlyphBitmap );
|
|
}
|
|
|
|
void SImageOutputDev::EndTextObject(GrState *pGState)
|
|
{
|
|
if ( m_pTextClipPath )
|
|
{
|
|
m_pSImage->ClipToPath( m_pTextClipPath, FALSE );
|
|
delete m_pTextClipPath;
|
|
m_pTextClipPath = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL SImageOutputDev::ImageMaskSrc(void *pData, SColorPointer pLine)
|
|
{
|
|
ImageMaskData *pImageMaskData = (ImageMaskData *)pData;
|
|
|
|
if ( pImageMaskData->nY == pImageMaskData->nHeight )
|
|
{
|
|
return FALSE;
|
|
}
|
|
int nX;
|
|
unsigned char *pMask;
|
|
SColorPointer pImageMask;
|
|
for ( nX = 0, pMask = pImageMaskData->pImageStream->GetNextLine(), pImageMask = pLine; nX < pImageMaskData->nWidth; ++nX )
|
|
{
|
|
*pImageMask++ = *pMask++ ^ pImageMaskData->bInvert;
|
|
}
|
|
++pImageMaskData->nY;
|
|
return TRUE;
|
|
}
|
|
|
|
void SImageOutputDev::DrawImageMask(GrState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, BOOL bInvert, BOOL bInlineImage)
|
|
{
|
|
if ( pGState->GetFillColorSpace()->IsNonMarking() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
double arrMatrix[6];
|
|
double *pCTM = pGState->GetCTM();
|
|
arrMatrix[0] = pCTM[0];
|
|
arrMatrix[1] = pCTM[1];
|
|
arrMatrix[2] = -pCTM[2];
|
|
arrMatrix[3] = -pCTM[3];
|
|
arrMatrix[4] = pCTM[2] + pCTM[4];
|
|
arrMatrix[5] = pCTM[3] + pCTM[5];
|
|
|
|
ImageMaskData oImageMaskData;
|
|
oImageMaskData.pImageStream = new ImageStream( pStream, nWidth, 1, 1 );
|
|
oImageMaskData.pImageStream->Reset();
|
|
oImageMaskData.bInvert = bInvert ? 0 : 1;
|
|
oImageMaskData.nWidth = nWidth;
|
|
oImageMaskData.nHeight = nHeight;
|
|
oImageMaskData.nY = 0;
|
|
|
|
m_pSImage->FillImageMask( &ImageMaskSrc, &oImageMaskData, nWidth, nHeight, arrMatrix, m_pT3GlyphStack != NULL );
|
|
if ( bInlineImage )
|
|
{
|
|
while ( oImageMaskData.nY < nHeight )
|
|
{
|
|
oImageMaskData.pImageStream->GetNextLine();
|
|
++oImageMaskData.nY;
|
|
}
|
|
}
|
|
|
|
delete oImageMaskData.pImageStream;
|
|
pStream->Close();
|
|
}
|
|
|
|
BOOL SImageOutputDev::ImageSrc(void *pData, SColorPointer pColorLine, unsigned char *pAlphaLine)
|
|
{
|
|
ImageData *pImageData = (ImageData *)pData;
|
|
if ( pImageData->nY == pImageData->nHeight )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int nComponentsCount = pImageData->pColorMap->GetComponentsCount();
|
|
|
|
int nX;
|
|
unsigned char *pSrc;
|
|
SColorPointer pRes, col;
|
|
if ( pImageData->pLookup )
|
|
{
|
|
switch (pImageData->eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
for ( nX = 0, pSrc = pImageData->pStream->GetNextLine(), pRes = pColorLine; nX < pImageData->nWidth; ++nX, ++pSrc )
|
|
{
|
|
*pRes++ = pImageData->pLookup[*pSrc];
|
|
}
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
for ( nX = 0, pSrc = pImageData->pStream->GetNextLine(), pRes = pColorLine; nX < pImageData->nWidth; ++nX, ++pSrc )
|
|
{
|
|
col = &pImageData->pLookup[3 * *pSrc];
|
|
*pRes++ = col[0];
|
|
*pRes++ = col[1];
|
|
*pRes++ = col[2];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (pImageData->eColorMode)
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
for ( nX = 0, pSrc = pImageData->pStream->GetNextLine(), pRes = pColorLine; nX < pImageData->nWidth; ++nX, pSrc += nComponentsCount )
|
|
{
|
|
GrGray oGray;
|
|
pImageData->pColorMap->GetGray( pSrc, &oGray );
|
|
*pRes++ = ColorToByte( oGray );
|
|
}
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
for ( nX = 0, pSrc = pImageData->pStream->GetNextLine(), pRes = pColorLine; nX < pImageData->nWidth; ++nX, pSrc += nComponentsCount )
|
|
{
|
|
GrRGB oRGB;
|
|
pImageData->pColorMap->GetRGB( pSrc, &oRGB );
|
|
*pRes++ = ColorToByte( oRGB.r );
|
|
*pRes++ = ColorToByte( oRGB.g );
|
|
*pRes++ = ColorToByte( oRGB.b );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
++pImageData->nY;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SImageOutputDev::AlphaImageSrc(void *pData, SColorPointer pColorLine, unsigned char *pAlphaLine)
|
|
{
|
|
ImageData *pImageData = (ImageData *)pData;
|
|
|
|
if ( pImageData->nY == pImageData->nHeight )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int nComponentsCount = pImageData->pColorMap->GetComponentsCount();
|
|
|
|
int nX;
|
|
unsigned char *pSrc, *pAlphaRes;
|
|
SColorPointer pColorRes, pColor;
|
|
for ( nX = 0, pSrc = pImageData->pStream->GetNextLine(), pColorRes = pColorLine, pAlphaRes = pAlphaLine; nX < pImageData->nWidth; ++nX, pSrc += nComponentsCount )
|
|
{
|
|
unsigned char unAlpha = 0;
|
|
for ( int nIndex = 0; nIndex < nComponentsCount; ++nIndex )
|
|
{
|
|
if ( pSrc[nIndex] < pImageData->pMaskColors[2 * nIndex] || pSrc[nIndex] > pImageData->pMaskColors[2 * nIndex + 1] )
|
|
{
|
|
unAlpha = 0xff;
|
|
break;
|
|
}
|
|
}
|
|
|
|
GrGray oGray;
|
|
GrRGB oRGB;
|
|
if ( pImageData->pLookup )
|
|
{
|
|
switch ( pImageData->eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
*pColorRes++ = pImageData->pLookup[*pSrc];
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pColor = &pImageData->pLookup[3 * *pSrc];
|
|
*pColorRes++ = pColor[0];
|
|
*pColorRes++ = pColor[1];
|
|
*pColorRes++ = pColor[2];
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ( pImageData->eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pImageData->pColorMap->GetGray( pSrc, &oGray );
|
|
*pColorRes++ = ColorToByte( oGray );
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pImageData->pColorMap->GetRGB( pSrc, &oRGB );
|
|
*pColorRes++ = ColorToByte( oRGB.r );
|
|
*pColorRes++ = ColorToByte( oRGB.g );
|
|
*pColorRes++ = ColorToByte( oRGB.b );
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
++pImageData->nY;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SImageOutputDev::MaskedImageSrc(void *pData, SColorPointer pColorLine, unsigned char *pAlphaLine)
|
|
{
|
|
MaskedImageData *pImageData = (MaskedImageData *)pData;
|
|
|
|
if ( pImageData->nY == pImageData->nHeight )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int nComponentsCount = pImageData->pColorMap->GetComponentsCount();
|
|
int nX;
|
|
unsigned char *pSrc, *pAlphaRes;
|
|
SColorPointer pColorRes, pColor;
|
|
for ( nX = 0, pSrc = pImageData->pImageStream->GetNextLine(), pColorRes = pColorLine, pAlphaRes = pAlphaLine; nX < pImageData->nWidth; ++nX, pSrc += nComponentsCount )
|
|
{
|
|
SColor pMaskColor;
|
|
pImageData->pMask->GetPixel( nX, pImageData->nY, pMaskColor );
|
|
unsigned char unAlpha = pMaskColor[0] ? 0xff : 0x00;
|
|
|
|
GrGray oGray;
|
|
GrRGB oRGB;
|
|
if ( pImageData->pLookup )
|
|
{
|
|
switch ( pImageData->eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
*pColorRes++ = pImageData->pLookup[*pSrc];
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pColor = &pImageData->pLookup[3 * *pSrc];
|
|
*pColorRes++ = pColor[0];
|
|
*pColorRes++ = pColor[1];
|
|
*pColorRes++ = pColor[2];
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ( pImageData->eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pImageData->pColorMap->GetGray( pSrc, &oGray );
|
|
*pColorRes++ = ColorToByte( oGray );
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pImageData->pColorMap->GetRGB( pSrc, &oRGB );
|
|
*pColorRes++ = ColorToByte( oRGB.r );
|
|
*pColorRes++ = ColorToByte( oRGB.g );
|
|
*pColorRes++ = ColorToByte( oRGB.b );
|
|
*pAlphaRes++ = unAlpha;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
++pImageData->nY;
|
|
return TRUE;
|
|
}
|
|
|
|
void SImageOutputDev::DrawImage(GrState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GrImageColorMap *pColorMap, int *pMaskColors, BOOL bInlineImage)
|
|
{
|
|
double arrMatrix[6];
|
|
double *pCTM = pGState->GetCTM();
|
|
arrMatrix[0] = pCTM[0];
|
|
arrMatrix[1] = pCTM[1];
|
|
arrMatrix[2] = -pCTM[2];
|
|
arrMatrix[3] = -pCTM[3];
|
|
arrMatrix[4] = pCTM[2] + pCTM[4];
|
|
arrMatrix[5] = pCTM[3] + pCTM[5];
|
|
|
|
ImageData oImageData;
|
|
oImageData.pStream = new ImageStream( pStream, nWidth, pColorMap->GetComponentsCount(), pColorMap->GetBitsPerComponent() );
|
|
oImageData.pStream->Reset();
|
|
oImageData.pColorMap = pColorMap;
|
|
oImageData.pMaskColors = pMaskColors;
|
|
oImageData.eColorMode = m_eColorMode;
|
|
oImageData.nWidth = nWidth;
|
|
oImageData.nHeight = nHeight;
|
|
oImageData.nY = 0;
|
|
oImageData.pLookup = NULL;
|
|
|
|
if ( pColorMap->GetComponentsCount() == 1 )
|
|
{
|
|
int nBits = 1 << pColorMap->GetBitsPerComponent();
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc(nBits);
|
|
for ( int nIndex = 0; nIndex < nBits; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrGray oGray;
|
|
pColorMap->GetGray( &unPixel, &oGray );
|
|
oImageData.pLookup[nIndex] = ColorToByte( oGray );
|
|
}
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc(3 * nBits);
|
|
for ( int nIndex = 0; nIndex < nBits; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrRGB oRGB;
|
|
pColorMap->GetRGB( &unPixel, &oRGB );
|
|
oImageData.pLookup[3 * nIndex + 0] = ColorToByte( oRGB.r );
|
|
oImageData.pLookup[3 * nIndex + 1] = ColorToByte( oRGB.g );
|
|
oImageData.pLookup[3 * nIndex + 2] = ColorToByte( oRGB.b );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
SColorMode eSrcMode;
|
|
if ( m_eColorMode == colorModeMono1 )
|
|
{
|
|
eSrcMode = colorModeMono8;
|
|
}
|
|
else
|
|
{
|
|
eSrcMode = m_eColorMode;
|
|
}
|
|
SImageSource pImageSrc = pMaskColors ? &AlphaImageSrc : &ImageSrc;
|
|
m_pSImage->DrawImage( pImageSrc, &oImageData, eSrcMode, pMaskColors ? TRUE : FALSE, nWidth, nHeight, arrMatrix );
|
|
if ( bInlineImage )
|
|
{
|
|
while ( oImageData.nY < nHeight )
|
|
{
|
|
oImageData.pStream->GetNextLine();
|
|
++oImageData.nY;
|
|
}
|
|
}
|
|
|
|
MemUtilsFree( oImageData.pLookup );
|
|
delete oImageData.pStream;
|
|
pStream->Close();
|
|
}
|
|
|
|
void SImageOutputDev::DrawMaskedImage(GrState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GrImageColorMap *pColorMap, Stream *pMaskStream, int nMaskWidth, int nMaskHeight, BOOL bMaskInvert)
|
|
{
|
|
// Åñëè ó ìàêñè ðàçðåøåíèå áîëüøå, ÷åì ó ñàìîãî èçîáðàæåíèÿ, òîãäà èñïîëüçóåì ôóíêöèþ DrawSoftMaskedImage().
|
|
if ( nMaskWidth > nWidth || nMaskHeight > nHeight )
|
|
{
|
|
Object oDecodeLow, oDecodeHigh, oMaskDecode;
|
|
oDecodeLow.InitInt( bMaskInvert ? 0 : 1 );
|
|
oDecodeHigh.InitInt( bMaskInvert ? 1 : 0 );
|
|
oMaskDecode.InitArray( m_pXref );
|
|
oMaskDecode.ArrayAdd( &oDecodeLow );
|
|
oMaskDecode.ArrayAdd( &oDecodeHigh );
|
|
GrImageColorMap *pMaskColorMap = new GrImageColorMap( 1, &oMaskDecode, new GrDeviceGrayColorSpace() );
|
|
oMaskDecode.Free();
|
|
DrawSoftMaskedImage( pGState, pRef, pStream, nWidth, nHeight, pColorMap, pMaskStream, nMaskWidth, nMaskHeight, pMaskColorMap );
|
|
delete pMaskColorMap;
|
|
}
|
|
else
|
|
{
|
|
// Èçìåíÿåì ðàçìåðû ìàêñè äî çðàçìåðîâ èñõîäíîé êàðòèíêè.
|
|
double arrMatrix[6];
|
|
arrMatrix[0] = (double)nWidth;
|
|
arrMatrix[1] = 0;
|
|
arrMatrix[2] = 0;
|
|
arrMatrix[3] = (double)nHeight;
|
|
arrMatrix[4] = 0;
|
|
arrMatrix[5] = 0;
|
|
|
|
ImageMaskData oImageMaskData;
|
|
oImageMaskData.pImageStream = new ImageStream( pMaskStream, nMaskWidth, 1, 1);
|
|
oImageMaskData.pImageStream->Reset();
|
|
oImageMaskData.bInvert = bMaskInvert ? 0 : 1;
|
|
oImageMaskData.nWidth = nMaskWidth;
|
|
oImageMaskData.nHeight = nMaskHeight;
|
|
oImageMaskData.nY = 0;
|
|
|
|
SBitmap *pMaskBitmap = new SBitmap( nWidth, nHeight, 1, colorModeMono1, FALSE);
|
|
SImage *pMaskSImage = new SImage( pMaskBitmap, FALSE );
|
|
SColor pMaskColor;
|
|
pMaskColor[0] = 0;
|
|
pMaskSImage->Clear( pMaskColor );
|
|
pMaskColor[0] = 0xff;
|
|
pMaskSImage->SetFillPattern( new SSolidColor( pMaskColor ) );
|
|
pMaskSImage->FillImageMask( &ImageMaskSrc, &oImageMaskData, nMaskWidth, nMaskHeight, arrMatrix, FALSE );
|
|
delete oImageMaskData.pImageStream;
|
|
pMaskStream->Close();
|
|
delete pMaskSImage;
|
|
|
|
// Ðèñóåì èñõîäíóþ êàðòèíêó
|
|
|
|
double *pCTM = pGState->GetCTM();
|
|
arrMatrix[0] = pCTM[0];
|
|
arrMatrix[1] = pCTM[1];
|
|
arrMatrix[2] = -pCTM[2];
|
|
arrMatrix[3] = -pCTM[3];
|
|
arrMatrix[4] = pCTM[2] + pCTM[4];
|
|
arrMatrix[5] = pCTM[3] + pCTM[5];
|
|
|
|
MaskedImageData oImageData;
|
|
oImageData.pImageStream = new ImageStream( pStream, nWidth, pColorMap->GetComponentsCount(), pColorMap->GetBitsPerComponent() );
|
|
oImageData.pImageStream->Reset();
|
|
oImageData.pColorMap = pColorMap;
|
|
oImageData.pMask = pMaskBitmap;
|
|
oImageData.eColorMode = m_eColorMode;
|
|
oImageData.nWidth = nWidth;
|
|
oImageData.nHeight = nHeight;
|
|
oImageData.nY = 0;
|
|
|
|
// Ñïåöèàëüíûé ñëó÷àé äëÿ îäíîêàíàëüíûõ èçîáðàæåíèé: ñòðîèì òàáëèöó ïîèñêà çäåñü
|
|
oImageData.pLookup = NULL;
|
|
if ( pColorMap->GetComponentsCount() == 1 )
|
|
{
|
|
int nBitsCount = 1 << pColorMap->GetBitsPerComponent();
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc( nBitsCount );
|
|
for ( int nIndex = 0; nIndex < nBitsCount; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrGray oGray;
|
|
pColorMap->GetGray( &unPixel, &oGray );
|
|
oImageData.pLookup[nIndex] = ColorToByte( oGray );
|
|
}
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc(3 * nBitsCount);
|
|
for ( int nIndex = 0; nIndex < nBitsCount; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrRGB oRGB;
|
|
pColorMap->GetRGB( &unPixel, &oRGB );
|
|
oImageData.pLookup[3 * nIndex + 0] = ColorToByte( oRGB.r );
|
|
oImageData.pLookup[3 * nIndex + 1] = ColorToByte( oRGB.g );
|
|
oImageData.pLookup[3 * nIndex + 2] = ColorToByte( oRGB.b );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
SColorMode eSourceMode;
|
|
if ( m_eColorMode == colorModeMono1 )
|
|
{
|
|
eSourceMode = colorModeMono8;
|
|
}
|
|
else
|
|
{
|
|
eSourceMode = m_eColorMode;
|
|
}
|
|
m_pSImage->DrawImage( &MaskedImageSrc, &oImageData, eSourceMode, TRUE, nWidth, nHeight, arrMatrix );
|
|
|
|
delete pMaskBitmap;
|
|
MemUtilsFree( oImageData.pLookup );
|
|
delete oImageData.pImageStream;
|
|
pStream->Close();
|
|
}
|
|
}
|
|
|
|
void SImageOutputDev::DrawSoftMaskedImage(GrState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GrImageColorMap *pColorMap, Stream *pMaskStream, int nMaskWidth, int nMaskHeight, GrImageColorMap *pMaskColorMap)
|
|
{
|
|
double *pCTM = pGState->GetCTM();
|
|
double arrMatrix[6];
|
|
arrMatrix[0] = pCTM[0];
|
|
arrMatrix[1] = pCTM[1];
|
|
arrMatrix[2] = -pCTM[2];
|
|
arrMatrix[3] = -pCTM[3];
|
|
arrMatrix[4] = pCTM[2] + pCTM[4];
|
|
arrMatrix[5] = pCTM[3] + pCTM[5];
|
|
|
|
ImageData oImageMaskData;
|
|
oImageMaskData.pStream = new ImageStream( pMaskStream, nMaskWidth, pMaskColorMap->GetComponentsCount(), pMaskColorMap->GetBitsPerComponent() );
|
|
oImageMaskData.pStream->Reset();
|
|
oImageMaskData.pColorMap = pMaskColorMap;
|
|
oImageMaskData.pMaskColors = NULL;
|
|
oImageMaskData.eColorMode = colorModeMono8;
|
|
oImageMaskData.nWidth = nMaskWidth;
|
|
oImageMaskData.nHeight = nMaskHeight;
|
|
oImageMaskData.nY = 0;
|
|
|
|
int nBitsCount = 1 << pMaskColorMap->GetBitsPerComponent();
|
|
oImageMaskData.pLookup = (SColorPointer)MemUtilsMalloc(nBitsCount);
|
|
for ( int nIndex = 0; nIndex < nBitsCount; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrGray oGray;
|
|
pMaskColorMap->GetGray( &unPixel, &oGray );
|
|
oImageMaskData.pLookup[nIndex] = ColorToByte( oGray );
|
|
}
|
|
SBitmap *pMaskBitmap = new SBitmap( m_pBitmap->GetWidth(), m_pBitmap->GetHeight(), 1, colorModeMono8, FALSE );
|
|
SImage *pMaskSImage = new SImage( pMaskBitmap, m_bVectorAA );
|
|
SColor pMaskColor;
|
|
pMaskColor[0] = 0;
|
|
pMaskSImage->Clear( pMaskColor );
|
|
pMaskSImage->DrawImage( &ImageSrc, &oImageMaskData, colorModeMono8, FALSE, nMaskWidth, nMaskHeight, arrMatrix );
|
|
delete oImageMaskData.pStream;
|
|
pMaskStream->Close();
|
|
MemUtilsFree( oImageMaskData.pLookup );
|
|
delete pMaskSImage;
|
|
m_pSImage->SetSoftMask( pMaskBitmap );
|
|
|
|
ImageData oImageData;
|
|
oImageData.pStream = new ImageStream( pStream, nWidth, pColorMap->GetComponentsCount(), pColorMap->GetBitsPerComponent() );
|
|
oImageData.pStream->Reset();
|
|
oImageData.pColorMap = pColorMap;
|
|
oImageData.pMaskColors = NULL;
|
|
oImageData.eColorMode = m_eColorMode;
|
|
oImageData.nWidth = nWidth;
|
|
oImageData.nHeight = nHeight;
|
|
oImageData.nY = 0;
|
|
oImageData.pLookup = NULL;
|
|
if ( pColorMap->GetComponentsCount() == 1 )
|
|
{
|
|
nBitsCount = 1 << pColorMap->GetBitsPerComponent();
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc(nBitsCount);
|
|
for ( int nIndex = 0; nIndex < nBitsCount; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrGray oGray;
|
|
pColorMap->GetGray( &unPixel, &oGray );
|
|
oImageData.pLookup[nIndex] = ColorToByte( oGray );
|
|
}
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
oImageData.pLookup = (SColorPointer)MemUtilsMalloc(3 * nBitsCount);
|
|
for ( int nIndex = 0; nIndex < nBitsCount; ++nIndex )
|
|
{
|
|
unsigned char unPixel = (unsigned char)nIndex;
|
|
GrRGB oRGB;
|
|
pColorMap->GetRGB( &unPixel, &oRGB );
|
|
oImageData.pLookup[3 * nIndex + 0] = ColorToByte( oRGB.r );
|
|
oImageData.pLookup[3 * nIndex + 1] = ColorToByte( oRGB.g );
|
|
oImageData.pLookup[3 * nIndex + 2] = ColorToByte( oRGB.b );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
SColorMode eSourceMode;
|
|
if ( m_eColorMode == colorModeMono1 )
|
|
{
|
|
eSourceMode = colorModeMono8;
|
|
}
|
|
else
|
|
{
|
|
eSourceMode = m_eColorMode;
|
|
}
|
|
m_pSImage->DrawImage( &ImageSrc, &oImageData, eSourceMode, FALSE, nWidth, nHeight, arrMatrix );
|
|
|
|
m_pSImage->SetSoftMask(NULL);
|
|
MemUtilsFree( oImageData.pLookup );
|
|
delete oImageData.pStream;
|
|
pStream->Close();
|
|
}
|
|
|
|
void SImageOutputDev::BeginTransparencyGroup(GrState *pGState, double *pBBox, GrColorSpace *pBlendingColorSpace, BOOL bIsolated, BOOL bKnockout, BOOL bForSoftMask)
|
|
{
|
|
double dX, dY;
|
|
pGState->Transform( pBBox[0], pBBox[1], &dX, &dY );
|
|
double dMinX = dX, dMaxX = dX;
|
|
double dMinY = dY, dMaxY = dY;
|
|
pGState->Transform( pBBox[0], pBBox[3], &dX, &dY );
|
|
if ( dX < dMinX )
|
|
{
|
|
dMinX = dX;
|
|
}
|
|
else if ( dX > dMaxX )
|
|
{
|
|
dMaxX = dX;
|
|
}
|
|
if ( dY < dMinY )
|
|
{
|
|
dMinY = dY;
|
|
}
|
|
else if ( dY > dMaxY )
|
|
{
|
|
dMaxY = dY;
|
|
}
|
|
pGState->Transform( pBBox[2], pBBox[1], &dX, &dY );
|
|
if ( dX < dMinX )
|
|
{
|
|
dMinX = dX;
|
|
}
|
|
else if ( dX > dMaxX )
|
|
{
|
|
dMaxX = dX;
|
|
}
|
|
if ( dY < dMinY )
|
|
{
|
|
dMinY = dY;
|
|
}
|
|
else if ( dY > dMaxY )
|
|
{
|
|
dMaxY = dY;
|
|
}
|
|
pGState->Transform( pBBox[2], pBBox[3], &dX, &dY );
|
|
if ( dX < dMinX )
|
|
{
|
|
dMinX = dX;
|
|
}
|
|
else if ( dX > dMaxX )
|
|
{
|
|
dMaxX = dX;
|
|
}
|
|
if ( dY < dMinY )
|
|
{
|
|
dMinY = dY;
|
|
}
|
|
else if ( dY > dMaxY )
|
|
{
|
|
dMaxY = dY;
|
|
}
|
|
int nTransX = (int)floor( dMinX );
|
|
if ( nTransX < 0 )
|
|
{
|
|
nTransX = 0;
|
|
}
|
|
else if ( nTransX > m_pBitmap->GetWidth() )
|
|
{
|
|
nTransX = m_pBitmap->GetWidth();
|
|
}
|
|
int nTransY = (int)floor( dMinY );
|
|
if ( nTransY < 0 )
|
|
{
|
|
nTransY = 0;
|
|
}
|
|
else if ( nTransY > m_pBitmap->GetHeight() )
|
|
{
|
|
nTransY = m_pBitmap->GetHeight();
|
|
}
|
|
int nWidth = (int)ceil( dMaxX ) - nTransX + 1;
|
|
if ( nTransX + nWidth > m_pBitmap->GetWidth() )
|
|
{
|
|
nWidth = m_pBitmap->GetWidth() - nTransX;
|
|
}
|
|
if ( nWidth < 1 )
|
|
{
|
|
nWidth = 1;
|
|
}
|
|
int nHeight = (int)ceil( dMaxY ) - nTransY + 1;
|
|
if ( nTransY + nHeight > m_pBitmap->GetHeight() )
|
|
{
|
|
nHeight = m_pBitmap->GetHeight() - nTransY;
|
|
}
|
|
if ( nHeight < 1 )
|
|
{
|
|
nHeight = 1;
|
|
}
|
|
|
|
// Ñîçäàåì íîâûé ýëåìåíò â ñòåêå
|
|
TransparencyGroup *pTranspGroup;
|
|
pTranspGroup = new TransparencyGroup();
|
|
pTranspGroup->nTransX = nTransX;
|
|
pTranspGroup->nTransY = nTransY;
|
|
pTranspGroup->pBlendColorSpace = pBlendingColorSpace;
|
|
pTranspGroup->bIsolated = bIsolated;
|
|
pTranspGroup->pNext = m_pTranspGroupStack;
|
|
m_pTranspGroupStack = pTranspGroup;
|
|
|
|
// Ñîõðàíÿåì ñîñòîÿíèå
|
|
pTranspGroup->pOriginalBitmap = m_pBitmap;
|
|
pTranspGroup->pOriginalSImage = m_pSImage;
|
|
|
|
m_pBitmap = new SBitmap( nWidth, nHeight, m_nBitmapRowPad, m_eColorMode, TRUE, m_bBitmapTopDown );
|
|
m_pSImage = new SImage( m_pBitmap, m_bVectorAA, pTranspGroup->pOriginalSImage->GetScreen() );
|
|
if ( bIsolated )
|
|
{
|
|
SColor pColor;
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
pColor[0] = 0;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
pColor[0] = pColor[1] = pColor[2] = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
m_pSImage->Clear( pColor, 0 );
|
|
}
|
|
else
|
|
{
|
|
m_pSImage->BlitTransparent( pTranspGroup->pOriginalBitmap, nTransX, nTransY, 0, 0, nWidth, nHeight );
|
|
m_pSImage->SetInNonIsolatedGroup( pTranspGroup->pOriginalBitmap, nTransX, nTransY );
|
|
}
|
|
pTranspGroup->pBitmap = m_pBitmap;
|
|
pGState->ShiftCTM( -nTransX, -nTransY );
|
|
UpdateCTM( pGState, 0, 0, 0, 0, 0, 0 );
|
|
}
|
|
|
|
void SImageOutputDev::EndTransparencyGroup(GrState *pGState)
|
|
{
|
|
// Âîññòàíàâëèâàåì ïðåäûäóùåå ñîñòîÿíèå
|
|
delete m_pSImage;
|
|
m_pBitmap = m_pTranspGroupStack->pOriginalBitmap;
|
|
m_pSImage = m_pTranspGroupStack->pOriginalSImage;
|
|
double *pCTM = pGState->GetCTM();
|
|
pGState->ShiftCTM( m_pTranspGroupStack->nTransX, m_pTranspGroupStack->nTransY );
|
|
UpdateCTM( pGState, 0, 0, 0, 0, 0, 0 );
|
|
}
|
|
|
|
void SImageOutputDev::PaintTransparencyGroup(GrState *pGState, double *pBBox)
|
|
{
|
|
int nTransX = m_pTranspGroupStack->nTransX;
|
|
int nTransY = m_pTranspGroupStack->nTransY;
|
|
SBitmap *pTempBitmap = m_pTranspGroupStack->pBitmap;
|
|
BOOL bIsolated = m_pTranspGroupStack->bIsolated;
|
|
|
|
m_pSImage->Composite( pTempBitmap, 0, 0, nTransX, nTransY, pTempBitmap->GetWidth(), pTempBitmap->GetHeight(), FALSE, !bIsolated );
|
|
|
|
// Óäàëÿåì ýëåìåíò èç ñòåêà
|
|
TransparencyGroup *pTranspGroup = m_pTranspGroupStack;
|
|
m_pTranspGroupStack = pTranspGroup->pNext;
|
|
delete pTranspGroup;
|
|
delete pTempBitmap;
|
|
}
|
|
|
|
void SImageOutputDev::SetSoftMask(GrState *pGState, double *pBBox, BOOL bAlpha, Function *pTransferFunc, GrColor *pBackdropColor)
|
|
{
|
|
int nTransX = m_pTranspGroupStack->nTransX;
|
|
int nTransY = m_pTranspGroupStack->nTransY;
|
|
SBitmap *pTBitmap = m_pTranspGroupStack->pBitmap;
|
|
|
|
// Ñîâìåùàåì ñ ïîäêëàäêîé (pBackdropColor)
|
|
if ( !bAlpha && m_eColorMode != colorModeMono1 )
|
|
{
|
|
SImage *pTSImage = new SImage( pTBitmap, m_bVectorAA, m_pTranspGroupStack->pOriginalSImage->GetScreen() );
|
|
SColor pColor;
|
|
if ( m_pTranspGroupStack->pBlendColorSpace )
|
|
{
|
|
GrGray oGray;
|
|
GrRGB oRGB;
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
// Ïðîçðà÷íîñòü íå ïîääåðæèâàåòñÿ â ñëó÷àå Mono1
|
|
break;
|
|
case colorModeMono8:
|
|
m_pTranspGroupStack->pBlendColorSpace->GetGray( pBackdropColor, &oGray );
|
|
pColor[0] = ColorToByte( oGray );
|
|
pTSImage->CompositeBackground( pColor );
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
m_pTranspGroupStack->pBlendColorSpace->GetRGB( pBackdropColor, &oRGB );
|
|
pColor[0] = ColorToByte( oRGB.r );
|
|
pColor[1] = ColorToByte( oRGB.g );
|
|
pColor[2] = ColorToByte( oRGB.b );
|
|
pTSImage->CompositeBackground( pColor );
|
|
break;
|
|
}
|
|
delete pTSImage;
|
|
}
|
|
}
|
|
|
|
SBitmap *pSoftMask = new SBitmap( m_pBitmap->GetWidth(), m_pBitmap->GetHeight(), 1, colorModeMono8, FALSE );
|
|
memset( pSoftMask->GetData(), 0, pSoftMask->GetStride() * pSoftMask->GetHeight() );
|
|
SColorPointer pLine = pSoftMask->GetData() + nTransY * pSoftMask->GetStride() + nTransX;
|
|
for ( int nY = 0; nY < pTBitmap->GetHeight(); ++nY )
|
|
{
|
|
for ( int nX = 0; nX < pTBitmap->GetWidth(); ++nX )
|
|
{
|
|
SColor pColor;
|
|
pTBitmap->GetPixel( nX, nY, pColor );
|
|
if ( bAlpha )
|
|
{
|
|
// Ïîêà íå ïîääåðæèâàåòñÿ
|
|
}
|
|
else
|
|
{
|
|
double dLuminosity, dLuminosity2;
|
|
switch ( m_eColorMode )
|
|
{
|
|
case colorModeMono1:
|
|
case colorModeMono8:
|
|
dLuminosity = pColor[0] / 255.0;
|
|
break;
|
|
case colorModeRGB8:
|
|
case colorModeBGR8:
|
|
dLuminosity = (0.3 / 255.0) * pColor[0] + (0.59 / 255.0) * pColor[1] + (0.11 / 255.0) * pColor[2];
|
|
break;
|
|
}
|
|
if ( pTransferFunc )
|
|
{
|
|
pTransferFunc->Transform( &dLuminosity, &dLuminosity2 );
|
|
}
|
|
else
|
|
{
|
|
dLuminosity2 = dLuminosity;
|
|
}
|
|
pLine[nX] = (int)(dLuminosity2 * 255.0 + 0.5);
|
|
}
|
|
}
|
|
pLine += pSoftMask->GetStride();
|
|
}
|
|
m_pSImage->SetSoftMask( pSoftMask );
|
|
|
|
// Óäàëÿåì ýëåìåíò èç ñòåêà
|
|
TransparencyGroup *pTranspGroup = m_pTranspGroupStack;
|
|
m_pTranspGroupStack = pTranspGroup->pNext;
|
|
delete pTranspGroup;
|
|
|
|
delete pTBitmap;
|
|
}
|
|
|
|
void SImageOutputDev::ClearSoftMask(GrState *pGState)
|
|
{
|
|
m_pSImage->SetSoftMask(NULL);
|
|
}
|
|
|
|
void SImageOutputDev::SetPaperColor(SColorPointer pPaperColor)
|
|
{
|
|
ColorCopy( m_pPaperColor, pPaperColor );
|
|
}
|
|
|
|
int SImageOutputDev::GetBitmapWidth()
|
|
{
|
|
return m_pBitmap->GetWidth();
|
|
}
|
|
|
|
int SImageOutputDev::GetBitmapHeight()
|
|
{
|
|
return m_pBitmap->GetHeight();
|
|
}
|
|
|
|
SBitmap *SImageOutputDev::TakeBitmap()
|
|
{
|
|
SBitmap *m_pRet = m_pBitmap;
|
|
m_pBitmap = new SBitmap( 1, 1, m_nBitmapRowPad, m_eColorMode, m_eColorMode != colorModeMono1, m_bBitmapTopDown );
|
|
return m_pRet;
|
|
}
|
|
|
|
void SImageOutputDev::GetModRegion(int *pnMinX, int *pnMinY, int *pnMaxX, int *pnMaxY)
|
|
{
|
|
m_pSImage->GetModRegion( pnMinX, pnMinY, pnMaxX, pnMaxY );
|
|
}
|
|
|
|
void SImageOutputDev::ClearModRegion()
|
|
{
|
|
m_pSImage->ClearModRegion();
|
|
}
|
|
|
|
void SImageOutputDev::SetFillColor(int nR, int nG, int nB)
|
|
{
|
|
GrRGB oRGB;
|
|
GrGray oGray;
|
|
|
|
oRGB.r = ByteToColor( nR );
|
|
oRGB.g = ByteToColor( nG );
|
|
oRGB.b = ByteToColor( nB );
|
|
oGray = (GrColorComp)(0.299 * oRGB.r + 0.587 * oRGB.g + 0.114 * oRGB.g + 0.5);
|
|
if ( oGray > GrColorComp1 )
|
|
{
|
|
oGray = GrColorComp1;
|
|
}
|
|
m_pSImage->SetFillPattern( GetColor( oGray, &oRGB ) );
|
|
}
|
|
|
|
SFont *SImageOutputDev::GetFont(StringExt *seName, double *pTextMatrix)
|
|
{
|
|
int nIndex;
|
|
for ( nIndex = 0; nIndex < 16; ++nIndex )
|
|
{
|
|
if ( !seName->Compare( c_arrSImageOutSubstFonts[nIndex].sName ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( nIndex == 16 )
|
|
{
|
|
return NULL;
|
|
}
|
|
Ref oRef;
|
|
oRef.nNum = nIndex;
|
|
oRef.nGen = -1;
|
|
SImageOutFontFileID *pID = new SImageOutFontFileID( &oRef );
|
|
|
|
// Ñíà÷àëà èùåì â êýøå
|
|
SFontFile *pFontFile = NULL;
|
|
if ( ( pFontFile = m_pFontEngine->GetFontFile( pID ) ) )
|
|
{
|
|
delete pID;
|
|
}
|
|
else
|
|
{
|
|
DisplayFontParam *pDisplayFontParam = NULL;
|
|
if ( m_pGlobalParams )
|
|
{
|
|
pDisplayFontParam = m_pGlobalParams->GetDisplayFont( seName );
|
|
}
|
|
if ( pDisplayFontParam && pDisplayFontParam->m_eType == displayFontT1 )
|
|
{
|
|
pFontFile = m_pFontEngine->LoadType1Font( pID, pDisplayFontParam->m_oT1.pwsFileName->GetBuffer(), FALSE, c_arrWinAnsiEncoding );
|
|
}
|
|
else if ( pDisplayFontParam && pDisplayFontParam->m_eType == displayFontTT )
|
|
{
|
|
CFontFileTrueType *pTTFontFile = NULL;
|
|
if ( !( pTTFontFile = CFontFileTrueType::LoadFromFile( pDisplayFontParam->m_oTT.pwsFileName->GetBuffer() ) ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
int nCMapIndex;
|
|
for ( nCMapIndex = 0; nCMapIndex < pTTFontFile->GetCmapsCount(); ++nCMapIndex )
|
|
{
|
|
if ( ( pTTFontFile->GetCmapPlatform( nCMapIndex ) == 3 && pTTFontFile->GetCmapEncoding( nCMapIndex ) == 1) || pTTFontFile->GetCmapPlatform( nCMapIndex ) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( nCMapIndex == pTTFontFile->GetCmapsCount() )
|
|
{
|
|
delete pTTFontFile;
|
|
return NULL;
|
|
}
|
|
unsigned short *pCodeToGID = (unsigned short *)MemUtilsMallocArray( 256, sizeof(unsigned short) );
|
|
for ( nIndex = 0; nIndex < 256; ++nIndex )
|
|
{
|
|
pCodeToGID[nIndex] = 0;
|
|
Unicode nUnicode;
|
|
if ( c_arrWinAnsiEncoding[nIndex] && m_pGlobalParams && ( nUnicode = m_pGlobalParams->MapNameToUnicode(c_arrWinAnsiEncoding[nIndex] ) ) )
|
|
{
|
|
pCodeToGID[nIndex] = pTTFontFile->MapCodeToGID( nCMapIndex, nUnicode );
|
|
}
|
|
}
|
|
delete pTTFontFile;
|
|
pFontFile = m_pFontEngine->LoadTrueTypeFont( pID, pDisplayFontParam->m_oTT.pwsFileName->GetBuffer(), FALSE, pCodeToGID, 256, m_pGlobalParams->GetTempFolder() );
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
double arrTextMatrix[4];
|
|
arrTextMatrix[0] = (double)pTextMatrix[0];
|
|
arrTextMatrix[1] = (double)pTextMatrix[1];
|
|
arrTextMatrix[2] = (double)pTextMatrix[2];
|
|
arrTextMatrix[3] = (double)pTextMatrix[3];
|
|
SFont *pFontObject = m_pFontEngine->GetFont( pFontFile, arrTextMatrix, m_pSImage->GetMatrix() );
|
|
|
|
return pFontObject;
|
|
}
|
|
|
|
BOOL SImageOutputDev::GetVectorAntialias()
|
|
{
|
|
return m_pSImage->GetVectorAA();
|
|
}
|
|
|
|
void SImageOutputDev::SetVectorAntialias(BOOL vaa)
|
|
{
|
|
m_pSImage->SetVectorAA(vaa);
|
|
}
|