mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 06:22:44 +08:00
303 lines
9.3 KiB
C
303 lines
9.3 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;
|
|
}
|
|
} |