Files
core/ASCImageStudio3/ASCGraphics/Objects/ASCGraphics.h

2923 lines
80 KiB
C++

// ASCGraphicsPath.h : Declaration of the AVSGraphicsPath
#pragma once
#include "stdafx.h"
#include "resource.h" // main symbols
#include "Registration.h"
#include "..\Interfaces\IASCGraphics.h"
#include "ASCMatrix.h"
#include "ASCGraphicsPath.h"
#include "ASCSolidPattern.h"
#include "ASCGlyphImage.h"
#include "..\VectorGraphics\STypes.h"
#include "..\Common\Clip.h"
#include "..\Common\Pixels.h"
#include "..\VectorGraphics\SScreen.h"
#include "..\VectorGraphics\SErrorCodes.h"
#include "..\VectorGraphics\SXPath.h"
#include "..\VectorGraphics\SXPathScanner.h"
#include "..\VectorGraphics\SMathExt.h"
#include "ASCFontManager.h"
#include "TimeMeasurer.h"
// Ðàññòîÿíèå îò öåíòðà äî êîíòðîëüíûõ òî÷åê Áåçüå äëÿ àïïðîêñèìàöèè îêðóæíîñòè = (4 * (sqrt(2) - 1) / 3) * r
static const double c_dKappa = ((double)0.55228475);
static const double c_dKappa_2 = ((double)(0.5 * 0.55228475));
// Äåëèì 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;
}
}
// CAVSGraphicsPath
[coclass, uuid("C79DCE54-5676-4d95-9C36-2A136C5D0592"), threading(apartment), vi_progid("AVSGraphics.Graphics"), progid("AVSGraphics.Graphics"), version(1.0), support_error_info(IAVSGraphics), registration_script("control.rgs")]
class ATL_NO_VTABLE CAVSGraphics
: public IAVSGraphics
{
protected:
double m_dWidthPix;
double m_dHeightPix;
double m_dDpiX;
double m_dDpiY;
LONG m_lSmoothMode;
LONG m_lAntialiseMode;
LONG m_lPageUnits;
CPixels m_oPixels;
CPixels m_oAABuffer;
CPixels m_oSoftMask;
int m_nAABufferY;
CPixels m_oAlpha0Bitmap; // Äëÿ Non-isolated ãðóïï, áèòìàï õðàíÿùèé çíà÷åíèÿ àëüôà-êàíàëà
int m_nAlpha0X; //
int m_nAlpha0Y; // Ñäâèã â m_pAlpha0Bitmap
BOOL m_bDeleteSoftMask;
BOOL m_bInNonIsolatedGroup;
Gdiplus::Matrix m_oCoordTransform;
Gdiplus::Matrix m_oBaseTransform;
Gdiplus::Matrix m_oTransform;
CClip m_oClip;
double m_dClipFlatness;
double m_dFlatness;
SBlendFunc m_pBlendFunction;
SScreen m_oScreen;
double m_arrdAAGamma[AntiAliasingSize * AntiAliasingSize + 1];
int m_nModRegMinX; //
int m_nModRegMinY; // Ãðàíèöû ðåãèîíà, â êîòîðîì ïðîèçâîäèëèñü ïîñëåäíèå èçìåíåíèÿ
int m_nModRegMaxX; // (ò.å. èçìåíåíèÿ ïîñëå âûçîâà ôóíêöèè GetModificationRegion())
int m_nModRegMaxY; //
SClipResult m_pOpClipRes; // Ðåçóëüòàò ïîñëåäíåé îïåðàöèè ðèñîâàíèÿ ïî îòíîøåíèþ ê Clipping
BOOL m_bVectorAA;
static SPipeResultColorCtrl m_arrePipeResultColorNoAlphaBlend[];
static SPipeResultColorCtrl m_arrePipeResultColorAlphaNoBlend[];
static SPipeResultColorCtrl m_arrePipeResultColorAlphaBlend[];
static int m_arrnPipeNonIsoGroupCorrection[];
public:
CAVSGraphics() :
m_oClip(), m_oCoordTransform(), m_oBaseTransform(), m_oTransform()
{
m_dWidthPix = 0;
m_dHeightPix = 0;
m_dDpiX = 72.0;
m_dDpiY = 72.0;
m_lSmoothMode = c_ag_SmoothingModeAntiAlias;
m_lAntialiseMode = c_ag_TextRenderingHintAntiAlias;
m_lPageUnits = c_ag_PageUnitPixel;
m_oPixels.m_pPixels = NULL;
m_dClipFlatness = 1.0;
m_dFlatness = 1.0;
m_bVectorAA = TRUE;
m_pBlendFunction = NULL;
}
~CAVSGraphics()
{
}
public:
STDMETHOD(SetAdditionalParam)(BSTR ParamName, VARIANT ParamValue)
{
return S_OK;
}
STDMETHOD(GetAdditionalParam)(BSTR ParamName, VARIANT* ParamValue)
{
return S_OK;
}
STDMETHOD(CreateDublicate)(IAVSGraphicsBase** ppGraphicsBase)
{
if (NULL == ppGraphicsBase)
return S_FALSE;
RELEASEINTERFACE((*ppGraphicsBase));
if (SUCCEEDED(CoCreateInstance(__uuidof(CAVSGraphics), NULL, CLSCTX_INPROC, __uuidof(IAVSGraphicsBase), (void**)ppGraphicsBase)))
{
return S_OK;
}
return S_FALSE;
}
STDMETHOD(Create)(BYTE* pPixels, LONG lWidth, LONG lHeight, LONG lStride, LONG lPitch, LONG lColorSpace)
{
// òóò íàäî íàïèñàòü êëàññ CPixels
m_oPixels.Create(pPixels, lWidth, lHeight, 1, colorModeRGBA8, TRUE, 0, TRUE);
/*m_oPixels.m_pPixels = pPixels;
m_oPixels.m_lLeft = 0;
m_oPixels.m_lTop = 0;
m_oPixels.m_lWidth = lWidth;
m_oPixels.m_lHeight = lHeight;
m_oPixels.m_lPitch = lPitch;
m_oPixels.m_eMode = (SColorMode)lColorSpace;*/
m_dWidthPix = (double)lWidth;
m_dHeightPix = (double)lHeight;
m_oClip.Reset(0, 0, m_dWidthPix, m_dHeightPix, TRUE);
m_pBlendFunction = NULL;
m_dFlatness = 1;
m_oSoftMask.Release();
m_oAlpha0Bitmap.Release();
m_bDeleteSoftMask = FALSE;
m_bInNonIsolatedGroup = FALSE;
if ( m_bVectorAA )
{
m_oAABuffer.Create( NULL, AntiAliasingSize * m_oPixels.m_lWidth, AntiAliasingSize, 1, colorModeMono1, FALSE );
for ( int nIndex = 0; nIndex <= AntiAliasingSize * AntiAliasingSize; ++nIndex )
{
m_arrdAAGamma[nIndex] = pow((double)nIndex / (double)(AntiAliasingSize * AntiAliasingSize), 1.5);
}
}
else
{
m_oAABuffer.Release();
}
ClearModRegion();
UpdateUnits();
return S_OK;
}
STDMETHOD(CreatePart)(LONG lLeft, LONG lTop, LONG lWidth, LONG lHeight, IAVSGraphics** ppPart)
{
// çäåñü ìèíèìóì êîäà. Ïðîñòî ñäåëàòü äóáëèêàò - è âûñòàâèòü åìó ïðàâèëüíûå ãðàíèöû.
// à ïîòîì óæå è dpi è âñå íàñòðîéêè.
return S_OK;
}
STDMETHOD(get_DpiX)(double* lDpiX)
{
if (NULL == lDpiX)
return S_FALSE;
*lDpiX = m_dDpiX;
return S_OK;
}
STDMETHOD(put_DpiX)(double lDpiX)
{
m_dDpiX = lDpiX;
UpdateUnits();
return S_OK;
}
STDMETHOD(get_DpiY)(double* lDpiY)
{
if (NULL == lDpiY)
return S_FALSE;
*lDpiY = m_dDpiY;
return S_OK;
}
STDMETHOD(put_DpiY)(double lDpiY)
{
m_dDpiY = lDpiY;
UpdateUnits();
return S_OK;
}
STDMETHOD(SetPageWidth)(double lWidth, LONG lUnit)
{
// âû÷èñèëèòü dpi è âûñòàâèòü åãî
switch (lUnit)
{
case c_ag_PageUnitPoint:
{
lWidth /= c_ag_Inch_to_Point;
put_DpiX(m_dWidthPix / lWidth);
break;
}
case c_ag_PageUnitMillimeter:
{
lWidth /= c_ag_Inch_to_MM;
put_DpiX(m_dWidthPix / lWidth);
break;
}
case c_ag_PageUnitInch:
{
put_DpiX(m_dWidthPix / lWidth);
break;
}
default:
break;
};
return S_OK;
}
STDMETHOD(SetPageHeight)(double lHeight, LONG lUnit)
{
// âû÷èñèëèòü dpi è âûñòàâèòü åãî
switch (lUnit)
{
case c_ag_PageUnitPoint:
{
lHeight /= c_ag_Inch_to_Point;
put_DpiY(m_dHeightPix / lHeight);
break;
}
case c_ag_PageUnitMillimeter:
{
lHeight /= c_ag_Inch_to_MM;
put_DpiY(m_dHeightPix / lHeight);
break;
}
case c_ag_PageUnitInch:
{
put_DpiY(m_dHeightPix / lHeight);
break;
}
default:
break;
};
return S_OK;
}
STDMETHOD(get_PageUnit)(LONG* lUnit)
{
if (NULL != lUnit)
return S_FALSE;
*lUnit = m_lPageUnits;
return S_OK;
}
STDMETHOD(put_PageUnit)(LONG lUnit)
{
if (lUnit != m_lPageUnits)
{
m_lPageUnits = lUnit;
UpdateUnits();
}
return S_OK;
}
STDMETHOD(get_Transform)(IAVSMatrix** ppTransform)
{
if (NULL == ppTransform)
return S_OK;
CoCreateInstance(__uuidof(CAVSMatrix), NULL, CLSCTX_INPROC, __uuidof(IAVSMatrix), (void**)ppTransform);
if (NULL != *ppTransform)
{
float mass[6];
m_oTransform.GetElements(mass);
(*ppTransform)->SetElements((double)mass[0], (double)mass[1], (double)mass[2], (double)mass[3], (double)mass[4], (double)mass[5]);
}
return S_OK;
}
STDMETHOD(put_Transform)(IAVSMatrix* pTransform)
{
if (NULL == pTransform)
return S_FALSE;
NSStructures::SetMatrix(m_oTransform, ((CAVSMatrix*)pTransform)->m_oMatrix);
return S_OK;
}
STDMETHOD(get_BaseTransform)(IAVSMatrix** ppTransform)
{
if (NULL == ppTransform)
return S_OK;
CoCreateInstance(__uuidof(CAVSMatrix), NULL, CLSCTX_INPROC, __uuidof(IAVSMatrix), (void**)ppTransform);
if (NULL != *ppTransform)
{
float mass[6];
m_oBaseTransform.GetElements(mass);
(*ppTransform)->SetElements((double)mass[0], (double)mass[1], (double)mass[2], (double)mass[3], (double)mass[4], (double)mass[5]);
}
return S_OK;
}
STDMETHOD(put_BaseTransform)(IAVSMatrix* pTransform)
{
if (NULL == pTransform)
return S_FALSE;
NSStructures::SetMatrix(m_oBaseTransform, ((CAVSMatrix*)pTransform)->m_oMatrix);
return S_OK;
}
STDMETHOD(TranslateTransform)(double dX, double dY, LONG lMatrixOrder)
{
m_oTransform.Translate((float)dX, (float)dY, (Gdiplus::MatrixOrder)lMatrixOrder);
return S_OK;
}
STDMETHOD(RotateTransform)(double dAngle, LONG lMatrixOrder)
{
m_oTransform.Rotate((float)dAngle, (Gdiplus::MatrixOrder)lMatrixOrder);
return S_OK;
}
STDMETHOD(ScaleTransform)(double dScaleX, double dScaleY, LONG lMatrixOrder)
{
m_oTransform.Scale((float)dScaleX, (float)dScaleY, (Gdiplus::MatrixOrder)lMatrixOrder);
return S_OK;
}
STDMETHOD(MultiplyTransform)(IAVSMatrix* pTransform, LONG lMatrixOrder)
{
if (NULL == pTransform)
return S_FALSE;
m_oTransform.Multiply(&((CAVSMatrix*)pTransform)->m_oMatrix, (Gdiplus::MatrixOrder)lMatrixOrder);
return S_OK;
}
STDMETHOD(Save)(IAVSGraphicsState** pState)
{
return S_OK;
}
STDMETHOD(Restore)(IAVSGraphicsState* pState)
{
return S_OK;
}
// ôóíêöèè îòñå÷åíèÿ
STDMETHOD(SetClip1)(double dLeft, double dTop, double dWidth, double dHeight, LONG lCombineMode)
{
CGraphicsPath oPath;
oPath.AddRectangle(dLeft, dTop, dWidth, dHeight);
double mass[6];
SetUpMatrix(mass);
switch (lCombineMode)
{
case c_ag_CombineModeReplace:
{
m_oClip.Reset();
m_oClip.Intersect(&oPath, mass, m_dClipFlatness, FALSE);
break;
}
case c_ag_CombineModeIntersect:
{
m_oClip.Intersect(&oPath, mass, m_dClipFlatness, FALSE);
break;
}
case c_ag_CombineModeUnion:
{
m_oClip.Exclude(&oPath, mass, m_dClipFlatness, FALSE);
break;
}
default:
{
m_oClip.Reset();
m_oClip.Intersect(&oPath, mass, m_dClipFlatness, FALSE);
break;
}
};
return S_OK;
}
STDMETHOD(SetClip2)(IAVSGraphicsPath* punkPath, LONG lCombineMode)
{
if (NULL == punkPath)
return S_FALSE;
double mass[6];
SetUpMatrix(mass);
CGraphicsPath* pPath = &(((CAVSGraphicsPath*)punkPath)->m_oPath);
switch (lCombineMode)
{
case c_ag_CombineModeReplace:
{
m_oClip.Reset();
m_oClip.Intersect(pPath, mass, m_dClipFlatness, FALSE);
break;
}
case c_ag_CombineModeIntersect:
{
m_oClip.Intersect(pPath, mass, m_dClipFlatness, FALSE);
break;
}
case c_ag_CombineModeUnion:
{
m_oClip.Exclude(pPath, mass, m_dClipFlatness, FALSE);
break;
}
default:
{
m_oClip.Reset();
m_oClip.Intersect(pPath, mass, m_dClipFlatness, FALSE);
break;
}
};
return S_OK;
}
STDMETHOD(SetClip3)(IUnknown* pRegion, LONG lCombineMode)
{
return S_OK;
}
STDMETHOD(ExludeClip1)(double dLeft, double dTop, double dWidth, double dHeight, LONG lCombineMode)
{
CGraphicsPath oPath;
oPath.AddRectangle(dLeft, dTop, dWidth, dHeight);
double mass[6];
SetUpMatrix(mass);
m_oClip.Reset();
m_oClip.Intersect(&oPath, mass, m_dClipFlatness, FALSE);
return S_OK;
}
STDMETHOD(ExludeClip2)(IAVSGraphicsPath* punkPath, LONG lCombineMode)
{
if (NULL == punkPath)
return S_FALSE;
double mass[6];
SetUpMatrix(mass);
CGraphicsPath* pPath = &((CAVSGraphicsPath*)punkPath)->m_oPath;
m_oClip.Reset();
m_oClip.Intersect(pPath, mass, m_dClipFlatness, FALSE);
return S_OK;
}
STDMETHOD(ExludeClip3)(IUnknown* pRegion, LONG lCombineMode)
{
return S_OK;
}
// èçìåðåíèå òåêñòà
STDMETHOD(MeasureString)(BSTR bstrText, IAVSFontManager* pManager, double* lWidth, double* lHeight)
{
if (NULL == pManager || NULL == lWidth || NULL == lHeight)
return S_FALSE;
pManager->LoadString(bstrText, 0, 0);
float x = 0;
float y = 0;
float w = 0;
float h = 0;
pManager->MeasureString(&x, &y, &w, &h);
*lWidth = (double)w;
*lHeight = (double)h;
return S_OK;
}
// òóò åùå íàäî ïðîäóìàòü çà÷åðêèâàíèå, ïîä÷åðêèâàíèå. ðåàëèçîâûâàòü íóæíî, ïîíÿòíî, â ìåòîäå DrawString
// íàñòðîéêè îòðèñîâùèêà
STDMETHOD(get_SmoothingMode)(LONG* lMode)
{
if (NULL == lMode)
return S_FALSE;
*lMode = m_lSmoothMode;
return S_OK;
}
STDMETHOD(put_SmoothingMode)(LONG lMode)
{
m_lSmoothMode = lMode;
return S_OK;
}
STDMETHOD(get_TextRenderingHint)(LONG* lMode)
{
if (NULL != lMode)
return S_FALSE;
*lMode = m_lAntialiseMode;
return S_OK;
}
STDMETHOD(put_TextRenderingHint)(LONG lMode)
{
m_lAntialiseMode = lMode;
return S_OK;
}
STDMETHOD(get_CompositingMode)(LONG* lMode)
{
return S_OK;
}
STDMETHOD(put_CompositingMode)(LONG lMode)
{
return S_OK;
}
STDMETHOD(get_CompositingQuality)(LONG* lMode)
{
return S_OK;
}
STDMETHOD(put_CompositingQuality)(LONG lMode)
{
return S_OK;
}
STDMETHOD(get_InterpolationMode)(LONG* lMode)
{
return S_OK;
}
STDMETHOD(put_InterpolationMode)(LONG lMode)
{
return S_OK;
}
STDMETHOD(get_PixelOffsetMode)(LONG* lMode)
{
return S_OK;
}
STDMETHOD(put_PixelOffsetMode)(LONG lMode)
{
return S_OK;
}
// îòðèñîâêà ïðèìèòèâîâ (áåç çàëèâêè)
STDMETHOD(Clear)(LONG lColor)
{
SColorPointer pColor = (SColorPointer)&lColor;
BYTE unAlpha = (BYTE)(lColor);
unsigned char unMono;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
unMono = (pColor[0] & 0x80) ? 0xff : 0x00;
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), unMono, -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, unMono, m_oPixels.m_lStride * m_oPixels.m_lHeight);
}
break;
case colorModeMono8:
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), pColor[0], -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, pColor[0], m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
break;
case colorModeRGB8:
if ( pColor[0] == pColor[1] && pColor[1] == pColor[2] )
{
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), pColor[0], -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, pColor[0], m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
}
else
{
SColorPointer pLine = m_oPixels.m_pPixels;
for ( int nY = 0; nY < m_oPixels.m_lHeight; ++nY )
{
SColorPointer pCur = pLine;
for ( int nX = 0; nX < m_oPixels.m_lWidth; ++nX )
{
*pCur++ = pColor[2];
*pCur++ = pColor[1];
*pCur++ = pColor[0];
}
pLine += m_oPixels.m_lStride;
}
}
break;
case colorModeBGR8:
if ( pColor[0] == pColor[1] && pColor[1] == pColor[2] )
{
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), pColor[0], -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, pColor[0], m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
}
else
{
SColorPointer pLine = m_oPixels.m_pPixels;
for ( int nY = 0; nY < m_oPixels.m_lHeight; ++nY )
{
SColorPointer pCur = pLine;
for ( int nX = 0; nX < m_oPixels.m_lWidth; ++nX )
{
*pCur++ = pColor[0];
*pCur++ = pColor[1];
*pCur++ = pColor[2];
}
pLine += m_oPixels.m_lStride;
}
}
break;
case colorModeRGBA8:
if ( pColor[0] == pColor[1] && pColor[1] == pColor[2] )
{
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), pColor[0], -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, pColor[0], m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
}
else
{
SColorPointer pLine = m_oPixels.m_pPixels;
for ( int nY = 0; nY < m_oPixels.m_lHeight; ++nY )
{
SColorPointer pCur = pLine;
for ( int nX = 0; nX < m_oPixels.m_lWidth; ++nX )
{
*pCur++ = pColor[2];
*pCur++ = pColor[1];
*pCur++ = pColor[0];
*pCur++ = unAlpha;
}
pLine += m_oPixels.m_lStride;
}
}
break;
case colorModeBGRA8:
if ( pColor[0] == pColor[1] && pColor[1] == pColor[2] )
{
if ( m_oPixels.m_lStride < 0 )
{
memset( m_oPixels.m_pPixels + m_oPixels.m_lStride * (m_oPixels.m_lHeight - 1), pColor[0], -m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
else
{
memset( m_oPixels.m_pPixels, pColor[0], m_oPixels.m_lStride * m_oPixels.m_lHeight );
}
}
else
{
SColorPointer pLine = m_oPixels.m_pPixels;
for ( int nY = 0; nY < m_oPixels.m_lHeight; ++nY )
{
SColorPointer pCur = pLine;
for ( int nX = 0; nX < m_oPixels.m_lWidth; ++nX )
{
*pCur++ = pColor[0];
*pCur++ = pColor[1];
*pCur++ = pColor[2];
*pCur++ = unAlpha;
}
pLine += m_oPixels.m_lStride;
}
}
break;
}
if ( m_oPixels.m_pAlpha )
{
memset( m_oPixels.m_pAlpha, unAlpha, m_oPixels.m_lWidth * m_oPixels.m_lHeight );
}
UpdateModX( 0 );
UpdateModY( 0 );
UpdateModX( m_oPixels.m_lWidth - 1 );
UpdateModY( m_oPixels.m_lHeight - 1 );
return S_OK;
}
STDMETHOD(DrawArc)(IAVSPen* pPen, double x, double y, double width, double height, double startAngle, double sweepAngle)
{
CGraphicsPath oPath;
oPath.AddArc(x, y, width, height, startAngle, sweepAngle);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawBezier)(IAVSPen* pPen, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
CGraphicsPath oPath;
oPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawBeziers)(IAVSPen* pPen, LPSAFEARRAY pPoints)
{
if (NULL == pPoints)
return S_FALSE;
LONG lCount = pPoints->rgsabound[0].cElements;
double* pData = (double*)pPoints->pvData;
CGraphicsPath oPath;
oPath.AddBeziers(pData, lCount);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawCurve)(IAVSPen* pPen, LPSAFEARRAY pPoints)
{
if (NULL == pPoints)
return S_FALSE;
LONG lCount = pPoints->rgsabound[0].cElements;
double* pData = (double*)pPoints->pvData;
CGraphicsPath oPath;
oPath.AddCurve(pData, lCount);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawLine)(IAVSPen* pPen, double x1, double y1, double x2, double y2)
{
CGraphicsPath oPath;
oPath.AddLine(x1, y1, x2, y2);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawLines)(IAVSPen* pPen, LPSAFEARRAY pPoints)
{
if (NULL == pPoints)
return S_FALSE;
LONG lCount = pPoints->rgsabound[0].cElements;
double* pData = (double*)pPoints->pvData;
CGraphicsPath oPath;
oPath.AddLines(pData, lCount);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawEllipse)(IAVSPen* pPen, double x, double y, double width, double height)
{
CGraphicsPath oPath;
oPath.AddEllipse(x, y, width, height);
BOOL bRes = DrawPath(pPen, &oPath);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(DrawPath)(IAVSPen* pPen, IAVSGraphicsPath* pPath)
{
BOOL bRes = DrawPath(pPen, &((CAVSGraphicsPath*)pPath)->m_oPath);
return bRes ? S_OK : S_FALSE;
}
// çàëèâêà
STDMETHOD(FillEllipse)(IAVSBrush* pBrush, double x, double y, double width, double height)
{
CGraphicsPath oPath;
oPath.AddEllipse(x, y, width, height);
IAVSPattern* pPattern = NULL;
oPath.Pattern(pBrush, &pPattern);
BOOL bRes = FillPath(pPattern, &oPath);
RELEASEINTERFACE(pPattern);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(FillPath)(IAVSBrush* pBrush, IAVSGraphicsPath* pPath)
{
IAVSPattern* pPattern = NULL;
pPath->Pattern(pBrush, &pPattern);
BOOL bRes = FillPath(pPattern, &((CAVSGraphicsPath*)pPath)->m_oPath);
RELEASEINTERFACE(pPattern);
return bRes ? S_OK : S_FALSE;
}
STDMETHOD(FillPolygon)(IAVSBrush* pBrush, LPSAFEARRAY pPoints)
{
if (NULL == pPoints)
return S_FALSE;
LONG lCount = pPoints->rgsabound[0].cElements;
double* pData = (double*)pPoints->pvData;
CGraphicsPath oPath;
oPath.AddPolygon(pData, lCount);
IAVSPattern* pPattern = NULL;
oPath.Pattern(pBrush, &pPattern);
BOOL bRes = FillPath(pPattern, &oPath);
RELEASEINTERFACE(pPattern);
return bRes ? S_OK : S_FALSE;
}
// îòðèñîâêà êàðòèíêè
STDMETHOD(DrawImage)(IAVSImage* pImage, double x, double y, double width, double height)
{
return S_OK;
}
STDMETHOD(DrawImage2)(IAVSImage* pImage, LPSAFEARRAY pPoints)
{
return S_OK;
}
STDMETHOD(DrawImageUnscaled)(IAVSImage* pImage, double x, double y)
{
return S_OK;
}
// îòðèñîâêà òåêñòà
STDMETHOD(DrawString)(BSTR bstrText, IAVSFontManager* pFont, IAVSBrush* pBrush, double x, double y)
{
double mass[6];
GetElements(mass);
pFont->SetTextMatrix(mass[0], mass[1], mass[2], mass[3], mass[4], mass[5]);
pFont->LoadString(bstrText, (float)x, (float)y);
CString str(bstrText);
int nCount = str.GetLength();
float fX = 0;
float fY = 0;
VARIANT_BOOL bRes = VARIANT_FALSE;
IAVSPattern* pPattern = NULL;
CGraphicsPath oPath;
oPath.Pattern(pBrush, &pPattern);
while (TRUE)
{
IAVSGlyphImage* pGlyph = NULL;
float fX = 0, fY = 0;
pFont->GetNextChar2(&pGlyph, &fX, &fY, &bRes);
if (VARIANT_FALSE == bRes || NULL == pGlyph)
break;
FillGlyph((int)fX, (int)fY, &((CAVSGlyphImage*)pGlyph)->m_oGlyph, pPattern, 1.0);
RELEASEINTERFACE(pGlyph);
}
RELEASEINTERFACE(pPattern);
return S_OK;
}
STDMETHOD(DrawString2)(BSTR bstrText, IAVSFontManager* pFont, IAVSBrush* pBrush,
IAVSStringFormat* pFormat, double x, double y, double width, double height)
{
return S_OK;
}
static HRESULT LoadImageFromFile(BSTR bstrPath, IAVSImage** ppImage)
{
return S_OK;
}
protected:
int FillPath(IAVSPattern* pPattern, CGraphicsPath* pPath, double dAlpha = 1.0)
{
double matrix[6];
GetElements(matrix);
int nX0 = 0, nX1 = 0;
if ( pPath->m_nPointsCount == 0 )
{
return SErrorEmptyPath;
}
SXPath *pXPath = new SXPath( pPath, matrix, m_dFlatness, TRUE );
if ( !pXPath )
return SErrorMemory;
if ( m_bVectorAA )
{
pXPath->AntiAliasingScale();
}
pXPath->Sort();
SXPathScanner *pScanner = new SXPathScanner( pXPath, (1 == pPath->m_lMode) );
if ( !pScanner )
return SErrorMemory;
int nMinX, nMinY, nMaxX, nMaxY;
if ( m_bVectorAA )
{
pScanner->GetBBoxAA( &nMinX, &nMinY, &nMaxX, &nMaxY );
}
else
{
pScanner->GetBBox( &nMinX, &nMinY, &nMaxX, &nMaxY );
}
SClipResult eClipResult;
if ( ( eClipResult = m_oClip.CheckRectangle( nMinX, nMinY, nMaxX, nMaxY) ) != clipAllOutside )
{
if ( nMinY < m_oClip.GetMinY() )
{
nMinY = m_oClip.GetMinY();
}
if ( nMaxY > m_oClip.GetMaxY() )
{
nMaxY = m_oClip.GetMaxY();
}
SPipe oPipe;
PipeInit( &oPipe, 0, nMinY, pPattern, NULL, dAlpha, m_bVectorAA, FALSE );
if ( m_bVectorAA )
{
for ( int nY = nMinY; nY <= nMaxY; ++nY )
{
pScanner->RenderAALine( &m_oAABuffer, &nX0, &nX1, nY );
if ( eClipResult != clipAllInside )
{
m_oClip.ClipAALine( &m_oAABuffer, &nX0, &nX1, nY );
}
DrawAALine( &oPipe, nX0, nX1, nY );
}
}
else
{
for ( int nY = nMinY; nY <= nMaxY; ++nY )
{
while ( pScanner->GetNextSpan( nY, &nX0, &nX1) )
{
if ( eClipResult == clipAllInside )
{
DrawSpan( &oPipe, nX0, nX1, nY, TRUE );
}
else
{
// limit the x range
if ( nX0 < m_oClip.GetMinX() )
{
nX0 = m_oClip.GetMinX();
}
if ( nX1 > m_oClip.GetMaxX() )
{
nX1 = m_oClip.GetMaxX();
}
SClipResult eTempClipRes = m_oClip.CheckSpan( nX0, nX1, nY );
DrawSpan( &oPipe, nX0, nX1, nY, eTempClipRes == clipAllInside );
}
}
}
}
}
m_pOpClipRes = eClipResult;
delete pScanner;
delete pXPath;
//return SNoError;
return TRUE;
}
BOOL DrawPath(IAVSPen* pPen, CGraphicsPath* pPath)
{
CState oState;
IAVSPattern* pPattern = NULL;
pPath->Pattern(pPen, &pPattern);
BOOL bRes = (SNoError == DrawPath(pPattern, pPath, &oState));
RELEASEINTERFACE(pPattern);
return bRes;
}
int DrawPath(IAVSPattern* pPattern, CGraphicsPath* pPath, CState* pState)
{
m_pOpClipRes = clipAllOutside;
if ( pPath->m_nPointsCount == 0 )
{
return SErrorEmptyPath;
}
CGraphicsPath *pResultPath = FlattenPath( pPath, pState->m_arrdMatrix, m_dFlatness );
if ( !pResultPath )
return SErrorMemory;
if ( pState->m_nLineDashCount > 0 )
{
CGraphicsPath *pDashPath = MakeDashedPath( pResultPath, pState );
delete pResultPath;
pResultPath = pDashPath;
}
if ( pState->m_dLineWidth == 0 )
{
StrokeNarrow( pResultPath, pState, pPattern );
}
else
{
StrokeWide( pResultPath, pState, pPattern );
}
delete pResultPath;
return SNoError;
}
void StrokeNarrow(CGraphicsPath *pPath, CState* pState, IAVSPattern* pPattern)
{
SClipResult eClipResult;
int arrnClipRes[3];
arrnClipRes[0] = arrnClipRes[1] = arrnClipRes[2] = 0;
SXPath *pXPath = new SXPath( pPath, pState->m_arrdMatrix, m_dFlatness, FALSE );
if ( !pXPath )
return;
SPipe oPipe;
PipeInit( &oPipe, 0, 0, pPattern, NULL, pState->m_dStrokeAlpha, FALSE, FALSE );
int nSegmentIndex;
SXPathSegment *pSegment = NULL;
for ( nSegmentIndex = 0, pSegment = pXPath->m_pSegments; nSegmentIndex < pXPath->m_nSegmentsCount; ++nSegmentIndex, ++pSegment )
{
int nX0 = (int)floor( pSegment->dFirstX );
int nX1 = (int)floor( pSegment->dSecondX );
int nY0 = (int)floor( pSegment->dFirstY );
int nY1 = (int)floor( pSegment->dSecondY );
// ãîðèçîíòàëüíûé ñåãìåíò
if ( nY0 == nY1 )
{
if ( nX0 > nX1 )
{
int nTemp = nX0;
nX0 = nX1;
nX1 = nTemp;
}
if ( ( eClipResult = m_oClip.CheckSpan( nX0, nX1, nY0 ) ) != clipAllOutside )
{
DrawSpan( &oPipe, nX0, nX1, nY0, eClipResult == clipAllInside );
}
}
else if ( fabs(pSegment->dDxDy) > 1) // |dDx| > |dDy|
{
double dDx = pSegment->dSecondX - pSegment->dFirstX;
double dDy = pSegment->dSecondY - pSegment->dFirstY;
double dDxDy = pSegment->dDxDy;
if ( nY0 > nY1 )
{
int nTemp = nY0;
nY0 = nY1;
nY1 = nTemp;
nTemp = nX0;
nX0 = nX1;
nX1 = nTemp;
dDx = -dDx;
dDy = -dDy;
}
if ( ( eClipResult = m_oClip.CheckRectangle( nX0 <= nX1 ? nX0 : nX1, nY0, nX0 <= nX1 ? nX1 : nX0, nY1) ) != clipAllOutside )
{
if ( dDx > 0 )
{
int nX2 = nX0;
int nX3 = (int)floor( pSegment->dFirstX + ((double)nY0 + 1 - pSegment->dFirstY) * dDxDy );
DrawSpan( &oPipe, nX2, (nX2 <= nX3 - 1) ? nX3 - 1 : nX2, nY0, eClipResult == clipAllInside );
nX2 = nX3;
for ( int nY = nY0 + 1; nY <= nY1 - 1; ++nY )
{
nX3 = (int)floor( pSegment->dFirstX + ((double)nY + 1 - pSegment->dFirstY) * dDxDy );
DrawSpan( &oPipe, nX2, nX3 - 1, nY, eClipResult == clipAllInside );
nX2 = nX3;
}
DrawSpan( &oPipe, nX2, nX2 <= nX1 ? nX1 : nX2, nY1, eClipResult == clipAllInside );
}
else
{
int nX2 = nX0;
int nX3 = (int)floor( pSegment->dFirstX + ((double)nY0 + 1 - pSegment->dFirstY) * dDxDy );
DrawSpan( &oPipe, (nX3 + 1 <= nX2) ? nX3 + 1 : nX2, nX2, nY0, eClipResult == clipAllInside );
nX2 = nX3;
for ( int nY = nY0 + 1; nY <= nY1 - 1; ++nY )
{
nX3 = (int)floor( pSegment->dFirstX + ((double)nY + 1 - pSegment->dFirstY) * dDxDy );
DrawSpan( &oPipe, nX3 + 1, nX2, nY, eClipResult == clipAllInside );
nX2 = nX3;
}
DrawSpan( &oPipe, nX1, (nX1 <= nX2) ? nX2 : nX1, nY1, eClipResult == clipAllInside );
}
}
}
else // |dDy| > |dDx|
{
double dDxDy = pSegment->dDxDy;
if ( nY0 > nY1 )
{
int nTemp = nX0;
nX0 = nX1;
nX1 = nTemp;
nTemp = nY0;
nY0 = nY1;
nY1 = nTemp;
}
if ( ( eClipResult = m_oClip.CheckRectangle( nX0 <= nX1 ? nX0 : nX1, nY0, nX0 <= nX1 ? nX1 : nX0, nY1) ) != clipAllOutside )
{
DrawPixel( &oPipe, nX0, nY0, eClipResult == clipAllInside );
for ( int nY = nY0 + 1; nY <= nY1 - 1; ++nY )
{
int nX = (int)floor(pSegment->dFirstX + ((double)nY - pSegment->dFirstY) * dDxDy);
DrawPixel( &oPipe, nX, nY, eClipResult == clipAllInside );
}
DrawPixel( &oPipe, nX1, nY1, eClipResult == clipAllInside );
}
}
++arrnClipRes[eClipResult];
}
if ( arrnClipRes[clipPartial] || ( arrnClipRes[clipAllInside] && arrnClipRes[clipAllOutside] ) )
{
m_pOpClipRes = clipPartial;
}
else if ( arrnClipRes[clipAllInside] )
{
m_pOpClipRes = clipAllInside;
}
else
{
m_pOpClipRes = clipAllOutside;
}
delete pXPath;
}
void StrokeWide(CGraphicsPath *pPath, CState* pState, IAVSPattern* pPattern)
{
CGraphicsPath *pStrokePath = MakeStrokePath( pPath, FALSE, pState );
if ( !pStrokePath )
return;
FillPath( pPattern, pStrokePath, pState->m_dStrokeAlpha );
delete pStrokePath;
}
CGraphicsPath* MakeDashedPath(SPath *pPath, CState* pState)
{
double dLineDashTotal = 0;
int nIndex = 0;
for ( nIndex = 0; nIndex < pState->m_nLineDashCount; ++nIndex )
{
dLineDashTotal += pState->m_pdLineDash[nIndex];
}
double dLineDashStartPhase = pState->m_dLineDashPhase;
nIndex = (int)floor( dLineDashStartPhase / dLineDashTotal );
dLineDashStartPhase -= (double)nIndex * dLineDashTotal;
BOOL bLineDashStartOn = TRUE;
int nLineDashStartIndex = 0;
while ( dLineDashStartPhase >= pState->m_pdLineDash[nLineDashStartIndex] )
{
bLineDashStartOn = !bLineDashStartOn;
dLineDashStartPhase -= pState->m_pdLineDash[nLineDashStartIndex];
++nLineDashStartIndex;
}
CGraphicsPath *pDashPath = new CGraphicsPath();
nIndex = 0;
while ( nIndex < pPath->m_nPointsCount )
{
// Èùåì îêîí÷àíèå äàííîãî SupPath
int nEndIndex;
for ( nEndIndex = nIndex; nEndIndex < pPath->m_nPointsCount - 1 && !(pPath->m_pFlags[nEndIndex] & SPathLast); ++nEndIndex) ;
// Îáíóëÿåì ïàðàìåòðû
BOOL bLineDashOn = bLineDashStartOn;
int nLineDashIndex = nLineDashStartIndex;
double dLineDashDist = pState->m_pdLineDash[nLineDashIndex] - dLineDashStartPhase;
// Ðàáîòàåì ñ ÷àñòÿìè SupPath
BOOL bNewPath = TRUE;
for ( int nK = nIndex; nK < nEndIndex; ++nK )
{
// Çàáèðàåì ñåãìåíò
double dX0 = pPath->m_pPoints[nK].dX;
double dY0 = pPath->m_pPoints[nK].dY;
double dX1 = pPath->m_pPoints[nK + 1].dX;
double dY1 = pPath->m_pPoints[nK + 1].dY;
double dSegLen = distance( dX0, dY0, dX1, dY1 );
while ( dSegLen > 0 )
{
if ( dLineDashDist >= dSegLen )
{
if ( bLineDashOn )
{
if ( bNewPath )
{
pDashPath->MoveTo( dX0, dY0 );
bNewPath = FALSE;
}
pDashPath->LineTo( dX1, dY1 );
}
dLineDashDist -= dSegLen;
dSegLen = 0;
}
else
{
double dTempX = dX0 + (dLineDashDist / dSegLen) * (dX1 - dX0);
double dTempY = dY0 + (dLineDashDist / dSegLen) * (dY1 - dY0);
if ( bLineDashOn )
{
if ( bNewPath )
{
pDashPath->MoveTo( dX0, dY0 );
bNewPath = FALSE;
}
pDashPath->LineTo( dTempX, dTempY );
}
dX0 = dTempX;
dY0 = dTempY;
dSegLen -= dLineDashDist;
dLineDashDist = 0;
}
if ( dLineDashDist <= 0 )
{
bLineDashOn = !bLineDashOn;
if ( ++nLineDashIndex == pState->m_nLineDashCount )
{
nLineDashIndex = 0;
}
dLineDashDist = pState->m_pdLineDash[nLineDashIndex];
bNewPath = TRUE;
}
}
}
nIndex = nEndIndex + 1;
}
return pDashPath;
}
CGraphicsPath* MakeStrokePath(CGraphicsPath *pPath, BOOL bFlatten, CState* pState)
{
CGraphicsPath *pPathIn, *pPathOut;
if ( bFlatten )
{
pPathIn = FlattenPath( pPath, pState->m_arrdMatrix, m_dFlatness );
if ( pState->m_nLineDashCount > 0 )
{
pPathOut = MakeDashedPath( pPathIn, pState );
delete pPathIn;
pPathIn = pPathOut;
}
}
else
{
pPathIn = pPath;
}
int nSubpathStart = 0;
BOOL bClosed = FALSE;
int nLeft0 = 0, nLeft1 = 0, nRight0 = 0, nRight1 = 0, nJoin0 = 0, nJoin1 = 0, nLeft2, nRight2, nJoin2;
int nLeftFirst = 0, nRightFirst = 0, nFirstPoint = 0;
pPathOut = new CGraphicsPath();
double dWidth = pState->m_dLineWidth;
for ( int nIndex = 0; nIndex < pPathIn->m_nPointsCount - 1; ++nIndex )
{
if ( pPathIn->m_pFlags[nIndex] & SPathLast )
{
continue;
}
BOOL bFirst;
if ( ( bFirst = pPathIn->m_pFlags[nIndex] & SPathFirst ) )
{
nSubpathStart = nIndex;
bClosed = pPathIn->m_pFlags[nIndex] & SPathClosed;
}
BOOL bLast = pPathIn->m_pFlags[nIndex + 1] & SPathLast;
// Âû÷èñëèì äèàãîíàëü ñåãìåíòà ( nIndex, nIndex + 1 )
double dDist = distance( pPathIn->m_pPoints[nIndex].dX, pPathIn->m_pPoints[nIndex].dY, pPathIn->m_pPoints[nIndex + 1].dX, pPathIn->m_pPoints[nIndex + 1].dY );
double dDx, dDy;
if ( dDist == 0 )
{
dDx = 0;
dDy = 1;
}
else
{
dDist = (double)1 / dDist;
dDx = dDist * ( pPathIn->m_pPoints[nIndex + 1].dX - pPathIn->m_pPoints[nIndex].dX );
dDy = dDist * ( pPathIn->m_pPoints[nIndex + 1].dY - pPathIn->m_pPoints[nIndex].dY );
}
double dWidthDx = (double)0.5 * dWidth * dDx;
double dWidthDy = (double)0.5 * dWidth * dDy;
// Âû÷èñëèì äèàãîíàëü ñåãìåíòà ( nIndex + 1, nNext )
int nNext = bLast ? nSubpathStart + 1 : nIndex + 2;
dDist = distance( pPathIn->m_pPoints[nIndex + 1].dX, pPathIn->m_pPoints[nIndex + 1].dY, pPathIn->m_pPoints[nNext].dX, pPathIn->m_pPoints[nNext].dY );
double dNextDx, dNextDy;
if ( dDist == 0 )
{
dNextDx = 0;
dNextDy = 1;
}
else
{
dDist = (double)1 / dDist;
dNextDx = dDist * ( pPathIn->m_pPoints[nNext].dX - pPathIn->m_pPoints[nIndex + 1].dX );
dNextDy = dDist * ( pPathIn->m_pPoints[nNext].dY - pPathIn->m_pPoints[nIndex + 1].dY );
}
double dWidthNextDx = (double)0.5 * dWidth * dNextDx;
double dWidthNextDy = (double)0.5 * dWidth * dNextDy;
// Ðèñóåì íà÷àëî ëèíèè
pPathOut->MoveTo( pPathIn->m_pPoints[nIndex].dX - dWidthDy, pPathIn->m_pPoints[nIndex].dY + dWidthDx );
if ( nIndex == nSubpathStart )
{
nFirstPoint = pPathOut->m_nPointsCount - 1;
}
if ( bFirst && !bClosed )
{
switch ( pState->m_nLineCap )
{
case /*LineCapButt*/0:
pPathOut->LineTo( pPathIn->m_pPoints[nIndex].dX + dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDx );
break;
case /*LineCapRound*/1:
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex].dX - dWidthDy - c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex].dY + dWidthDx - c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex].dX - dWidthDx - c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDy + c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex].dX - dWidthDx, pPathIn->m_pPoints[nIndex].dY - dWidthDy );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex].dX - dWidthDx + c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDy - c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex].dX + dWidthDy - c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex].dY - dWidthDx - c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex].dX + dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDx );
break;
case /*LineCapProjecting*/2:
pPathOut->LineTo( pPathIn->m_pPoints[nIndex].dX - dWidthDx - dWidthDy, pPathIn->m_pPoints[nIndex].dY + dWidthDx - dWidthDy );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex].dX - dWidthDx + dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDx - dWidthDy );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex].dX + dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDx );
break;
}
}
else
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex].dX + dWidthDy, pPathIn->m_pPoints[nIndex].dY - dWidthDx );
}
// Ðèñóåì ëåâóþ ñòîðîíóþ äëÿ ïðÿìîóãîëüíèêà ñåãìåíòà
nLeft2 = pPathOut->m_nPointsCount - 1;
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY - dWidthDx );
// Ðèñóåì îêîí÷àíèå ëèíèè
if ( bLast && !bClosed )
{
switch (pState->m_nLineCap)
{
case /*LineCapButt*/0:
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
break;
case /*LineCapRound*/1:
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDy + c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex + 1].dY - dWidthDx + c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex + 1].dX + dWidthDx + c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDy - c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex + 1].dX + dWidthDx, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDy );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDx - c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDy + c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy + c_dKappa * dWidthDx, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx + c_dKappa * dWidthDy, pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
break;
case /*LineCapProjecting*/2:
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDy + dWidthDx, pPathIn->m_pPoints[nIndex + 1].dY - dWidthDx + dWidthDy );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy + dWidthDx, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx + dWidthDy );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
break;
}
}
else
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
}
// Ðèñóåì ïðàâóþ ñòîðîíóþ äëÿ ïðÿìîóãîëüíèêà ñåãìåíòà
nRight2 = pPathOut->m_nPointsCount - 1;
pPathOut->Close();
// Ðèñóåì ñîåäèíåíèå
nJoin2 = pPathOut->m_nPointsCount;
if ( !bLast || bClosed )
{
double dCrossprod = dDx * dNextDy - dDy * dNextDx;
double dDotprod = -(dDx * dNextDx + dDy * dNextDy);
double dMiter, dMit;
if ( dDotprod > 0.99999 )
{
// Äëÿ èçáåæàíèÿ äåëåíèé íà íîëü
dMiter = ( pState->m_dMiterLimit + 1 ) * ( pState->m_dMiterLimit + 1 );
dMit = 0;
}
else
{
dMiter = (double)2 / ((double)1 - dDotprod);
if ( dMiter < 1 )
{
dMiter = 1;
}
dMit = sqrt( dMiter - 1 );
}
// Ñêðóãëåííîå ñîåäèíåíèå
if ( pState->m_nLineJoin == /*LineJoinRound*/1 )
{
pPathOut->MoveTo ( pPathIn->m_pPoints[nIndex + 1].dX + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY + c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX + c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX, pPathIn->m_pPoints[nIndex + 1].dY + (double)0.5 * dWidth );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX - c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX - (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY + c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX - (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX - (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY - c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX - c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY - (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX, pPathIn->m_pPoints[nIndex + 1].dY - (double)0.5 * dWidth );
pPathOut->CurveTo( pPathIn->m_pPoints[nIndex + 1].dX + c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY - (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY - c_dKappa_2 * dWidth, pPathIn->m_pPoints[nIndex + 1].dX + (double)0.5 * dWidth, pPathIn->m_pPoints[nIndex + 1].dY );
}
else
{
pPathOut->MoveTo( pPathIn->m_pPoints[nIndex + 1].dX, pPathIn->m_pPoints[nIndex + 1].dY );
if ( dCrossprod < 0 ) // Óãîë < 180
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthNextDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthNextDx );
if ( pState->m_nLineJoin == /*LineJoinMiter*/0 && sqrt( dMiter ) <= pState->m_dMiterLimit ) // òèï ñîåäèíåíèÿ = LineJoinMiter è dMiter ìåíüøå dMiterLimit
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy + dWidthDx * dMit, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx + dWidthDy * dMit );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
}
else // ëèáî òèï ñîåäèíåíèÿ = LineJoinBevel, ëèáî dMiter áîëüøå dMiterLimit
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX - dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY + dWidthDx );
}
}
else // Óãîë >= 180
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDy, pPathIn->m_pPoints[nIndex + 1].dY - dWidthDx );
if ( pState->m_nLineJoin == /*LineJoinMiter*/0 && sqrt( dMiter ) <= pState->m_dMiterLimit ) // òèï ñîåäèíåíèÿ = LineJoinMiter è dMiter ìåíüøå dMiterLimit
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthDy + dWidthDx * dMit, pPathIn->m_pPoints[nIndex + 1].dY - dWidthDx + dWidthDy * dMit );
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthNextDy, pPathIn->m_pPoints[nIndex + 1].dY - dWidthNextDx );
}
else // ëèáî òèï ñîåäèíåíèÿ = LineJoinBevel, ëèáî dMiter áîëüøå dMiterLimit
{
pPathOut->LineTo( pPathIn->m_pPoints[nIndex + 1].dX + dWidthNextDy, pPathIn->m_pPoints[nIndex + 1].dY - dWidthNextDx );
}
}
}
pPathOut->Close();
}
if ( pState->m_bStrokeAdjust )
{
if ( nIndex >= nSubpathStart + 1 )
{
if ( nIndex >= nSubpathStart + 2 )
{
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nLeft0 + 1, nRight0 );
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nJoin0, nLeft2 );
}
else
{
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nFirstPoint, nLeft2 );
}
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nRight2 + 1, nRight2 + 1 );
}
nLeft0 = nLeft1;
nLeft1 = nLeft2;
nRight0 = nRight1;
nRight1 = nRight2;
nJoin0 = nJoin1;
nJoin1 = nJoin2;
if ( nIndex == nSubpathStart )
{
nLeftFirst = nLeft2;
nRightFirst = nRight2;
}
if ( bLast )
{
if ( nIndex >= nSubpathStart + 2 )
{
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nLeft0 + 1, nRight0 );
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nJoin0, pPathOut->m_nPointsCount - 1 );
}
else
{
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nFirstPoint, pPathOut->m_nPointsCount - 1 );
}
if ( bClosed )
{
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nFirstPoint, nLeftFirst );
pPathOut->AddStrokeAdjustHint( nLeft1, nRight1, nRightFirst + 1, nRightFirst + 1 );
pPathOut->AddStrokeAdjustHint( nLeftFirst, nRightFirst, nLeft1 + 1, nRight1 );
pPathOut->AddStrokeAdjustHint( nLeftFirst, nRightFirst, nJoin1, pPathOut->m_nPointsCount - 1 );
}
}
}
}
if ( pPathIn != pPath )
{
delete pPathIn;
}
return pPathOut;
}
CGraphicsPath* FlattenPath(SPath *pPath, double *pMatrix, double dFlatness)
{
CGraphicsPath *pFlatPath = new CGraphicsPath();
double dFlatness_2 = dFlatness * dFlatness;
int nPointIndex = 0;
while ( nPointIndex < pPath->m_nPointsCount )
{
unsigned char unFlag = pPath->m_pFlags[nPointIndex];
if ( unFlag & SPathFirst )
{
pFlatPath->MoveTo( pPath->m_pPoints[nPointIndex].dX, pPath->m_pPoints[nPointIndex].dY );
++nPointIndex;
}
else
{
if ( unFlag & SPathCurve )
{
FlattenCurve( pPath->m_pPoints[nPointIndex - 1].dX, pPath->m_pPoints[nPointIndex - 1].dY, pPath->m_pPoints[nPointIndex].dX, pPath->m_pPoints[nPointIndex].dY, pPath->m_pPoints[nPointIndex + 1].dX, pPath->m_pPoints[nPointIndex + 1].dY, pPath->m_pPoints[nPointIndex + 2].dX, pPath->m_pPoints[nPointIndex + 2].dY, pMatrix, dFlatness_2, pFlatPath );
nPointIndex += 3;
}
else
{
pFlatPath->LineTo( pPath->m_pPoints[nPointIndex].dX, pPath->m_pPoints[nPointIndex].dY );
++nPointIndex;
}
if ( pPath->m_pFlags[nPointIndex - 1] & SPathClosed )
{
pFlatPath->Close();
}
}
}
return pFlatPath;
}
void FlattenCurve(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, double *matrix, double dFlatness_2, SPath *fPath)
{
double arrSegX[MaxCurveSplits + 1][3];
double arrSegY[MaxCurveSplits + 1][3];
int arrNext[MaxCurveSplits + 1];
double xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
double yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
double dx, dy, mx, my, tx, ty, d1, d2;
// Íà÷àëüíûé ñåãìåíò
int nPart1 = 0, nPart2 = MaxCurveSplits;
arrSegX[nPart1][0] = x0; arrSegY[nPart1][0] = y0;
arrSegX[nPart1][1] = x1; arrSegY[nPart1][1] = y1;
arrSegX[nPart1][2] = x2; arrSegY[nPart1][2] = y2;
arrSegX[nPart2][0] = x3; arrSegY[nPart2][0] = y3;
arrNext[nPart1] = nPart2;
while ( nPart1 < MaxCurveSplits )
{
// Ñëåäóþùèé ñåãìåíò
xl0 = arrSegX[nPart1][0]; yl0 = arrSegY[nPart1][0];
xx1 = arrSegX[nPart1][1]; yy1 = arrSegY[nPart1][1];
xx2 = arrSegX[nPart1][2]; yy2 = arrSegY[nPart1][2];
nPart2 = arrNext[nPart1];
xr3 = arrSegX[nPart2][0]; yr3 = arrSegY[nPart2][0];
// Âû÷èñëÿåì ðàññòîÿíèå îò êîíòðîëüíûõ òî÷åê äî ñðåäíèõ òî÷åê ïðÿìîé ëèíèè. (Âû÷èñëåíèå íå ñîâñåì òî÷íîå, íî áûñòðîå)
Transform( matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my );
Transform( matrix, xx1, yy1, &tx, &ty );
dx = tx - mx;
dy = ty - my;
d1 = dx*dx + dy*dy;
Transform(matrix, xx2, yy2, &tx, &ty);
dx = tx - mx;
dy = ty - my;
d2 = dx*dx + dy*dy;
// Åñëè ñåãìåíò óæå äîñòàòî÷íî ïëîñêèé èëè áîëüøå äåëåíèé íåâîçîìæíî ñäåëàòü, äîáàâëÿåì ïðÿìóþ ëèíèþ
if ( nPart2 - nPart1 == 1 || ( d1 <= dFlatness_2 && d2 <= dFlatness_2 ) )
{
fPath->LineTo( xr3, yr3 );
nPart1 = nPart2;
}
else // otherwise, subdivide the curve
{
xl1 = (xl0 + xx1) * 0.5;
yl1 = (yl0 + yy1) * 0.5;
xh = (xx1 + xx2) * 0.5;
yh = (yy1 + yy2) * 0.5;
xl2 = (xl1 + xh) * 0.5;
yl2 = (yl1 + yh) * 0.5;
xr2 = (xx2 + xr3) * 0.5;
yr2 = (yy2 + yr3) * 0.5;
xr1 = (xh + xr2) * 0.5;
yr1 = (yh + yr2) * 0.5;
xr0 = (xl2 + xr1) * 0.5;
yr0 = (yl2 + yr1) * 0.5;
// add the new subdivision points
int nPart3 = (nPart1 + nPart2) / 2;
arrSegX[nPart1][1] = xl1; arrSegY[nPart1][1] = yl1;
arrSegX[nPart1][2] = xl2; arrSegY[nPart1][2] = yl2;
arrNext[nPart1] = nPart3;
arrSegX[nPart3][0] = xr0; arrSegY[nPart3][0] = yr0;
arrSegX[nPart3][1] = xr1; arrSegY[nPart3][1] = yr1;
arrSegX[nPart3][2] = xr2; arrSegY[nPart3][2] = yr2;
arrNext[nPart3] = nPart2;
}
}
}
inline void Transform(double *pMatrix, double dUserX, double dUserY, double *pdDeviceX, double *pdDeviceY)
{
*pdDeviceX = dUserX * pMatrix[0] + dUserY * pMatrix[2] + pMatrix[4];
*pdDeviceY = dUserX * pMatrix[1] + dUserY * pMatrix[3] + pMatrix[5];
}
inline void PipeInit(SPipe *pPipe, int nX, int nY, IAVSPattern* pPattern, SColorPointer pColorSrc, double dAlphaInput, BOOL bUsesShape, BOOL bNonIsolatedGroup)
{
PipeSetXY( pPipe, nX, nY );
pPipe->pPattern = NULL;
// Source color
if ( pPattern )
{
LONG lTypePattern = 0;
pPattern->get_Type(&lTypePattern);
if ( 1 == lTypePattern )
{
// íóæíî ñäåëàòü êîíñòàíòû
pPattern->GetPixel( nX, nY, (LONG*)pPipe->arrColorSrcVal );
}
else
{
pPipe->pPattern = pPattern;
}
pPipe->pColorSrc = pPipe->arrColorSrcVal;
}
else
{
pPipe->pColorSrc = pColorSrc;
}
// Source alpha
pPipe->dAlphaInput = dAlphaInput;
if ( !m_oSoftMask.m_pPixels )
{
if ( bUsesShape )
{
pPipe->dAlphaInput *= 255;
}
else
{
pPipe->unAlphaSrc = (unsigned char)round( pPipe->dAlphaInput * 255 );
}
}
pPipe->bUsesShape = bUsesShape;
// Result Alpha
if ( dAlphaInput == 1 && !m_oSoftMask.m_pPixels && !bUsesShape && !m_bInNonIsolatedGroup )
{
pPipe->bNoTransparency = TRUE;
}
else
{
pPipe->bNoTransparency = FALSE;
}
// Result Color
if ( pPipe->bNoTransparency )
{
pPipe->eResultColorCtrl = m_arrePipeResultColorNoAlphaBlend[m_oPixels.m_eMode];
}
else if ( !m_pBlendFunction )
{
pPipe->eResultColorCtrl = m_arrePipeResultColorAlphaNoBlend[m_oPixels.m_eMode];
}
else
{
pPipe->eResultColorCtrl = m_arrePipeResultColorAlphaBlend[m_oPixels.m_eMode];
}
// Non-isolated group correction
if ( bNonIsolatedGroup )
{
pPipe->nNonIsolatedGroup = SColorModeNComps[m_oPixels.m_eMode];
}
else
{
pPipe->nNonIsolatedGroup = 0;
}
}
inline void PipeRun(SPipe *pPipe)
{
unsigned char aSrc, aDest, alpha2, alpha0, aResult;
SColor cDest, cBlend;
unsigned char cResult0, cResult1, cResult2, cResult3;
//----- source color
// static pattern: handled in pipeInit
// dynamic pattern
if ( pPipe->pPattern )
{
pPipe->pPattern->GetPixel( pPipe->nX, pPipe->nY, (LONG*)pPipe->arrColorSrcVal );
}
if ( pPipe->bNoTransparency && !m_pBlendFunction )
{
//----- write destination pixel
BOOL bAlphaSet = FALSE;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
cResult0 = pPipe->pColorSrc[0];
if ( m_oScreen.GetGrayPixel( pPipe->nX, pPipe->nY, cResult0 ) )
{
*pPipe->pColorDst |= pPipe->nColorMaskDst;
}
else
{
*pPipe->pColorDst &= ~pPipe->nColorMaskDst;
}
if ( !(pPipe->nColorMaskDst >>= 1) )
{
pPipe->nColorMaskDst = 0x80;
++pPipe->pColorDst;
}
break;
case colorModeMono8:
*pPipe->pColorDst++ = pPipe->pColorSrc[0];
break;
case colorModeRGB8:
*pPipe->pColorDst++ = pPipe->pColorSrc[0];
*pPipe->pColorDst++ = pPipe->pColorSrc[1];
*pPipe->pColorDst++ = pPipe->pColorSrc[2];
break;
case colorModeBGR8:
*pPipe->pColorDst++ = pPipe->pColorSrc[2];
*pPipe->pColorDst++ = pPipe->pColorSrc[1];
*pPipe->pColorDst++ = pPipe->pColorSrc[0];
break;
case colorModeBGRA8:
*pPipe->pColorDst++ = pPipe->pColorSrc[2];
*pPipe->pColorDst++ = pPipe->pColorSrc[1];
*pPipe->pColorDst++ = pPipe->pColorSrc[0];
*pPipe->pColorDst++ = pPipe->pColorSrc[3];
bAlphaSet = TRUE;
pPipe->pAlphaDst += 4;
break;
case colorModeRGBA8:
*pPipe->pColorDst++ = pPipe->pColorSrc[0];
*pPipe->pColorDst++ = pPipe->pColorSrc[1];
*pPipe->pColorDst++ = pPipe->pColorSrc[2];
*pPipe->pColorDst++ = pPipe->pColorSrc[3];
bAlphaSet = TRUE;
pPipe->pAlphaDst += 4;
break;
}
if ( pPipe->pAlphaDst && !bAlphaSet )
{
*pPipe->pAlphaDst++ = 255;
}
}
else
{
//----- read destination pixel
BOOL bAlphaSet = FALSE;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
cDest[0] = (*pPipe->pColorDst & pPipe->nColorMaskDst) ? 0xff : 0x00;
break;
case colorModeMono8:
cDest[0] = *pPipe->pColorDst;
break;
case colorModeRGB8:
cDest[0] = pPipe->pColorDst[0];
cDest[1] = pPipe->pColorDst[1];
cDest[2] = pPipe->pColorDst[2];
break;
case colorModeBGR8:
cDest[0] = pPipe->pColorDst[2];
cDest[1] = pPipe->pColorDst[1];
cDest[2] = pPipe->pColorDst[0];
break;
case colorModeRGBA8:
cDest[0] = pPipe->pColorDst[0];
cDest[1] = pPipe->pColorDst[1];
cDest[2] = pPipe->pColorDst[2];
cDest[3] = pPipe->pColorDst[3];
aDest = *pPipe->pAlphaDst;
bAlphaSet = TRUE;
break;
case colorModeBGRA8:
cDest[0] = pPipe->pColorDst[2];
cDest[1] = pPipe->pColorDst[1];
cDest[2] = pPipe->pColorDst[0];
cDest[3] = pPipe->pColorDst[3];
aDest = *pPipe->pAlphaDst;
bAlphaSet = TRUE;
break;
}
if ( pPipe->pAlphaDst )
{
aDest = *pPipe->pAlphaDst;
}
else if(!bAlphaSet)
{
aDest = 0xFF;
}
//----- blend function
if ( m_pBlendFunction )
{
(*m_pBlendFunction)( pPipe->pColorSrc, cDest, cBlend, m_oPixels.m_eMode );
}
//----- source alpha
if ( m_oSoftMask.m_pPixels )
{
if ( pPipe->bUsesShape )
{
aSrc = (unsigned char)round( pPipe->dAlphaInput * *pPipe->pSMask++ * pPipe->dShape );
}
else
{
aSrc = (unsigned char)round( pPipe->dAlphaInput * *pPipe->pSMask++ );
}
}
else if ( pPipe->bUsesShape )
{
aSrc = (unsigned char)round( pPipe->dAlphaInput * pPipe->dShape );
}
else
{
aSrc = pPipe->unAlphaSrc;
}
//----- result alpha and non-isolated group element correction
if ( pPipe->bNoTransparency )
{
alpha2 = aResult = 255;
}
else
{
aResult = aSrc + aDest - Div255(aSrc * aDest);
if ( pPipe->pAlpha0 )
{
alpha0 = *pPipe->pAlpha0++;
alpha2 = aResult + alpha0 - Div255(aResult * alpha0);
}
else
{
alpha2 = aResult;
}
}
//----- result color
cResult0 = cResult1 = cResult2 = cResult3 = 0;
switch ( pPipe->eResultColorCtrl )
{
case PipeResultColorNoAlphaBlendRGB:
cResult2 = Div255((255 - aDest) * pPipe->pColorSrc[2] + aDest * cBlend[2]);
cResult1 = Div255((255 - aDest) * pPipe->pColorSrc[1] + aDest * cBlend[1]);
case PipeResultColorNoAlphaBlendMono:
cResult0 = Div255((255 - aDest) * pPipe->pColorSrc[0] + aDest * cBlend[0]);
break;
case PipeResultColorAlphaNoBlendMono:
if ( alpha2 == 0 )
{
cResult0 = 0;
}
else
{
cResult0 = (unsigned char)(((alpha2 - aSrc) * cDest[0] + aSrc * pPipe->pColorSrc[0]) / alpha2);
}
break;
case PipeResultColorAlphaNoBlendRGB:
if ( alpha2 == 0 )
{
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
}
else
{
cResult0 = (unsigned char)(((alpha2 - aSrc) * cDest[0] + aSrc * pPipe->pColorSrc[0]) / alpha2);
cResult1 = (unsigned char)(((alpha2 - aSrc) * cDest[1] + aSrc * pPipe->pColorSrc[1]) / alpha2);
cResult2 = (unsigned char)(((alpha2 - aSrc) * cDest[2] + aSrc * pPipe->pColorSrc[2]) / alpha2);
}
break;
case PipeResultColorAlphaBlendMono:
if ( alpha2 == 0 )
{
cResult0 = 0;
}
else
{
cResult0 = (unsigned char)(((alpha2 - aSrc) * cDest[0] + aSrc * ((255 - aDest) * pPipe->pColorSrc[0] + aDest * cBlend[0]) / 255) / alpha2);
}
break;
case PipeResultColorAlphaBlendRGB:
if ( alpha2 == 0 )
{
cResult0 = 0;
cResult1 = 0;
cResult2 = 0;
}
else
{
cResult0 = (unsigned char)(((alpha2 - aSrc) * cDest[0] + aSrc * ((255 - aDest) * pPipe->pColorSrc[0] + aDest * cBlend[0]) / 255) / alpha2);
cResult1 = (unsigned char)(((alpha2 - aSrc) * cDest[1] + aSrc * ((255 - aDest) * pPipe->pColorSrc[1] + aDest * cBlend[1]) / 255) / alpha2);
cResult2 = (unsigned char)(((alpha2 - aSrc) * cDest[2] + aSrc * ((255 - aDest) * pPipe->pColorSrc[2] + aDest * cBlend[2]) / 255) / alpha2);
}
break;
}
//----- non-isolated group correction
if ( aResult != 0 )
{
switch ( pPipe->nNonIsolatedGroup )
{
case 3:
cResult2 += (cResult2 - cDest[2]) * aDest * (255 - aResult) / (255 * aResult);
cResult1 += (cResult1 - cDest[1]) * aDest * (255 - aResult) / (255 * aResult);
case 1:
cResult0 += (cResult0 - cDest[0]) * aDest * (255 - aResult) / (255 * aResult);
case 0:
break;
}
}
//----- write destination pixel
bAlphaSet = FALSE;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
if ( m_oScreen.GetGrayPixel(pPipe->nX, pPipe->nY, cResult0) )
{
*pPipe->pColorDst |= pPipe->nColorMaskDst;
}
else
{
*pPipe->pColorDst &= ~pPipe->nColorMaskDst;
}
if ( !( pPipe->nColorMaskDst >>= 1 ) )
{
pPipe->nColorMaskDst = 0x80;
++pPipe->pColorDst;
}
break;
case colorModeMono8:
*pPipe->pColorDst++ = cResult0;
break;
case colorModeRGB8:
*pPipe->pColorDst++ = cResult0;
*pPipe->pColorDst++ = cResult1;
*pPipe->pColorDst++ = cResult2;
break;
case colorModeBGR8:
*pPipe->pColorDst++ = cResult2;
*pPipe->pColorDst++ = cResult1;
*pPipe->pColorDst++ = cResult0;
case colorModeRGBA8:
*pPipe->pColorDst++ = cResult0;
*pPipe->pColorDst++ = cResult1;
*pPipe->pColorDst++ = cResult2;
*pPipe->pColorDst++ = aResult;
bAlphaSet = TRUE;
pPipe->pAlphaDst += 4;
break;
case colorModeBGRA8:
*pPipe->pColorDst++ = cResult2;
*pPipe->pColorDst++ = cResult1;
*pPipe->pColorDst++ = cResult0;
*pPipe->pColorDst++ = aResult;
bAlphaSet = TRUE;
pPipe->pAlphaDst += 4;
break;
}
if ( pPipe->pAlphaDst && !bAlphaSet )
{
*pPipe->pAlphaDst++ = aResult;
}
}
++pPipe->nX;
}
inline void PipeSetXY(SPipe *pPipe, int nX, int nY)
{
pPipe->nX = nX;
pPipe->nY = nY;
if ( NULL != m_oSoftMask.m_pPixels )
{
pPipe->pSMask = &m_oSoftMask.m_pPixels[nY * m_oSoftMask.m_lStride + nX];
}
LONG lStride = m_oPixels.m_lStride;
BOOL bIsUseAlpha = FALSE;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
pPipe->pColorDst = &m_oPixels.m_pPixels[nY * lStride + (nX >> 3)];
pPipe->nColorMaskDst = 0x80 >> (nX & 7);
break;
case colorModeMono8:
pPipe->pColorDst = &m_oPixels.m_pPixels[nY * lStride + nX];
break;
case colorModeRGB8:
case colorModeBGR8:
pPipe->pColorDst = &m_oPixels.m_pPixels[nY * lStride + 3 * nX];
break;
case colorModeRGBA8:
case colorModeBGRA8:
pPipe->pColorDst = &m_oPixels.m_pPixels[nY * lStride + 4 * nX];
pPipe->pAlphaDst = &m_oPixels.m_pPixels[nY * lStride + 4 * nX + 3];
bIsUseAlpha = TRUE;
break;
}
if ( m_oPixels.m_pAlpha )
{
pPipe->pAlphaDst = &m_oPixels.m_pPixels[nY * m_oPixels.m_lWidth + nX];
}
else if (!bIsUseAlpha)
{
pPipe->pAlphaDst = NULL;
}
if ( m_bInNonIsolatedGroup && m_oAlpha0Bitmap.m_pAlpha )
{
pPipe->pAlpha0 = &m_oAlpha0Bitmap.m_pAlpha[( m_nAlpha0Y + nY ) * m_oAlpha0Bitmap.m_lWidth + ( m_nAlpha0X + nX )];
}
else
{
pPipe->pAlpha0 = NULL;
}
}
inline void PipeIncreaseX(SPipe *pPipe)
{
++pPipe->nX;
if ( m_oSoftMask.m_pPixels )
{
++pPipe->pSMask;
}
BOOL bAlphaSet = FALSE;
switch ( m_oPixels.m_eMode )
{
case colorModeMono1:
if ( !( pPipe->nColorMaskDst >>= 1 ) )
{
pPipe->nColorMaskDst = 0x80;
++pPipe->pColorDst;
}
break;
case colorModeMono8:
++pPipe->pColorDst;
break;
case colorModeRGB8:
case colorModeBGR8:
pPipe->pColorDst += 3;
break;
case colorModeRGBA8:
case colorModeBGRA8:
pPipe->pColorDst += 4;
pPipe->pAlphaDst += 4;
bAlphaSet = TRUE;
break;
}
if ( pPipe->pAlphaDst && !bAlphaSet )
{
++pPipe->pAlphaDst;
}
if ( pPipe->pAlpha0 )
{
++pPipe->pAlpha0;
}
}
inline void DrawPixel(SPipe *pPipe, int nX, int nY, BOOL bNoClip)
{
if ( bNoClip || m_oClip.IsInsideClip( nX, nY ) )
{
PipeSetXY( pPipe, nX, nY );
PipeRun( pPipe );
UpdateModX( nX );
UpdateModY( nY );
}
}
inline void UpdateModX(int nX)
{
if ( nX < m_nModRegMinX )
{
m_nModRegMinX = nX;
}
if ( nX > m_nModRegMaxX )
{
m_nModRegMaxX = nX;
}
}
inline void UpdateModY(int nY)
{
if ( nY < m_nModRegMinY )
{
m_nModRegMinY = nY;
}
if ( nY > m_nModRegMaxY )
{
m_nModRegMaxY = nY;
}
}
void ClearModRegion()
{
m_nModRegMinX = m_oPixels.m_lWidth;
m_nModRegMinY = m_oPixels.m_lHeight;
m_nModRegMaxX = -1;
m_nModRegMaxY = -1;
}
inline void DrawAAPixelInit()
{
m_nAABufferY = -1;
}
inline void DrawAAPixel(SPipe* pPipe, int nX, int nY)
{
static int arrnBitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
if ( nX < 0 || nX >= m_oPixels.m_lWidth || nY < m_oClip.GetMinY() || nY > m_oClip.GetMaxY() )
{
return;
}
// Ïåðåñ÷èòûâàåì m_nAABufferY
if ( nY != m_nAABufferY )
{
memset( m_oAABuffer.m_pPixels, 0xFF, m_oAABuffer.m_lStride * m_oAABuffer.m_lHeight );
int nX0 = 0;
int nX1 = m_oPixels.m_lWidth - 1;
m_oClip.ClipAALine( &m_oAABuffer, &nX0, &nX1, nY );
m_nAABufferY = nY;
}
SColorPointer pColor = m_oAABuffer.m_pPixels + (nX >> 1);
int nStride = m_oAABuffer.m_lStride;
int nTemp = 0;
if ( nX & 1 )
{
nTemp = arrnBitCount4[*pColor & 0x0f] + arrnBitCount4[pColor[nStride] & 0x0f] + arrnBitCount4[pColor[2 * nStride] & 0x0f] + arrnBitCount4[pColor[3 * nStride] & 0x0f];
}
else
{
nTemp = arrnBitCount4[*pColor >> 4] + arrnBitCount4[pColor[nStride] >> 4] + arrnBitCount4[pColor[2 * nStride] >> 4] + arrnBitCount4[pColor[3 * nStride] >> 4];
}
// Ðèñóåì äàííûé ïèêñåëü
if ( nTemp != 0 )
{
PipeSetXY( pPipe, nX, nY );
pPipe->dShape *= m_arrdAAGamma[nTemp];
PipeRun( pPipe );
UpdateModX( nX );
UpdateModY( nY );
}
}
inline void DrawSpan(SPipe *pPipe, int nX0, int nX1, int nY, BOOL bNoClip)
{
PipeSetXY( pPipe, nX0, nY );
if ( bNoClip )
{
for ( int nX = nX0; nX <= nX1; ++nX )
{
PipeRun( pPipe );
}
UpdateModX( nX0 );
UpdateModX( nX1 );
UpdateModY( nY );
}
else
{
for ( int nX = nX0; nX <= nX1; ++nX )
{
if ( m_oClip.IsInsideClip( nX, nY ) )
{
PipeRun( pPipe );
UpdateModX( nX );
UpdateModY( nY );
}
else
{
PipeIncreaseX( pPipe );
}
}
}
}
inline void DrawAALine(SPipe *pPipe, int nX0, int nX1, int nY)
{
static int arrnBitCount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
SColorPointer pLine0 = m_oAABuffer.m_pPixels + (nX0 >> 1);
LONG lStride = m_oAABuffer.m_lStride;
SColorPointer pLine1 = pLine0 + lStride;
SColorPointer pLine2 = pLine1 + lStride;
SColorPointer pLine3 = pLine2 + lStride;
PipeSetXY( pPipe, nX0, nY );
for ( int nX = nX0; nX <= nX1; ++nX )
{
int nTemp = 0;
if ( nX & 1 )
{
nTemp = arrnBitCount4[*pLine0 & 0x0f] + arrnBitCount4[*pLine1 & 0x0f] + arrnBitCount4[*pLine2 & 0x0f] + arrnBitCount4[*pLine3 & 0x0f];
++pLine0; ++pLine1; ++pLine2; ++pLine3;
}
else
{
nTemp = arrnBitCount4[*pLine0 >> 4] + arrnBitCount4[*pLine1 >> 4] + arrnBitCount4[*pLine2 >> 4] + arrnBitCount4[*pLine3 >> 4];
}
if ( nTemp != 0 )
{
pPipe->dShape = m_arrdAAGamma[nTemp];
PipeRun( pPipe );
UpdateModX( nX );
UpdateModY( nY );
}
else
{
PipeIncreaseX( pPipe );
}
}
}
int FillGlyph(int nX, int nY, TGlyphBitmap *pGlyph, IAVSPattern* pPattern, double dFillAlpha)
{
SPipe oPipe;
SClipResult eClipResult;
//if ( ( eClipResult = m_oClip.CheckRectangle( nX - pGlyph->nX, nY - pGlyph->nY, nX - pGlyph->nX + pGlyph->nWidth - 1, nY - pGlyph->nY + pGlyph->nHeight - 1 ) ) != clipAllOutside )
if ( ( eClipResult = m_oClip.CheckRectangle( nX, nY, nX + pGlyph->nWidth - 1, nY + pGlyph->nHeight - 1 ) ) != clipAllOutside )
{
BOOL bNoClip = (eClipResult == clipAllInside);
if ( bNoClip )
{
if ( pGlyph->bAA )
{
/*PipeInit( &oPipe, nX - pGlyph->nX, nY - pGlyph->nY, pPattern, NULL, dFillAlpha, TRUE, FALSE );
unsigned char *pData = pGlyph->pData;
for ( int nYY = 0, nY1 = nY - pGlyph->nY; nYY < pGlyph->nHeight; ++nYY, ++nY1 )
{
PipeSetXY( &oPipe, nX - pGlyph->nX, nY1 );
for ( int nXX = 0, nX1 = nX - pGlyph->nX; nXX < pGlyph->nWidth; ++nXX, ++nX1 )
{
int nAlpha = *pData++;
if ( nAlpha != 0 )
{
oPipe.dShape = (double)(nAlpha / 255.0);
PipeRun( &oPipe );
UpdateModX( nX1 );
UpdateModY( nY1 );
}
else
{
PipeIncreaseX( &oPipe );
}
}
}*/
PipeInit( &oPipe, nX, nY, pPattern, NULL, dFillAlpha, TRUE, FALSE );
unsigned char *pData = pGlyph->pData;
for ( int nYY = 0, nY1 = nY; nYY < pGlyph->nHeight; ++nYY, ++nY1 )
{
PipeSetXY( &oPipe, nX, nY1 );
for ( int nXX = 0, nX1 = nX; nXX < pGlyph->nWidth; ++nXX, ++nX1 )
{
int nAlpha = *pData++;
if ( nAlpha != 0 )
{
oPipe.dShape = (double)(nAlpha / 255.0);
PipeRun( &oPipe );
UpdateModX( nX1 );
UpdateModY( nY1 );
}
else
{
PipeIncreaseX( &oPipe );
}
}
}
}
else
{
PipeInit( &oPipe, nX - pGlyph->nX, nY - pGlyph->nY, pPattern, NULL, dFillAlpha, FALSE, FALSE );
unsigned char *pData = pGlyph->pData;
for ( int nYY = 0, nY1 = nY - pGlyph->nY; nYY < pGlyph->nHeight; ++nYY, ++nY1 )
{
PipeSetXY( &oPipe, nX - pGlyph->nX, nY1);
for ( int nXX = 0, nX1 = nX - pGlyph->nX; nXX < pGlyph->nWidth; nXX += 8 )
{
int nAlpha0 = *pData++;
for ( int nXX1 = 0; nXX1 < 8 && nXX + nXX1 < pGlyph->nWidth; ++nXX1, ++nX1 )
{
if ( nAlpha0 & 0x80 )
{
PipeRun( &oPipe );
UpdateModX( nX1 );
UpdateModY( nY1 );
}
else
{
PipeIncreaseX( &oPipe );
}
nAlpha0 <<= 1;
}
}
}
}
}
else
{
if ( pGlyph->bAA )
{
PipeInit( &oPipe, nX - pGlyph->nX, nY - pGlyph->nY, pPattern, NULL, dFillAlpha, TRUE, FALSE );
unsigned char *pData = pGlyph->pData;
for ( int nYY = 0, nY1 = nY - pGlyph->nY; nYY < pGlyph->nHeight; ++nYY, ++nY1 )
{
PipeSetXY( &oPipe, nX - pGlyph->nX, nY1 );
for ( int nXX = 0, nX1 = nX - pGlyph->nX; nXX < pGlyph->nWidth; ++nXX, ++nX1 )
{
if ( m_oClip.IsInsideClip( nX1, nY1 ) )
{
int nAlpha = *pData++;
if ( nAlpha != 0 )
{
oPipe.dShape = (double)(nAlpha / 255.0);
PipeRun( &oPipe );
UpdateModX( nX1 );
UpdateModY( nY1 );
}
else
{
PipeIncreaseX( &oPipe );
}
}
else
{
PipeIncreaseX( &oPipe );
++pData;
}
}
}
}
else
{
PipeInit( &oPipe, nX - pGlyph->nX, nY - pGlyph->nY, pPattern, NULL, dFillAlpha, FALSE, FALSE );
unsigned char *pData = pGlyph->pData;
for ( int nYY = 0, nY1 = nY - pGlyph->nY; nYY < pGlyph->nHeight; ++nYY, ++nY1 )
{
PipeSetXY( &oPipe, nX - pGlyph->nX, nY1 );
for ( int nXX = 0, nX1 = nX - pGlyph->nX; nXX < pGlyph->nWidth; nXX += 8 )
{
int nAlpha0 = *pData++;
for ( int nXX1 = 0; nXX1 < 8 && nXX + nXX1 < pGlyph->nWidth; ++nXX1, ++nX1 )
{
if ( m_oClip.IsInsideClip( nX1, nY1 ) )
{
if ( nAlpha0 & 0x80 )
{
PipeRun( &oPipe );
UpdateModX( nX1 );
UpdateModY( nY1 );
}
else
{
PipeIncreaseX( &oPipe );
}
}
else
{
PipeIncreaseX( &oPipe );
}
nAlpha0 <<= 1;
}
}
}
}
}
}
m_pOpClipRes = eClipResult;
return SNoError;
}
void SetUpMatrix(double* pElements)
{
Gdiplus::Matrix oMatrix;
oMatrix.Multiply(&m_oCoordTransform, Gdiplus::MatrixOrderAppend);
oMatrix.Multiply(&m_oBaseTransform, Gdiplus::MatrixOrderAppend);
oMatrix.Multiply(&m_oTransform, Gdiplus::MatrixOrderAppend);
float mass[6];
oMatrix.GetElements(mass);
pElements[0] = (double)mass[0];
pElements[1] = (double)mass[1];
pElements[2] = (double)mass[2];
pElements[3] = (double)mass[3];
pElements[4] = (double)mass[4];
pElements[5] = (double)mass[5];
}
void GetElements(double* mass)
{
Gdiplus::Matrix oMatrix;
oMatrix.Multiply(&m_oCoordTransform, Gdiplus::MatrixOrderAppend);
oMatrix.Multiply(&m_oBaseTransform, Gdiplus::MatrixOrderAppend);
oMatrix.Multiply(&m_oTransform, Gdiplus::MatrixOrderAppend);
float massR[6];
oMatrix.GetElements(massR);
mass[0] = (double)massR[0];
mass[1] = (double)massR[1];
mass[2] = (double)massR[2];
mass[3] = (double)massR[3];
mass[4] = (double)massR[4];
mass[5] = (double)massR[5];
}
void UpdateUnits()
{
// çäåñü - ïåðåñ÷åò êîîðäèíàò
m_oCoordTransform.Reset();
double dScaleX = 1.0;
double dScaleY = 1.0;
switch (m_lPageUnits)
{
case c_ag_PageUnitPoint:
{
dScaleX = m_dDpiX / c_ag_Inch_to_Point;
dScaleY = m_dDpiY / c_ag_Inch_to_Point;
break;
}
case c_ag_PageUnitMillimeter:
{
dScaleX = m_dDpiX / c_ag_Inch_to_MM;
dScaleY = m_dDpiY / c_ag_Inch_to_MM;
break;
}
case c_ag_PageUnitInch:
{
dScaleX = m_dDpiX;
dScaleY = m_dDpiY;
break;
}
default:
break;
};
m_oCoordTransform.Scale((float)dScaleX, (float)dScaleY, Gdiplus::MatrixOrderAppend);
}
friend class CAVSGraphicsPath;
friend class CGraphicsPath;
friend class CAVSMatrix;
friend class SXPath;
friend class SPath;
friend class CAVSGlyphImage;
};
SPipeResultColorCtrl CAVSGraphics::m_arrePipeResultColorNoAlphaBlend[] =
{
PipeResultColorNoAlphaBlendMono, // 1 bit
PipeResultColorNoAlphaBlendMono, // 8 bit
PipeResultColorNoAlphaBlendRGB, // 24 bit RGB
PipeResultColorNoAlphaBlendRGB, // 24 bit BGR
PipeResultColorNoAlphaBlendRGB, // 24 bit RGB
PipeResultColorNoAlphaBlendRGB // 24 bit BGR
};
SPipeResultColorCtrl CAVSGraphics::m_arrePipeResultColorAlphaNoBlend[] =
{
PipeResultColorAlphaNoBlendMono, // 1 bit
PipeResultColorAlphaNoBlendMono, // 8 bit
PipeResultColorAlphaNoBlendRGB, // 24 bit RGB
PipeResultColorAlphaNoBlendRGB,
PipeResultColorAlphaNoBlendRGB, // 24 bit RGB
PipeResultColorAlphaNoBlendRGB // 24 bit BGR
};
SPipeResultColorCtrl CAVSGraphics::m_arrePipeResultColorAlphaBlend[] =
{
PipeResultColorAlphaBlendMono, // 1 bit
PipeResultColorAlphaBlendMono, // 8 bit
PipeResultColorAlphaBlendRGB, // 24 bit RGB
PipeResultColorAlphaBlendRGB, // 24 bit BGR
PipeResultColorNoAlphaBlendRGB, // 24 bit RGB
PipeResultColorNoAlphaBlendRGB // 24 bit BGR
};