/* * (c) Copyright Ascensio System SIA 2010-2014 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, * EU, LV-1021. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ #pragma once #include #include #include #include "streamutils.h" #include "xmlutils.h" #include "atldefine.h" #include "GdiplusEx.h" namespace Painter { const int c_BrushTypeSolid_ = 0; const int c_BrushTypeHorizontal_ = 1; const int c_BrushTypeVertical_ = 2; const int c_BrushTypeDiagonal1_ = 3; const int c_BrushTypeDiagonal2_ = 4; const int c_BrushTypeCenter_ = 5; const int c_BrushTypePathGradient1_ = 6; const int c_BrushTypePathGradient2_ = 7; const int c_BrushTypeTexture_ = 8; const int c_BrushTypeHatch1_ = 9; const int c_BrushTypeHatch53_ = 61; const int c_BrushTypeGradient1_ = 62; const int c_BrushTypeGradient6_ = 70; const int c_BrushTypeSolid = 1000; const int c_BrushTypeHorizontal = 2001; const int c_BrushTypeVertical = 2002; const int c_BrushTypeDiagonal1 = 2003; const int c_BrushTypeDiagonal2 = 2004; const int c_BrushTypeCenter = 2005; const int c_BrushTypePathGradient1 = 2006; const int c_BrushTypePathGradient2 = 2007; const int c_BrushTypeCylinderHor = 2008; const int c_BrushTypeCylinderVer = 2009; const int c_BrushTypeTexture = 3008; const int c_BrushTypeHatch1 = 4009; const int c_BrushTypeHatch53 = 4061; const int c_BrushTextureModeStretch = 0; const int c_BrushTextureModeTile = 1; const int c_BrushTextureModeTileCenter = 2; const int c_AlphModeDoNothing = 0; const int c_AlphModeReplaceWithBrushAlpha = 1; const int c_AlphModeCombine = 2; inline int ConstantCompatible(int nConstant) { if( c_BrushTypeDiagonal1_ == nConstant ) nConstant = c_BrushTypeDiagonal2_; else if( c_BrushTypeDiagonal2_ == nConstant ) nConstant = c_BrushTypeDiagonal1_; if (1000 <= nConstant) return nConstant; if (c_BrushTypeSolid_ == nConstant) return nConstant + 1000; if (c_BrushTypeHorizontal_ <= nConstant && c_BrushTypePathGradient2_ >= nConstant) return nConstant + 2000; if (c_BrushTypeTexture_ == nConstant) return nConstant + 3000; if (c_BrushTypeHatch1_ <= nConstant && c_BrushTypeHatch53_ >= nConstant) return nConstant + 4000; if (c_BrushTypeGradient1_ <= nConstant && c_BrushTypeGradient6_ >= nConstant) return nConstant + 2000 - 61; return 1000; } inline BOOL IsBrushTypeGradient(int nType) { int nCompatibleType = ConstantCompatible(nType); return (nCompatibleType >= Painter::c_BrushTypeHorizontal && nCompatibleType <= Painter::c_BrushTypeCylinderVer); } inline void DrawBlurString(int currentBlurSize, Graphics* Gr, Gdiplus::Font* font, StringFormat* format, Brush* brush, BSTR Text, int len, RectF& rect) { for(int j = 0; j < currentBlurSize; j++) { rect.X += 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.Y += 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.X -= 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.X -= 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.Y -= 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.Y -= 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.X += 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.X += 1; Gr->DrawString(Text, len, font, rect, format, brush); } for(int j = 0; j < currentBlurSize; j++) { rect.Y += 1; Gr->DrawString(Text, len, font, rect, format, brush); } } inline void GetRectCurrentCharacter(Gdiplus::Graphics* graphics, Gdiplus::StringFormat* stringFormat, Gdiplus::Font* font, BSTR Text, int length, int index, Gdiplus::RectF& rectString, Gdiplus::RectF& rectCharacter) { CharacterRange charRanges[1] = {CharacterRange(index, 1)}; Region pCharRangeRegions; stringFormat->SetMeasurableCharacterRanges(1, charRanges); graphics->MeasureCharacterRanges(Text, length, font, rectString, stringFormat, 1, &pCharRangeRegions); int count = 1; Matrix matrix; pCharRangeRegions.GetRegionScans(&matrix, &rectCharacter, &count); } class CStream { protected: BYTE* m_pBuffer; int m_nOrigin; public: CStream() { m_pBuffer = 0; m_nOrigin = 0; } inline BOOL IsValid() const { if (m_pBuffer) return TRUE; return FALSE; } BYTE*& GetBuffer() { return m_pBuffer; } void SetBuffer(BYTE* pBuffer) { m_pBuffer = pBuffer; } void Seek(int nOrigin = 0) { m_nOrigin = nOrigin; } int GetPosition() { return m_nOrigin; } BYTE* GetData() { return m_pBuffer + m_nOrigin; } BYTE ReadByte() { int nOldOrigin = m_nOrigin; m_nOrigin += sizeof(BYTE); return *(BYTE*)(m_pBuffer + nOldOrigin); } short ReadShort() { int nOldOrigin = m_nOrigin; m_nOrigin += sizeof(short); return *(short*)(m_pBuffer + nOldOrigin); } long ReadLong() { int nOldOrigin = m_nOrigin; m_nOrigin += sizeof(long); return *(long*)(m_pBuffer + nOldOrigin); } double ReadDouble() { int nOldOrigin = m_nOrigin; m_nOrigin += sizeof(double); return *(double*)(m_pBuffer + nOldOrigin); } float ReadFloat() { int nOldOrigin = m_nOrigin; m_nOrigin += sizeof(float); return *(float*)(m_pBuffer + nOldOrigin); } CString ReadString() { int nOldOrigin = m_nOrigin; while (TRUE) { m_nOrigin++; if (m_pBuffer[m_nOrigin - 1] == 0) break; } return CString((char*)(m_pBuffer + nOldOrigin)); } BYTE* ReadPointer(int nSize) { int nOldOrigin = m_nOrigin; m_nOrigin += nSize; return (BYTE*)(m_pBuffer + nOldOrigin); } void WriteByte(BYTE nValue) { memcpy(m_pBuffer + m_nOrigin, &nValue, sizeof(BYTE)); m_nOrigin += sizeof(BYTE); } void WriteShort(short nValue) { memcpy(m_pBuffer + m_nOrigin, &nValue, sizeof(short)); m_nOrigin += sizeof(short); } void WriteLong(long nValue) { memcpy(m_pBuffer + m_nOrigin, &nValue, sizeof(long)); m_nOrigin += sizeof(long); } void WriteDouble(double dValue) { memcpy(m_pBuffer + m_nOrigin, &dValue, sizeof(double)); m_nOrigin += sizeof(double); } void WriteFloat(float fValue) { memcpy(m_pBuffer + m_nOrigin, &fValue, sizeof(float)); m_nOrigin += sizeof(float); } void WriteString(CString strValue) { TCHAR* pstr = strValue.GetBuffer(); memcpy(m_pBuffer + m_nOrigin, pstr, strValue.GetLength()); m_nOrigin += strValue.GetLength(); m_pBuffer[m_nOrigin] = 0; m_nOrigin += sizeof(_T("0")); } void WritePointer(BYTE* pData, int nSize) { memcpy(m_pBuffer + m_nOrigin, pData, nSize); m_nOrigin += nSize; } }; class CBuffer { BYTE* m_pBuffer; int m_nSize; public: CBuffer() { m_nSize = 0; m_pBuffer = 0; } ~CBuffer() { if (m_pBuffer) delete[] m_pBuffer; } }; class CTexture { public: Gdiplus::Bitmap* Bitmap; CString Path; BYTE* BitmapData; BOOL bFlipVertical; BOOL bAttach; int nWidth; int nHeight; int nStride; public: CTexture() { Path = ""; Bitmap = 0; BitmapData = 0; bFlipVertical = FALSE; bAttach = FALSE; nWidth = 0; nHeight = 0; nStride = 0; } ~CTexture() { Clear(); } void Clear() { if (Bitmap) { delete Bitmap; Bitmap = 0; } if( FALSE == bAttach ) { if (BitmapData) { delete[] BitmapData; BitmapData = 0; } } Path = ""; bFlipVertical = FALSE; bAttach = FALSE; nWidth = 0; nHeight = 0; nStride = 0; } BOOL Create(CString path, BOOL bFlip = FALSE) { Clear(); BSTR bstr = path.AllocSysString(); Bitmap = new Gdiplus::Bitmap(bstr); SysFreeString(bstr); if (!Bitmap || Bitmap->GetLastStatus() != Ok) return FALSE; RectF boundsRect; Unit unit; Bitmap->GetBounds(&boundsRect, &unit); nWidth = int(boundsRect.Width + 0.5); nHeight = int(boundsRect.Height + 0.5); Path = path; bFlipVertical = bFlip; if (bFlip) Bitmap->RotateFlip(RotateNoneFlipY); return TRUE; } BOOL SetImage(CString Name, SAFEARRAY* pImage) { if (NULL == pImage) return FALSE; VARTYPE type; long lBoundC, uBoundC; long lBoundW, uBoundW; long lBoundH, uBoundH; if (SafeArrayGetDim(pImage) != 3) return FALSE; if (FAILED(SafeArrayGetVartype(pImage, &type)) || type != VT_UI1 || SafeArrayGetElemsize(pImage) != 1) return FALSE; if (FAILED(SafeArrayGetLBound(pImage, 1, &lBoundC)) || FAILED(SafeArrayGetUBound(pImage, 1, &uBoundC)) || FAILED(SafeArrayGetLBound(pImage, 2, &lBoundW)) || FAILED(SafeArrayGetUBound(pImage, 2, &uBoundW)) || FAILED(SafeArrayGetLBound(pImage, 3, &lBoundH)) || FAILED(SafeArrayGetUBound(pImage, 3, &uBoundH))) return FALSE; int Channels = 1 + uBoundC - lBoundC; int Width = 1 + uBoundW - lBoundW; int Height = 1 + uBoundH - lBoundH; if (Channels != 4 || Width < 2 || Height < 2) return FALSE; Clear(); int sizeImage = 4*Width*Height; BitmapData = new BYTE[sizeImage]; memcpy(BitmapData,(BYTE*)((pImage)->pvData), sizeImage); Bitmap = new Gdiplus::Bitmap(Width, Height, Width*4, PixelFormat32bppARGB, BitmapData); Bitmap->RotateFlip(RotateNoneFlipY); Path = Name; bAttach = FALSE; nWidth = Width; nHeight = Height; nStride = 4*Width; return TRUE; } }; class CTextureManager { CAtlArray m_textures; public: ~CTextureManager() { Clear(); } int GetCount() { return (int)m_textures.GetCount(); } CTexture* GetAt(int index) { if (index < 0 || index >= GetCount()) return 0; return m_textures[index]; } CTexture* operator[] (int index) { return GetAt(index); } int Find(CString path) { path.MakeLower(); for (int index = 0; index < GetCount(); ++index) { if (m_textures[index]->Path == path) return index; } return -1; } void Clear() { for (int index = 0; index < GetCount(); ++index) { CTexture* texture = m_textures[index]; if (texture) delete texture; } m_textures.RemoveAll(); } void RemoveAt(int index) { if (index < 0 || index >= GetCount()) return; CTexture* texture = m_textures[index]; if (texture) delete texture; m_textures.RemoveAt(index); } long Add(CString path) { path.MakeLower(); int index = Find(path); if (index >= 0) return index; CTexture* texture = new CTexture(); if (!texture->Create(path)) { delete texture; return -1; } m_textures.Add(texture); return GetCount() - 1; } long Add(CString path, BOOL bVerticalFlip) { path.MakeLower(); int index = Find(path); if (index >= 0) return index; CTexture* texture = new CTexture(); if (!texture->Create(path, bVerticalFlip)) { delete texture; return -1; } m_textures.Add(texture); return GetCount() - 1; } long Add(CString Name, SAFEARRAY* pImage) { Name.MakeLower(); int index = Find(Name); if (index >= 0) return index; CTexture* texture = new CTexture(); if (!texture->SetImage(Name, pImage)) { delete texture; return -1; } m_textures.Add(texture); return GetCount() - 1; } long Add( CTexture* pTexture ) { if( !pTexture ) return -1; int index = Find( pTexture->Path ); if( index >= 0 ) return index; m_textures.Add( pTexture ); return GetCount() - 1; } }; class CPen { Gdiplus::Pen* m_pen; public: long Color; long Alpha; double Size; byte DashStyle; byte LineStartCap; byte LineEndCap; byte LineJoin; REAL* DashPattern; long Count; REAL DashOffset; PenAlignment Align; public: int GetSize() { return 2*sizeof(long) + sizeof(double) + 4*sizeof(byte) + sizeof(REAL*) + sizeof(long) + sizeof(REAL); } void Write(CStream& stream) { stream.WriteLong(Color); stream.WriteLong(Alpha); stream.WriteDouble(Size); stream.WriteByte(DashStyle); stream.WriteByte(LineStartCap); stream.WriteByte(LineEndCap); stream.WriteByte(LineJoin); stream.WriteLong(Count); if (DashPattern != NULL) { for (int i = 0; i < Count; ++i) { stream.WriteFloat(DashPattern[i]); } } stream.WriteFloat(DashOffset); } void Read(CStream& stream) { Color = stream.ReadLong(); Alpha = stream.ReadLong(); Size = stream.ReadDouble(); DashStyle = stream.ReadByte(); LineStartCap = stream.ReadByte(); LineEndCap = stream.ReadByte(); LineJoin = stream.ReadByte(); Count = stream.ReadLong(); RELEASEARRAYOBJECTS(DashPattern); if (Count != 0) { DashPattern = new REAL[Count]; for (int i = 0; i < Count; ++i) { DashPattern[i] = stream.ReadFloat(); } } DashOffset = stream.ReadFloat(); Update(); } CString ToXmlString(CString strRootNodeName = _T("pen"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("color"), Color); oXmlWriter.WriteNode(_T("alpha"), Alpha); oXmlWriter.WriteNode(_T("size"), Size); oXmlWriter.WriteNode(_T("style"), DashStyle); oXmlWriter.WriteNode(_T("line-start-cap"), LineStartCap); oXmlWriter.WriteNode(_T("line-end-cap"), LineEndCap); oXmlWriter.WriteNode(_T("line-join"), LineJoin); oXmlWriter.WriteNode(_T("dash-pattern-count"), Count); oXmlWriter.WriteNodeBegin(_T("dash-pattern")); if (DashPattern != NULL) { for (int i = 0; i < Count; ++i) { oXmlWriter.WriteNode(_T("dash"), DashPattern[i]); } } oXmlWriter.WriteNodeEnd(_T("dash-pattern")); oXmlWriter.WriteNode(_T("dash-offset"), DashOffset); oXmlWriter.WriteNode(_T("alignment"), Align); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { Color = pStream->ReadLong(); Alpha = pStream->ReadLong(); Size = pStream->ReadDouble(); DashStyle = pStream->ReadByte(); LineStartCap = pStream->ReadByte(); LineEndCap = pStream->ReadByte(); LineJoin = pStream->ReadByte(); Count = pStream->ReadLong(); RELEASEARRAYOBJECTS(DashPattern); if (Count > 0) { DashPattern = new REAL[Count]; for (int i = 0; i < Count; ++i) { DashPattern[i] = pStream->ReadFloat(); } } DashOffset = pStream->ReadFloat(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteLong(Color); pStream->WriteLong(Alpha); pStream->WriteDouble(Size); pStream->WriteByte(DashStyle); pStream->WriteByte(LineStartCap); pStream->WriteByte(LineEndCap); pStream->WriteByte(LineJoin); pStream->WriteLong(Count); if (DashPattern != NULL) { for (int i = 0; i < Count; ++i) { pStream->WriteFloat(DashPattern[i]); } } pStream->WriteFloat(DashOffset); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("color"), Color); oXmlWriter.WriteAttribute(_T("alpha"), Alpha); oXmlWriter.WriteAttribute(_T("size"), Size); oXmlWriter.WriteAttribute(_T("style"), DashStyle); oXmlWriter.WriteAttribute(_T("line-start-cap"), LineStartCap); oXmlWriter.WriteAttribute(_T("line-end-cap"), LineEndCap); oXmlWriter.WriteAttribute(_T("line-join"), LineJoin); oXmlWriter.WriteAttribute(_T("dash-offset"), DashOffset); oXmlWriter.WriteAttribute(_T("alignment"), Align); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { Color = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("alpha"), _T("0"))); Size = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("size"), _T("0"))); DashStyle = (byte)XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("style"), _T("0"))); LineStartCap = (byte)XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("line-start-cap"), _T("0"))); LineEndCap = (byte)XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("line-end-cap"), _T("0"))); LineJoin = (byte)XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("line-join"), _T("0"))); RELEASEARRAYOBJECTS(DashPattern); Count = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("dash-pattern-count"), _T("0"))); if (Count != 0) { XmlUtils::CXmlNode oPatternNode; oXmlReader.ReadNodeList(_T("dash-pattern")); if (oPatternNode.FromXmlString(oXmlReader.ReadNodeXml(0))) { XmlUtils::CXmlNodes oDashNodes; if (oPatternNode.GetNodes(_T("dash"), oDashNodes)) { Count = oDashNodes.GetCount(); if (Count != 0) { DashPattern = new REAL[Count]; XmlUtils::CXmlNode oDashNode; for (int i = 0; i < Count; ++i) { oDashNodes.GetAt(i, oDashNode); DashPattern[i] = (REAL)XmlUtils::GetDouble(oDashNode.GetText()); } } } } } DashOffset = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("dash-offset"), _T("0"))); SetAlignment( XmlUtils::GetInteger(oXmlReader.ReadNodeAttribute(_T("alignment"), _T("0"))) ); Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { Color = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alpha"), _T("0"))); Size = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("size"), _T("0"))); DashStyle = (byte)XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("style"), _T("0"))); LineStartCap = (byte)XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("line-start-cap"), _T("0"))); LineEndCap = (byte)XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("line-end-cap"), _T("0"))); LineJoin = (byte)XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("line-join"), _T("0"))); RELEASEARRAYOBJECTS(DashPattern); Count = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("dash-pattern-count"), _T("0"))); if (Count != 0) { XmlUtils::CXmlNode oPatternNode; if (oXmlNode.GetNode(_T("dash-pattern"), oPatternNode)) { XmlUtils::CXmlNodes oDashNodes; if (oPatternNode.GetNodes(_T("dash"), oDashNodes)) { Count = oDashNodes.GetCount(); if (Count != 0) { DashPattern = new REAL[Count]; XmlUtils::CXmlNode oDashNode; for (int i = 0; i < Count; ++i) { oDashNodes.GetAt(i, oDashNode); DashPattern[i] = (REAL)XmlUtils::GetDouble(oDashNode.GetText()); } } } } } DashOffset = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("dash-offset"), _T("0"))); SetAlignment( XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alignment"), _T("0"))) ); Update(); } long GetColor() const { return Color; } void SetColor(long nColor) { if (Color != nColor) Clear(); Color = nColor; } long GetAlpha() const { return Alpha; } void SetAlpha(long nAlpha) { if (Alpha != nAlpha) Clear(); Alpha = nAlpha; } double GetSize() const { return Size; } void SetSize(double dSize) { if (fabs(Size - dSize) > 0.0001) Clear(); Size = dSize; } byte GetStyle() const { return DashStyle; } void SetStyle(byte nStyle) { if (DashStyle != nStyle) Clear(); DashStyle = nStyle; } byte GetLineStartCap() const { return LineStartCap; } void SetLineStartCap(byte nLineStartCap) { if (LineStartCap != nLineStartCap) Clear(); LineStartCap = nLineStartCap; } byte GetLineEndCap() const { return LineEndCap; } void SetLineEndCap(byte nLineEndCap) { if (LineEndCap != nLineEndCap) Clear(); LineEndCap = nLineEndCap; } byte GetLineJoin() const { return LineJoin; } void SetLineJoin(byte nLineJoin) { if (LineJoin != nLineJoin) Clear(); LineJoin = nLineJoin; } long GetDashPatternCount() const { return Count; } void GetDashPattern(REAL* arrDashPattern, long& nCount) const { if (nCount == Count) { for (int i = 0; i < Count; ++i) { arrDashPattern[i] = DashPattern[i]; } } } void SetDashPattern(REAL* arrDashPattern, long nCount) { if ((arrDashPattern == NULL) || (nCount == 0)) { Count = 0; RELEASEARRAYOBJECTS(DashPattern); } else { if (Count != nCount) { Count = nCount; RELEASEARRAYOBJECTS(DashPattern); DashPattern = new REAL[Count]; } for (int i = 0; i < Count; ++i) { DashPattern[i] = arrDashPattern[i]; } } } REAL GetDashOffset() const { return DashOffset; } void SetDashOffset(REAL fDashOffset) { if (DashOffset != fDashOffset) Clear(); DashOffset = fDashOffset; } void SetAlignment( int align ) { Align = (align == PenAlignmentInset) ? PenAlignmentInset : PenAlignmentCenter; if( m_pen ) m_pen->SetAlignment( Align ); } int GetAlignment() const { return Align; } void ScaleAlpha( double dScale ) { long dNewAlpha = long(Alpha * dScale + 0.5); if( dNewAlpha > 255 ) dNewAlpha = 255; else if( dNewAlpha < 0 ) dNewAlpha = 0; SetAlpha( dNewAlpha ); } void FromPen(const CPen& oPen) { SetColor(oPen.GetColor()); SetAlpha(oPen.GetAlpha()); SetSize(oPen.GetSize()); SetStyle(oPen.GetStyle()); SetLineStartCap(oPen.GetLineStartCap()); SetLineEndCap(oPen.GetLineEndCap()); SetLineJoin(oPen.GetLineJoin()); long nCount = oPen.GetDashPatternCount(); REAL* arrDashPattern = new REAL[nCount]; oPen.GetDashPattern(arrDashPattern, nCount); SetDashPattern(arrDashPattern, nCount); RELEASEARRAYOBJECTS(arrDashPattern); SetDashOffset(oPen.GetDashOffset()); SetAlignment(oPen.GetAlignment()); } BOOL IsEqual(CPen* pPen) { if (NULL == pPen) return FALSE; return ((Color == pPen->Color) && (Alpha == pPen->Alpha) && (Size == pPen->Size) && (DashStyle == pPen->DashStyle) && (LineStartCap == pPen->LineStartCap) && (LineEndCap == pPen->LineEndCap) && (LineJoin == pPen->LineJoin)); } void SetDefaultParams() { Color = 0; Alpha = 255; Size = 1; DashStyle = 0; LineStartCap = 0; LineEndCap = 0; LineJoin = 0; DashPattern = NULL; Count = 0; DashOffset = 0; Align = Gdiplus::PenAlignmentCenter; } public: CPen() { m_pen = 0; Color = 0; Alpha = 255; Size = 1; DashStyle = 0; LineStartCap = 0; LineEndCap = 0; LineJoin = 0; DashPattern = NULL; Count = 0; DashOffset = 0; Align = PenAlignmentCenter; } CPen( const CPen& other ) { m_pen = NULL; Color = other.Color; Alpha = other.Alpha; Size = other.Size; DashStyle = other.DashStyle; LineStartCap = other.LineStartCap; LineEndCap = other.LineEndCap; LineJoin = other.LineJoin; Count = other.Count; if (Count != 0) { DashPattern = new REAL[Count]; for (int i = 0; i < Count; ++i) { DashPattern[i] = other.DashPattern[i]; } } DashOffset = other.DashOffset; Align = other.Align; } CPen& operator=(const CPen& pen) { Clear(); FromPen(pen); return *this; } ~CPen() { RELEASEARRAYOBJECTS(DashPattern); Clear(); } void Update() { Clear(); } void Clear() { if (m_pen) { delete m_pen; m_pen = 0; } } Gdiplus::Pen* GetPen() { if (m_pen) return m_pen; Gdiplus::Color color((BYTE)Alpha, GetRValue(Color), GetGValue(Color), GetBValue(Color)); m_pen = new Gdiplus::Pen(color, (REAL)Size); m_pen->SetDashStyle((Gdiplus::DashStyle)DashStyle); m_pen->SetStartCap((LineCap)LineStartCap); m_pen->SetEndCap((LineCap)LineEndCap); m_pen->SetLineJoin((Gdiplus::LineJoin)LineJoin); if ((Count != 0) && (DashPattern != NULL)) { m_pen->SetDashPattern(DashPattern, Count); } m_pen->SetDashOffset(DashOffset); m_pen->SetAlignment( Align ); return m_pen; } }; class CBrush { Gdiplus::Brush* m_brush; double m_dTransparency; public: long Type; long Color1; long Color2; long Alpha1; long Alpha2; long GradientAngle; CString TexturePath; long TextureAlpha; long TextureMode; BOOL Rectable; RectF Rect; public: int GetSize() { return 4*sizeof(double) + 9*sizeof(long) + TexturePath.GetLength() + 1; } void Write(CStream& stream) { stream.WriteLong(Type); stream.WriteLong(Color1); stream.WriteLong(Alpha1); stream.WriteLong(Color2); stream.WriteLong(Alpha2); stream.WriteLong(GradientAngle); stream.WriteString(TexturePath); stream.WriteLong(TextureAlpha); stream.WriteLong(TextureMode); stream.WriteLong(Rectable); stream.WriteDouble(Rect.X); stream.WriteDouble(Rect.Y); stream.WriteDouble(Rect.Width); stream.WriteDouble(Rect.Height); } void Read(CStream& stream) { Type = stream.ReadLong(); Color1 = stream.ReadLong(); Alpha1 = stream.ReadLong(); Color2 = stream.ReadLong(); Alpha2 = stream.ReadLong(); GradientAngle = stream.ReadLong(); TexturePath = stream.ReadString(); TextureAlpha = stream.ReadLong(); TextureMode = stream.ReadLong(); Rectable = stream.ReadLong(); Rect.X = (REAL)stream.ReadDouble(); Rect.Y = (REAL)stream.ReadDouble(); Rect.Width = (REAL)stream.ReadDouble(); Rect.Height = (REAL)stream.ReadDouble(); Update(); } CString ToXmlString(CString strRootNodeName = _T("brush"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("type"), Type); oXmlWriter.WriteNode(_T("color1"), Color1); oXmlWriter.WriteNode(_T("color2"), Color2); oXmlWriter.WriteNode(_T("alpha1"), Alpha1); oXmlWriter.WriteNode(_T("alpha2"), Alpha2); oXmlWriter.WriteNode(_T("gradient-angle"), GradientAngle); oXmlWriter.WriteNode(_T("texturepath"), TexturePath); oXmlWriter.WriteNode(_T("texturealpha"), TextureAlpha); oXmlWriter.WriteNode(_T("texturemode"), TextureMode); oXmlWriter.WriteNode(_T("rectable"), Rectable); oXmlWriter.WriteNodeBegin(_T("rectangle"), TRUE); oXmlWriter.WriteAttribute(_T("left"), Rect.X); oXmlWriter.WriteAttribute(_T("top"), Rect.Y); oXmlWriter.WriteAttribute(_T("width"), Rect.Width); oXmlWriter.WriteAttribute(_T("height"), Rect.Height); oXmlWriter.WriteNodeEnd(_T("rectangle"), TRUE); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { Type = pStream->ReadLong(); Type = ConstantCompatible(Type); Color1 = pStream->ReadLong(); Alpha1 = pStream->ReadLong(); Color2 = pStream->ReadLong(); Alpha2 = pStream->ReadLong(); GradientAngle = pStream->ReadLong(); TexturePath = pStream->ReadString(); TextureAlpha = pStream->ReadLong(); TextureMode = pStream->ReadLong(); Rectable = pStream->ReadLong(); Rect.X = (REAL)pStream->ReadDouble(); Rect.Y = (REAL)pStream->ReadDouble(); Rect.Width = (REAL)pStream->ReadDouble(); Rect.Height = (REAL)pStream->ReadDouble(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteLong(Type); pStream->WriteLong(Color1); pStream->WriteLong(Alpha1); pStream->WriteLong(Color2); pStream->WriteLong(Alpha2); pStream->WriteLong(GradientAngle); pStream->WriteString(TexturePath); pStream->WriteLong(TextureAlpha); pStream->WriteLong(TextureMode); pStream->WriteLong(Rectable); pStream->WriteDouble(Rect.X); pStream->WriteDouble(Rect.Y); pStream->WriteDouble(Rect.Width); pStream->WriteDouble(Rect.Height); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("type"), Type); oXmlWriter.WriteAttribute(_T("color1"), Color1); oXmlWriter.WriteAttribute(_T("color2"), Color2); oXmlWriter.WriteAttribute(_T("alpha1"), Alpha1); oXmlWriter.WriteAttribute(_T("alpha2"), Alpha2); oXmlWriter.WriteAttribute(_T("gradient-angle"), GradientAngle); oXmlWriter.WriteAttribute(_T("texturepath"), TexturePath); oXmlWriter.WriteAttribute(_T("texturealpha"), TextureAlpha); oXmlWriter.WriteAttribute(_T("texturemode"), TextureMode); oXmlWriter.WriteAttribute(_T("rectable"), Rectable); oXmlWriter.WriteAttribute(_T("rect-left"), Rect.X); oXmlWriter.WriteAttribute(_T("rect-top"), Rect.Y); oXmlWriter.WriteAttribute(_T("rect-width"), Rect.Width); oXmlWriter.WriteAttribute(_T("rect-height"), Rect.Height); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { Type = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("type"), _T("0"))); Type = ConstantCompatible(Type); Color1 = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("color1"), _T("0"))); Color2 = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("color2"), _T("0"))); Alpha1 = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("alpha1"), _T("0"))); Alpha2 = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("alpha2"), _T("0"))); GradientAngle = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("gradient-angle"), _T("0"))); TexturePath = oXmlReader.ReadNodeAttributeOrValue(_T("texturepath"), _T("")); TextureAlpha = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("texturealpha"), _T("0"))); TextureMode = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("texturemode"), _T("0"))); Rectable = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("rectable"), _T("0"))); Rect.X = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("rect-left"))); Rect.Y = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("rect-top"))); Rect.Width = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("rect-width"))); Rect.Height = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("rect-height"))); if (oXmlReader.ReadNode(_T("rectangle"))) { Rect.X = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttribute(_T("left"))); Rect.Y = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttribute(_T("top"))); Rect.Width = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttribute(_T("width"))); Rect.Height = (REAL)XmlUtils::GetDouble(oXmlReader.ReadNodeAttribute(_T("height"))); } Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { Type = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("type"), _T("0"))); Type = ConstantCompatible(Type); Color1 = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("color1"), _T("0"))); Color2 = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("color2"), _T("0"))); Alpha1 = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alpha1"), _T("0"))); Alpha2 = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alpha2"), _T("0"))); GradientAngle = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("gradient-angle"), _T("0"))); TexturePath = oXmlNode.GetAttributeOrValue(_T("texturepath"), _T("")); TextureAlpha = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("texturealpha"), _T("0"))); TextureMode = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("texturemode"), _T("0"))); Rectable = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("rectable"), _T("0"))); Rect.X = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("rect-left"))); Rect.Y = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("rect-top"))); Rect.Width = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("rect-width"))); Rect.Height = (REAL)XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("rect-height"))); XmlUtils::CXmlNode oNodeRect; if (oXmlNode.GetNode(_T("rectangle"), oNodeRect)) { Rect.X = (REAL)XmlUtils::GetDouble(oNodeRect.GetAttributeOrValue(_T("left"))); Rect.Y = (REAL)XmlUtils::GetDouble(oNodeRect.GetAttributeOrValue(_T("top"))); Rect.Width = (REAL)XmlUtils::GetDouble(oNodeRect.GetAttributeOrValue(_T("width"))); Rect.Height = (REAL)XmlUtils::GetDouble(oNodeRect.GetAttributeOrValue(_T("height"))); } Update(); } long GetType() const { return ConstantCompatible(Type); } void SetType(long nType) { if (Type != nType) Clear(); Type = ConstantCompatible(nType); } long GetColor1() const { return Color1; } void SetColor1(long nColor1) { if (Color1 != nColor1) Clear(); Color1 = nColor1; } long GetColor2() const { return Color2; } void SetColor2(int nColor2) { if (Color2 != nColor2) Clear(); Color2 = nColor2; } long GetAlpha1() const { return Alpha1; } void SetAlpha1(long nAlpha1) { if (Alpha1 != nAlpha1) Clear(); Alpha1 = nAlpha1; } long GetAlpha2() const { return Alpha2; } void SetAlpha2(long nAlpha2) { if (Alpha2 != nAlpha2) Clear(); Alpha2 = nAlpha2; } long GetGradientAngle() const { return GradientAngle; } void SetGradientAngle(long nGradientAngle) { if (GradientAngle != nGradientAngle) Clear(); GradientAngle = nGradientAngle; } CString GetTexturePath() const { return TexturePath; } void SetTexturePath(const CString& strTexturePath) { if (TexturePath != strTexturePath) Clear(); TexturePath = strTexturePath; } long GetTextureAlpha() const { return TextureAlpha; } void SetTextureAlpha(long nTextureAlpha) { if (TextureAlpha != nTextureAlpha) Clear(); TextureAlpha = nTextureAlpha; } long GetTextureMode() const { return TextureMode; } void SetTextureMode(long nTextureMode) { if (TextureMode != nTextureMode) Clear(); TextureMode = nTextureMode; } BOOL GetRectable() const { return Rectable; } Gdiplus::RectF GetRect() const { return Rect; } void SetRect(Gdiplus::RectF* pRect) { if (NULL == pRect) { if (Rectable) Clear(); Rectable = FALSE; } else { if (!Rectable || pRect->X != Rect.X || pRect->Y != Rect.Y || pRect->Width != Rect.Width || pRect->Height != Rect.Height) Clear(); Rect = *pRect; Rectable = TRUE; } } void ScaleAlpha1( double dScale ) { long dNewAlpha = long(Alpha1 * dScale + 0.5); if( dNewAlpha > 255 ) dNewAlpha = 255; else if( dNewAlpha < 0 ) dNewAlpha = 0; SetAlpha1( dNewAlpha ); } void ScaleAlpha2( double dScale ) { long dNewAlpha = long(Alpha2 * dScale + 0.5); if( dNewAlpha > 255 ) dNewAlpha = 255; else if( dNewAlpha < 0 ) dNewAlpha = 0; SetAlpha2( dNewAlpha ); } void ScaleTextureAlpha( double dScale ) { long dNewAlpha = long(TextureAlpha * dScale + 0.5); if( dNewAlpha > 255 ) dNewAlpha = 255; else if( dNewAlpha < 0 ) dNewAlpha = 0; SetTextureAlpha( dNewAlpha ); } void FromBrush(const CBrush& oBrush) { SetType(oBrush.GetType()); SetColor1(oBrush.GetColor1()); SetColor2(oBrush.GetColor2()); SetAlpha1(oBrush.GetAlpha1()); SetAlpha2(oBrush.GetAlpha2()); SetGradientAngle(oBrush.GetGradientAngle()); SetTexturePath(oBrush.GetTexturePath()); SetTextureAlpha(oBrush.GetTextureAlpha()); SetTextureMode(oBrush.GetTextureMode()); if (!oBrush.GetRectable()) SetRect(NULL); else SetRect(&oBrush.GetRect()); } void SetTransparency( double dIntensity ) { if( dIntensity > 1 ) dIntensity = 1; if( dIntensity < 0 ) dIntensity = 0; if( dIntensity != m_dTransparency ) { int nOldAlpha1 = int(m_dTransparency * Alpha1 + 0.5); int nNewAlpha1 = int(dIntensity * Alpha1 + 0.5); int nOldAlpha2 = int(m_dTransparency * Alpha2 + 0.5); int nNewAlpha2 = int(dIntensity * Alpha2 + 0.5); int nOldTextureAlpha = int(m_dTransparency * TextureAlpha + 0.5); int nNewTextureAlpha = int(dIntensity * TextureAlpha + 0.5); if( nNewAlpha1 != nOldAlpha1 || nNewAlpha2 != nOldAlpha2 || nNewTextureAlpha != nOldTextureAlpha ) { Update(); } m_dTransparency = dIntensity; } } double GetTransparency() const { return m_dTransparency; } BOOL IsEqual(CBrush* pBrush) { if (NULL == pBrush) return FALSE; return ((Type == pBrush->Type) && (Color1 == pBrush->Color1) && (Color2 == pBrush->Color2) && (Alpha1 == pBrush->Alpha1) && (Alpha2 == pBrush->Alpha2) && (GradientAngle == pBrush->GradientAngle)); } void SetDefaultParams() { Type = c_BrushTypeSolid; Color1 = 0; Alpha1 = 255; Color2 = 0; Alpha2 = 255; TextureAlpha = 255; TextureMode = c_BrushTextureModeStretch; TexturePath = _T(""); Rectable = FALSE; Rect.X = 0.0F; Rect.Y = 0.0F; Rect.Width = 0.0F; Rect.Height = 0.0F; } public: CBrush() { m_brush = 0; Type = 0; Color1 = 0; Alpha1 = 255; Color2 = 0; Alpha2 = 255; GradientAngle = 0; TextureAlpha = 255; TextureMode = c_BrushTextureModeStretch; Rectable = FALSE; Rect.X = 0.0F; Rect.Y = 0.0F; Rect.Width = 0.0F; Rect.Height = 0.0F; m_dTransparency = 1; } CBrush( const CBrush& other ) { m_brush = NULL; Type = other.Type; Color1 = other.Color1; Alpha1 = other.Alpha1; Color2 = other.Color2; Alpha2 = other.Alpha2; GradientAngle = other.GradientAngle; TexturePath = other.TexturePath; TextureAlpha = other.TextureAlpha; TextureMode = other.TextureMode; Rectable = other.Rectable; Rect = other.Rect; m_dTransparency = other.m_dTransparency; } CBrush& operator=(const CBrush& brush) { Clear(); FromBrush(brush); return *this; } ~CBrush() { Clear(); } void Update() { Clear(); } void Clear() { if( m_brush ) { delete m_brush; m_brush = 0; } } static bool GetTextRect(BSTR Text, Graphics* pGr, Gdiplus::Font* font, double Left, double Top, RectF* textRect) { if (!pGr || !font || !textRect) return false; PointF point((REAL)Left, (REAL)Top); Status s = pGr->MeasureString(Text, SysStringLen(Text), font, point, textRect); if (s != Ok) return false; return true; } Gdiplus::Brush* GetBrush(CTextureManager* manager = 0, RectF* pRect = 0, int index = 0, BOOL bAddIfNotExists = FALSE) { if( m_brush ) { if( EqualsRectable( pRect ) ) return m_brush; if( BrushTypeTextureFill == m_brush->GetType() ) { Gdiplus::TextureBrush* pBrush = (Gdiplus::TextureBrush*)m_brush; SetTextureBrushTransform( pBrush, pRect ); return m_brush; } Rectable = FALSE; Clear(); } int nBrushType = GetType(); if (c_BrushTypeTexture == nBrushType && manager) { int index = manager->Find(TexturePath); if (index < 0 && bAddIfNotExists) index = manager->Add(TexturePath); if (index >= 0) { Gdiplus::TextureBrush* brush = GetTexureBrush(manager->GetAt(index), pRect ); m_brush = brush; return m_brush; } } else if (nBrushType >= c_BrushTypeHatch1 && nBrushType <= c_BrushTypeHatch53) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); Gdiplus::HatchBrush* brush = new HatchBrush((HatchStyle)(nBrushType - c_BrushTypeHatch1), color1, color2); m_brush = brush; return m_brush; } else if (GradientAngle>0 && pRect && nBrushType!=c_BrushTypeSolid) { Gdiplus::LinearGradientBrush* brush = GetLinearGradientBrushAngle(GradientAngle, pRect); m_brush = brush; return m_brush; } else if (nBrushType >= c_BrushTypeHorizontal && nBrushType <= c_BrushTypeDiagonal2 && pRect) { int angle = 0; switch(nBrushType) { case c_BrushTypeVertical: angle = 90; break; case c_BrushTypeDiagonal1: angle = 45; break; case c_BrushTypeDiagonal2: angle = 135; break; } Gdiplus::LinearGradientBrush* brush = GetLinearGradientBrushAngle(90 - angle, pRect); m_brush = brush; return m_brush; } else if ((c_BrushTypeCenter == nBrushType && pRect) || (c_BrushTypePathGradient1 == nBrushType && pRect)) { Gdiplus::PathGradientBrush* brush = GetPathGradientBrushCenter(pRect); m_brush = brush; return m_brush; } if (c_BrushTypePathGradient2 == nBrushType && pRect) { Gdiplus::PathGradientBrush* brush = GetPathGradientBrush(pRect, index); m_brush = brush; return m_brush; } else if (nBrushType >= c_BrushTypeCylinderHor && nBrushType <= c_BrushTypeCylinderVer && pRect) { Gdiplus::LinearGradientBrush* brush = GetLinearGradientBrushCHV(nBrushType - c_BrushTypeCylinderHor, pRect); m_brush = brush; return m_brush; } Gdiplus::Color color((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::SolidBrush* brush = new Gdiplus::SolidBrush(color); m_brush = brush; return m_brush; } private: ImageAttributes* GetImageAttributes( int nAlpha ) { if( nAlpha < 0 || nAlpha >= 255 ) return NULL; REAL alph = (REAL)(nAlpha / 255.0); ColorMatrix colorMatrix = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, alph, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; ImageAttributes* pImageAtt = new ImageAttributes(); if( pImageAtt ) pImageAtt->SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap); return pImageAtt; } void SetTextureBrushTransform( Gdiplus::TextureBrush* pBrush, Gdiplus::RectF* pBrushRect ) { if( !pBrush ) return; Gdiplus::Image* pImage = pBrush->GetImage(); Gdiplus::RectF oImageRect; Gdiplus::Unit oImageUnit; if( pImage ) { pImage->GetBounds( &oImageRect, &oImageUnit ); delete pImage; } pBrush->ResetTransform(); Gdiplus::PointF oBrushOffset; if( pBrushRect ) { oBrushOffset.X = pBrushRect->X; oBrushOffset.Y = pBrushRect->Y; } switch(TextureMode) { case c_BrushTextureModeStretch: if( pBrushRect ) { pBrush->ScaleTransform( pBrushRect->Width / oImageRect.Width, pBrushRect->Height / oImageRect.Height ); break; } case c_BrushTextureModeTileCenter: if( pBrushRect ) { oBrushOffset.X += (pBrushRect->Width - oImageRect.Width)/2; oBrushOffset.Y += (pBrushRect->Height - oImageRect.Height)/2; pBrush->SetWrapMode( WrapModeTile ); break; } default: pBrush->SetWrapMode( WrapModeTile ); } if( oBrushOffset.X != 0 || oBrushOffset.Y != 0) { pBrush->TranslateTransform( oBrushOffset.X, oBrushOffset.Y, MatrixOrderAppend ); SetRectable( pBrushRect ); } } Gdiplus::TextureBrush* GetTexureBrush( Painter::CTexture* pTexture, Gdiplus::RectF* pRect) { int nAlpha = int(TextureAlpha * m_dTransparency + 0.5); if( nAlpha < 1 ) return NULL; if( !pTexture ) return NULL; Gdiplus::TextureBrush* pBrush = NULL; Gdiplus::Bitmap* pTextureBitmap = pTexture->Bitmap; if( !pTextureBitmap ) { BYTE* pBGRA = pTexture->BitmapData; int nWidth = pTexture->nWidth; int nHeight = pTexture->nHeight; int nStride = pTexture->nStride; if( NULL == pBGRA || nWidth <=0 || nHeight <= 0 || abs(nStride) < nWidth * 4 ) return NULL; BYTE* pBuffer = NULL; if( nAlpha < 255 ) { pBuffer = new BYTE[nWidth*nHeight*4]; if( pBuffer ) { if( nStride < 0 ) { pBGRA += nStride * (nHeight - 1); nStride = -nStride; } nStride -= nWidth * 4; BYTE* pSrc = pBGRA; BYTE* pDst = pBuffer; for( int nRow = nHeight; nRow > 0; --nRow, pSrc += nStride ) { for( int nPos = nWidth; nPos > 0; --nPos, pDst += 4, pSrc += 4 ) { DWORD alpha = ((DWORD(pSrc[3]) << 8) + 127) / 255; pDst[0] = BYTE(pSrc[0] * alpha >> 8); pDst[1] = BYTE(pSrc[1] * alpha >> 8); pDst[2] = BYTE(pSrc[2] * alpha >> 8); pDst[3] = BYTE(nAlpha); } } pBGRA = pBuffer; nStride = nWidth*4; } } Gdiplus::Bitmap oImage( nWidth, nHeight, nStride, PixelFormat32bppARGB, pBGRA ); if( Gdiplus::Ok == oImage.GetLastStatus() ) { pBrush = new Gdiplus::TextureBrush( &oImage, Gdiplus::Rect(0, 0, nWidth, nHeight), NULL); } if( pBuffer ) delete [] pBuffer; } else { Gdiplus::ImageAttributes* pImageAttr = GetImageAttributes( nAlpha ); pBrush = new Gdiplus::TextureBrush(pTextureBitmap, Gdiplus::Rect(0, 0, pTexture->nWidth, pTexture->nHeight), pImageAttr); if( pImageAttr ) { delete pImageAttr; pImageAttr = NULL; } } SetTextureBrushTransform( pBrush, pRect ); return pBrush; } Gdiplus::LinearGradientBrush* GetLinearGradientBrushHVD(int type, RectF* pRect) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); Gdiplus::LinearGradientBrush* brush = new Gdiplus::LinearGradientBrush(*pRect, color1, color2, (LinearGradientMode)type); if( brush ) { brush->SetWrapMode( Gdiplus::WrapModeTileFlipXY ); } SetRectable(pRect); return brush; } Gdiplus::LinearGradientBrush* GetLinearGradientBrushCHV(int type, RectF* pRect) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); float angle = 0; switch(type) { case 0: angle = -90; break; case 1: angle = -180; break; } Gdiplus::LinearGradientBrush* brush = new Gdiplus::LinearGradientBrush(*pRect, color1, color2, angle); if( brush ) { brush->SetBlendBellShape(0.70f); brush->SetWrapMode( Gdiplus::WrapModeTileFlipXY ); } SetRectable(pRect); return brush; } Gdiplus::LinearGradientBrush* GetLinearGradientBrushAngle(int nAngle, RectF* pRect) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); float angle = (float)(90 - nAngle); Gdiplus::LinearGradientBrush* brush = new Gdiplus::LinearGradientBrush(*pRect, color1, color2, angle); if( brush ) { brush->SetWrapMode( Gdiplus::WrapModeTileFlipXY ); } SetRectable(pRect); return brush; } Gdiplus::PathGradientBrush* GetPathGradientBrushCenter(RectF* pRect) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); Gdiplus::GraphicsPath path; path.AddRectangle(*pRect); PathGradientBrush* brush = new PathGradientBrush(&path); if( brush ) { Color colors[] = {color1}; int count = 1; brush->SetSurroundColors(colors, &count); brush->SetCenterColor(color2); brush->SetWrapMode( Gdiplus::WrapModeTileFlipXY ); } SetRectable(pRect); return brush; } Gdiplus::PathGradientBrush* GetPathGradientBrush(RectF* pRect, int index) { Gdiplus::Color color1((BYTE)(Alpha1 * m_dTransparency + 0.5), GetRValue(Color1), GetGValue(Color1), GetBValue(Color1)); Gdiplus::Color color2((BYTE)(Alpha2 * m_dTransparency + 0.5), GetRValue(Color2), GetGValue(Color2), GetBValue(Color2)); Gdiplus::GraphicsPath path; path.AddRectangle(*pRect); PathGradientBrush* brush = new PathGradientBrush(&path); if( brush ) { int colorsCount = 4; Color colors1[] = {color1, color2, color2, color1}; Color colors2[] = {color2, color1, color1, color2}; Color* pColors = (index % 2) ? colors2 : colors1; Color& oColor = (index % 2) ? color2 : color1; brush->SetSurroundColors(pColors, &colorsCount); brush->SetCenterColor(oColor); brush->SetWrapMode( Gdiplus::WrapModeTileFlipXY ); } SetRectable(pRect); return brush; } void SetRectable(RectF* pRect) { if( pRect ) { Rect = *pRect; } Rectable = TRUE; } BOOL EqualsRectable( Gdiplus::RectF* pRect ) { if( !Rectable ) return TRUE; if( !pRect ) return !Rect.Width && !Rect.Height && !Rect.X && !Rect.Y; else return Rect.Equals( *pRect ); } }; class CFont { Gdiplus::Font* m_font; public: CString Name; CString Path; double Size; BOOL Bold; BOOL Italic; BOOL Underline; BOOL Strikeout; public: int GetSize() { return Name.GetLength() + 1 + sizeof(double) + 4*sizeof(long) + Path.GetLength() + 1; } void Write(CStream& stream) { stream.WriteString(Name); stream.WriteString(Path); stream.WriteDouble(Size); stream.WriteLong(Bold); stream.WriteLong(Italic); stream.WriteLong(Underline); stream.WriteLong(Strikeout); } void Read(CStream& stream) { Name = stream.ReadString(); Path = stream.ReadString(); Size = stream.ReadDouble(); Bold = stream.ReadLong(); Italic = stream.ReadLong(); Underline = stream.ReadLong(); Strikeout = stream.ReadLong(); Update(); } CString ToXmlString(CString strRootNodeName = _T("font"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("name"), Name); oXmlWriter.WriteNode(_T("path"), Path); oXmlWriter.WriteNode(_T("size"), Size); oXmlWriter.WriteNode(_T("bold"), Bold); oXmlWriter.WriteNode(_T("italic"), Italic); oXmlWriter.WriteNode(_T("underline"), Underline); oXmlWriter.WriteNode(_T("strikeout"), Strikeout); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { Name = pStream->ReadString(); Path = pStream->ReadString(); Size = pStream->ReadDouble(); Bold = pStream->ReadLong(); Italic = pStream->ReadLong(); Underline = pStream->ReadLong(); Strikeout = pStream->ReadLong(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteString(Name); pStream->WriteString(Path); pStream->WriteDouble(Size); pStream->WriteLong(Bold); pStream->WriteLong(Italic); pStream->WriteLong(Underline); pStream->WriteLong(Strikeout); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("name"), Name); oXmlWriter.WriteAttribute(_T("path"), Path); oXmlWriter.WriteAttribute(_T("size"), Size); oXmlWriter.WriteAttribute(_T("bold"), Bold); oXmlWriter.WriteAttribute(_T("italic"), Italic); oXmlWriter.WriteAttribute(_T("underline"), Underline); oXmlWriter.WriteAttribute(_T("strikeout"), Strikeout); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { Name = oXmlReader.ReadNodeAttributeOrValue(_T("name"), _T("Arial")); Path = oXmlReader.ReadNodeAttributeOrValue(_T("path"), _T("")); Size = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("size"), _T("0"))); Bold = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("bold"), _T("0"))); Italic = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("italic"), _T("0"))); Underline = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("underline"), _T("0"))); Strikeout = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("strikeout"), _T("0"))); Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { Name = oXmlNode.GetAttributeOrValue(_T("name"), _T("Arial")); Path = oXmlNode.GetAttributeOrValue(_T("path"), _T("")); Size = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("size"), _T("0"))); Bold = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("bold"), _T("0"))); Italic = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("italic"), _T("0"))); Underline = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("underline"), _T("0"))); Strikeout = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("strikeout"), _T("0"))); Update(); } CString GetName() const { return Name; } void SetName(const CString& strName) { if (Name != strName) Clear(); Name = strName; } CString GetPath() const { return Path; } void SetPath(const CString& strPath) { if ( Path != strPath ) Clear(); Path = strPath; } double GetFontSize() const { return Size; } void SetFontSize(double dSize) { if (fabs(Size - dSize) > 0.0001) Clear(); Size = dSize; } BOOL GetBold() const { return Bold; } void SetBold(BOOL bBold) { if (Bold != bBold) Clear(); Bold = bBold; } BOOL GetItalic() const { return Italic; } void SetItalic(BOOL bItalic) { if (Italic != bItalic) Clear(); Italic = bItalic; } BOOL GetUnderline() const { return Underline; } void SetUnderline(BOOL bUnderline) { if (Underline != bUnderline) Clear(); Underline = bUnderline; } BOOL GetStrikeout() const { return Strikeout; } void SetStrikeout(BOOL bStrikeout) { if (Strikeout != bStrikeout) Clear(); Strikeout = bStrikeout; } void FromFont(const CFont& oFont) { SetName(oFont.GetName()); SetPath(oFont.GetPath()); SetFontSize(oFont.GetFontSize()); SetBold(oFont.GetBold()); SetItalic(oFont.GetItalic()); SetUnderline(oFont.GetUnderline()); SetStrikeout(oFont.GetStrikeout()); } BOOL IsEqual(CFont* pFont) { if (NULL == pFont) return FALSE; return ((Name == pFont->Name) && (Path == pFont->Path) && (Size == pFont->Size) && (Bold == pFont->Bold) && (Italic == pFont->Italic) && (Underline == pFont->Underline) && (Strikeout == pFont->Strikeout)); } void SetDefaultParams() { Name = _T("Arial"); Path = _T(""); Size = 0; Bold = FALSE; Italic = FALSE; Underline = 0; Strikeout = 0; } public: CFont() { m_font = 0; Size = 0; Bold = FALSE; Italic = FALSE; Underline = FALSE; Strikeout = FALSE; } CFont( const CFont& other ) { m_font = 0; Name = other.Name; Path = other.Path; Size = other.Size; Bold = other.Bold; Italic = other.Italic; Underline = other.Underline; Strikeout = other.Strikeout; } CFont& operator=(const CFont& font) { Clear(); FromFont(font); return *this; } ~CFont() { Clear(); } void Update() { Clear(); } void Clear() { if (m_font) { delete m_font; m_font = 0; } } Gdiplus::Font* GetFont(Gdiplus::Unit units = Gdiplus::UnitPixel) { if (m_font) return m_font; BSTR family = Name.AllocSysString(); int style = Gdiplus::FontStyleRegular; if (Bold) style |= Gdiplus::FontStyleBold; if (Italic) style |= Gdiplus::FontStyleItalic; if (Underline) style |= Gdiplus::FontStyleUnderline; if (Strikeout) style |= Gdiplus::FontStyleStrikeout; Gdiplus::Font* font = new Gdiplus::Font(family, (REAL)Size, style, units); SysFreeString(family); m_font = font; return m_font; } }; class CFormat { Gdiplus::StringFormat* m_stringFormat; public: BOOL AntiAliasPen; BOOL AntiAliasBrush; BOOL AntiAliasText; long StringAlignmentVertical; long StringAlignmentHorizontal; long ImageAlphMode; public: int GetSize() { return 6*sizeof(long); } void Write(CStream& stream) { stream.WriteLong(AntiAliasPen); stream.WriteLong(AntiAliasBrush); stream.WriteLong(AntiAliasText); stream.WriteLong(StringAlignmentVertical); stream.WriteLong(StringAlignmentHorizontal); stream.WriteLong(ImageAlphMode); } void Read(CStream& stream) { AntiAliasPen = stream.ReadLong(); AntiAliasBrush = stream.ReadLong(); AntiAliasText = stream.ReadLong(); StringAlignmentVertical = stream.ReadLong(); StringAlignmentHorizontal = stream.ReadLong(); ImageAlphMode = stream.ReadLong(); Update(); } CString ToXmlString(CString strRootNodeName = _T("format"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("antialiaspen"), AntiAliasPen); oXmlWriter.WriteNode(_T("antialiasbrush"), AntiAliasBrush); oXmlWriter.WriteNode(_T("antialiastext"), AntiAliasText); oXmlWriter.WriteNode(_T("stringalignmentvertical"), StringAlignmentVertical); oXmlWriter.WriteNode(_T("stringalignmenthorizontal"), StringAlignmentHorizontal); oXmlWriter.WriteNode(_T("imagealphmode"), ImageAlphMode); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { AntiAliasPen = pStream->ReadLong(); AntiAliasBrush = pStream->ReadLong(); AntiAliasText = pStream->ReadLong(); StringAlignmentVertical = pStream->ReadLong(); StringAlignmentHorizontal = pStream->ReadLong(); ImageAlphMode = pStream->ReadLong(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteLong(AntiAliasPen); pStream->WriteLong(AntiAliasBrush); pStream->WriteLong(AntiAliasText); pStream->WriteLong(StringAlignmentVertical); pStream->WriteLong(StringAlignmentHorizontal); pStream->WriteLong(ImageAlphMode); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("antialiaspen"), AntiAliasPen); oXmlWriter.WriteAttribute(_T("antialiasbrush"), AntiAliasBrush); oXmlWriter.WriteAttribute(_T("antialiastext"), AntiAliasText); oXmlWriter.WriteAttribute(_T("stringalignmentvertical"), StringAlignmentVertical); oXmlWriter.WriteAttribute(_T("stringalignmenthorizontal"), StringAlignmentHorizontal); oXmlWriter.WriteAttribute(_T("imagealphmode"), ImageAlphMode); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { AntiAliasPen = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("antialiaspen"), _T("1"))); AntiAliasBrush = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("antialiasbrush"), _T("1"))); AntiAliasText = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("antialiastext"), _T("0"))); StringAlignmentVertical = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("stringalignmentvertical"), _T("0"))); StringAlignmentHorizontal = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("stringalignmenthorizontal"), _T("0"))); ImageAlphMode = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("imagealphmode"), _T("0"))); Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { AntiAliasPen = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("antialiaspen"), _T("1"))); AntiAliasBrush = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("antialiasbrush"), _T("1"))); AntiAliasText = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("antialiastext"), _T("0"))); StringAlignmentVertical = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("stringalignmentvertical"), _T("0"))); StringAlignmentHorizontal = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("stringalignmenthorizontal"), _T("0"))); ImageAlphMode = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("imagealphmode"), _T("0"))); Update(); } static StringAlignment GetAlignment(long val) { switch(val) { case 0: return StringAlignmentNear; case 1: return StringAlignmentCenter; case 2: return StringAlignmentFar; } return StringAlignmentNear; } BOOL GetAntiAliasPen() const { return AntiAliasPen; } void SetAntiAliasPen(BOOL bAntiAliasPen) { AntiAliasPen = bAntiAliasPen; } BOOL GetAntiAliasBrush() const { return AntiAliasBrush; } void SetAntiAliasBrush(BOOL bAntiAliasBrush) { AntiAliasBrush = bAntiAliasBrush; } BOOL GetAntiAliasText() const { return AntiAliasText; } void SetAntiAliasText(BOOL bAntiAliasText) { AntiAliasText = bAntiAliasText; } long GetStringAlignmentVertical() const { return StringAlignmentVertical; } void SetStringAlignmentVertical(long nStringAlignmentVertical) { if (StringAlignmentVertical != nStringAlignmentVertical) Clear(); StringAlignmentVertical = nStringAlignmentVertical; } long GetStringAlignmentHorizontal() const { return StringAlignmentHorizontal; } void SetStringAlignmentHorizontal(long nStringAlignmentHorizontal) { if (StringAlignmentHorizontal != nStringAlignmentHorizontal) Clear(); StringAlignmentHorizontal = nStringAlignmentHorizontal; } long GetImageAlphaMode() const { return ImageAlphMode; } void SetImageAlphaMode(long nImageAlphaMode) { ImageAlphMode = nImageAlphaMode; } void FromFormat(const CFormat& oFormat) { SetAntiAliasPen(oFormat.GetAntiAliasPen()); SetAntiAliasBrush(oFormat.GetAntiAliasBrush()); SetAntiAliasText(oFormat.GetAntiAliasText()); SetStringAlignmentVertical(oFormat.GetStringAlignmentVertical()); SetStringAlignmentHorizontal(oFormat.GetStringAlignmentHorizontal()); SetImageAlphaMode(oFormat.GetImageAlphaMode()); } public: CFormat() { m_stringFormat = 0; AntiAliasPen = TRUE; AntiAliasBrush = TRUE; AntiAliasText = TRUE; StringAlignmentVertical = 0; StringAlignmentHorizontal = 0; ImageAlphMode = 0; } CFormat( const CFormat& other ) { m_stringFormat = 0; AntiAliasPen = other.AntiAliasPen; AntiAliasBrush = other.AntiAliasBrush; AntiAliasText = other.AntiAliasText; StringAlignmentVertical = other.StringAlignmentVertical; StringAlignmentHorizontal = other.StringAlignmentHorizontal; ImageAlphMode = other.ImageAlphMode; } CFormat& operator=(const CFormat& other) { Clear(); AntiAliasPen = other.AntiAliasPen; AntiAliasBrush = other.AntiAliasBrush; AntiAliasText = other.AntiAliasText; StringAlignmentVertical = other.StringAlignmentVertical; StringAlignmentHorizontal = other.StringAlignmentHorizontal; ImageAlphMode = other.ImageAlphMode; return *this; } ~CFormat() { Clear(); } void Update() { Clear(); } void Clear() { if (m_stringFormat) { delete m_stringFormat; m_stringFormat = 0; } } Gdiplus::StringFormat* GetStringFormat() { if (m_stringFormat) return m_stringFormat; StringFormat* pStringFormat = new StringFormat(); pStringFormat->SetAlignment(GetAlignment(StringAlignmentHorizontal)); pStringFormat->SetLineAlignment(GetAlignment(StringAlignmentVertical)); m_stringFormat = pStringFormat; return m_stringFormat; } }; class CShadow { Gdiplus::Brush* m_brush; public: BOOL Visible; double DistanceX; double DistanceY; double BlurSize; long Color; long Alpha; public: int GetSize() { return 3*sizeof(long) + 3*sizeof(double); } void Write(CStream& stream) { stream.WriteLong(Visible); stream.WriteDouble(DistanceX); stream.WriteDouble(DistanceY); stream.WriteDouble(BlurSize); stream.WriteLong(Color); stream.WriteLong(Alpha); } void Read(CStream& stream) { Visible = stream.ReadLong(); DistanceX = stream.ReadDouble(); DistanceY = stream.ReadDouble(); BlurSize = stream.ReadDouble(); Color = stream.ReadLong(); Alpha = stream.ReadLong(); Update(); } CString ToXmlString(CString strRootNodeName = _T("shadow"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("visible"), Visible); oXmlWriter.WriteNode(_T("distancex"), DistanceX); oXmlWriter.WriteNode(_T("distancey"), DistanceY); oXmlWriter.WriteNode(_T("blursize"), BlurSize); oXmlWriter.WriteNode(_T("color"), Color); oXmlWriter.WriteNode(_T("alpha"), Alpha); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { Visible = pStream->ReadLong(); DistanceX = pStream->ReadDouble(); DistanceY = pStream->ReadDouble(); BlurSize = pStream->ReadDouble(); Color = pStream->ReadLong(); Alpha = pStream->ReadLong(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteLong(Visible); pStream->WriteDouble(DistanceX); pStream->WriteDouble(DistanceY); pStream->WriteDouble(BlurSize); pStream->WriteLong(Color); pStream->WriteLong(Alpha); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("visible"), Visible); oXmlWriter.WriteAttribute(_T("distancex"), DistanceX); oXmlWriter.WriteAttribute(_T("distancey"), DistanceY); oXmlWriter.WriteAttribute(_T("blursize"), BlurSize); oXmlWriter.WriteAttribute(_T("color"), Color); oXmlWriter.WriteAttribute(_T("alpha"), Alpha); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { Visible = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("visible"), _T("0"))); DistanceX = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("distancex"), _T("0"))); DistanceY = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("distancey"), _T("0"))); BlurSize = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("blursize"), _T("0"))); Color = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("alpha"), _T("0"))); Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { Visible = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("visible"), _T("0"))); DistanceX = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("distancex"), _T("0"))); DistanceY = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("distancey"), _T("0"))); BlurSize = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("blursize"), _T("0"))); Color = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alpha"), _T("0"))); Update(); } BOOL GetVisible() const { return Visible; } void SetVisible(BOOL bVisible) { Visible = bVisible; } double GetDistanceX() const { return DistanceX; } void SetDistanceX(double nDistanceX) { DistanceX = nDistanceX; } double GetDistanceY() const { return DistanceY; } void SetDistanceY(double nDistanceY) { DistanceY = nDistanceY; } double GetBlurSize() const { return BlurSize; } void SetBlurSize(double nBlurSize) { BlurSize = nBlurSize; } long GetColor() const { return Color; } void SetColor(long nColor) { if (Color != nColor) Clear(); Color = nColor; } long GetAlpha() const { return Alpha; } void SetAlpha(long nAlpha) { if (Alpha != nAlpha) Clear(); Alpha = nAlpha; } void FromShadow(const CShadow& oShadow) { SetVisible(oShadow.GetVisible()); SetDistanceX(oShadow.GetDistanceX()); SetDistanceY(oShadow.GetDistanceY()); SetBlurSize(oShadow.GetBlurSize()); SetColor(oShadow.GetColor()); SetAlpha(oShadow.GetAlpha()); } void SetDefaultParams() { Visible = FALSE; DistanceX = 15; DistanceY = 15; BlurSize = 0; Color = 0; Alpha = 120; } public: CShadow() { m_brush = 0; Visible = TRUE; DistanceX = 15; DistanceY = 15; BlurSize = 0; Color = 0; Alpha = 120; } CShadow( const CShadow& other ) { m_brush = NULL; Visible = other.Visible; DistanceX = other.DistanceX; DistanceY = other.DistanceY; BlurSize = other.BlurSize; Color = other.Color; Alpha = other.Alpha; } CShadow& operator=(const CShadow& shadow) { Clear(); FromShadow(shadow); return *this; } ~CShadow() { Clear(); } void Update() { Clear(); } void Clear() { if( m_brush ) { delete m_brush; m_brush = 0; } } Gdiplus::Brush* GetBrush() { if (m_brush) return m_brush; Gdiplus::Color color((BYTE)Alpha, GetRValue(Color), GetGValue(Color), GetBValue(Color)); Gdiplus::Brush* pBrush = new SolidBrush(color); m_brush = pBrush; return m_brush; } void Draw(Graphics* Gr, Gdiplus::Font* font, StringFormat* format, BSTR Text, int len, RectF& rectDraw) { if (!Visible || !Gr) return; RectF shadowRect = rectDraw; shadowRect.X += float(DistanceX); shadowRect.Y += float(DistanceY); if (BlurSize) { Gdiplus::Color color((BYTE)Alpha, GetRValue(Color), GetGValue(Color), GetBValue(Color)); SolidBrush solid(color); RectF temp = shadowRect; for(float i = (float)BlurSize + 1.0F; i >= 1.0F; i--) { int iAlpha = (int)((double)(Alpha/8./i/1.1)); solid.SetColor(Gdiplus::Color((BYTE)iAlpha, GetRValue(Color), GetGValue(Color), GetBValue(Color))); DrawBlurString((int)i, Gr, font, format, &solid, Text, len, temp); temp = shadowRect; } } else Gr->DrawString(Text, len, font, shadowRect, format, GetBrush()); } void Draw(Graphics* Gr, Gdiplus::Font* font, StringFormat* format, BSTR Text, int len, RectF& rectDraw, BYTE alpha) { if (!Visible || !Gr) return; RectF shadowRect = rectDraw; shadowRect.X += float(DistanceX); shadowRect.Y += float(DistanceY); Gdiplus::Color color((BYTE)(Alpha*alpha/255), GetRValue(Color), GetGValue(Color), GetBValue(Color)); SolidBrush solid(color); if (BlurSize) { RectF temp = shadowRect; int nBlurSize = int(BlurSize); for(int i = 1; i <= nBlurSize + 1; i++) { int iAlpha = (int)((double)((Alpha*alpha/255.)/8/(i)/1.1)); solid.SetColor(Gdiplus::Color((BYTE)iAlpha, GetRValue(Color), GetGValue(Color), GetBValue(Color))); DrawBlurString(i, Gr, font, format, &solid, Text, len, temp); temp = shadowRect; } } else Gr->DrawString(Text, len, font, shadowRect, format, &solid); } }; class CEdgeText { Gdiplus::Brush* m_brush; Gdiplus::Pen* m_pen; double m_dTransparency; public: long Visible; double Dist; long Color; long Alpha; public: int GetSize() { return 3*sizeof(long) + sizeof(double); } void Write(CStream& stream) { stream.WriteLong(Visible); stream.WriteDouble(Dist); stream.WriteLong(Color); stream.WriteLong(Alpha); } void Read(CStream& stream) { Visible = stream.ReadLong(); Dist = stream.ReadDouble(); Color = stream.ReadLong(); Alpha = stream.ReadLong(); Update(); } CString ToXmlString(CString strRootNodeName = _T("edgetext"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("visible"), Visible); oXmlWriter.WriteNode(_T("dist"), Dist); oXmlWriter.WriteNode(_T("color"), Color); oXmlWriter.WriteNode(_T("alpha"), Alpha); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); ToXmlAttributes(oXmlWriter); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); FromXmlAttributes(oXmlReader); } BOOL FromStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { Visible = pStream->ReadLong(); Dist = pStream->ReadDouble(); Color = pStream->ReadLong(); Alpha = pStream->ReadLong(); Update(); return TRUE; } catch (...) { } return FALSE; } BOOL ToStream(Streams::IStream* pStream) { if (!pStream) return FALSE; try { pStream->WriteLong(Visible); pStream->WriteDouble(Dist); pStream->WriteLong(Color); pStream->WriteLong(Alpha); return TRUE; } catch (...) { } return FALSE; } void ToXmlAttributes(XmlUtils::CXmlWriter& oXmlWriter) { oXmlWriter.WriteAttribute(_T("visible"), Visible); oXmlWriter.WriteAttribute(_T("dist"), Dist); oXmlWriter.WriteAttribute(_T("color"), Color); oXmlWriter.WriteAttribute(_T("alpha"), Alpha); } void FromXmlAttributes(XmlUtils::CXmlReader& oXmlReader) { Visible = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("visible"), _T("0"))); Dist = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("dist"), _T("0"))); Color = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("alpha"), _T("0"))); Update(); } void FromXmlNode(XmlUtils::CXmlNode& oXmlNode) { Visible = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("visible"), _T("0"))); Dist = XmlUtils::GetDouble(oXmlNode.GetAttributeOrValue(_T("dist"), _T("0"))); Color = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("color"), _T("0"))); Alpha = XmlUtils::GetInteger(oXmlNode.GetAttributeOrValue(_T("alpha"), _T("0"))); Update(); } long GetVisible() const { return Visible; } void SetVisible(long nVisible) { Visible = nVisible; } double GetDistance() const { return Dist; } void SetDistance(double nDistance) { Dist = nDistance; } long GetColor() const { return Color; } void SetColor(long nColor) { if (Color != nColor) Clear(); Color = nColor; } long GetAlpha() const { return Alpha; } void SetAlpha(long nAlpha) { if (Alpha != nAlpha) Clear(); Alpha = nAlpha; } void FromEdge(const CEdgeText& oEdge) { SetVisible(oEdge.GetVisible()); SetDistance(oEdge.GetDistance()); SetColor(oEdge.GetColor()); SetAlpha(oEdge.GetAlpha()); } void SetDefaultParams() { Visible = 0; Dist = 5; Color = 0; Alpha = 255; } public: CEdgeText() { m_brush = 0; m_pen = 0; Visible = 0; Dist = 5; Color = 0; Alpha = 255; m_dTransparency = 1; } CEdgeText( const CEdgeText& other ) { m_brush = 0; m_pen = 0; Visible = other.Visible; Dist = other.Dist; Color = other.Color; Alpha = other.Alpha; m_dTransparency = other.m_dTransparency; } CEdgeText& operator=(const CEdgeText& edge) { Clear(); FromEdge(edge); return *this; } ~CEdgeText() { Clear(); } void Update() { Clear(); } void Clear() { if (m_brush) { delete m_brush; m_brush = 0; } if (m_pen) { delete m_pen; m_pen = 0; } } void SetTransparency( double dIntensity ) { if( dIntensity > 1 ) dIntensity = 1; if( dIntensity < 0 ) dIntensity = 0; if( dIntensity != m_dTransparency ) { int nOldAlpha = int(m_dTransparency * Alpha + 0.5); int nNewAlpha = int(dIntensity * Alpha + 0.5); if( nNewAlpha != nOldAlpha ) { Update(); } m_dTransparency = dIntensity; } } double GetTransparency() const { return m_dTransparency; } Gdiplus::Brush* GetBrush() { if (m_brush) return m_brush; Gdiplus::Color color((BYTE)(Alpha * m_dTransparency + 0.5), GetRValue(Color), GetGValue(Color), GetBValue(Color)); Gdiplus::Brush* pBrush = new SolidBrush(color); m_brush = pBrush; return m_brush; } Gdiplus::Pen* GetPen() { if (m_pen) return m_pen; Gdiplus::Color color((BYTE)(Alpha * m_dTransparency + 0.5), GetRValue(Color), GetGValue(Color), GetBValue(Color)); Gdiplus::Pen* pPen = new Gdiplus::Pen( color, REAL(Dist) ); if( pPen ) { pPen->SetLineJoin(LineJoinRound); } m_pen = pPen; return pPen; } void Draw(Graphics* Gr, Gdiplus::Font* font, StringFormat* format, BSTR Text, int len, RectF& rectDraw) { if (!Visible || !Gr) return; if (Visible == -1) { Gdiplus::Color color((BYTE)(Alpha), GetRValue(Color), GetGValue(Color), GetBValue(Color)); SolidBrush solid(color); RectF temp = rectDraw; int offset = int(Dist); for(int i = offset; i >= 1; i--) { int iAlpha = (int)((double)(Alpha/8/(i)/1.1)); solid.SetColor(Gdiplus::Color((BYTE)iAlpha, GetRValue(Color), GetGValue(Color), GetBValue(Color))); DrawBlurString(i, Gr, font, format, &solid, Text, len, temp); temp = rectDraw; } } if (Visible == 1) { SmoothingMode oldSmoothingMode = Gr->GetSmoothingMode(); Gr->SetSmoothingMode(SmoothingModeHighQuality); RectF temp = rectDraw; FontFamily family; font->GetFamily(&family); GraphicsPath path; path.AddString(Text, len, &family, font->GetStyle(), font->GetSize(), temp, format); int offset = int(Dist); for (int i = 1; i <= offset; i++) { Gdiplus::Pen pen(Gdiplus::Color((BYTE)(Alpha*i/offset), GetRValue(Color), GetGValue(Color), GetBValue(Color)), (REAL) 2*(offset - i + 1)); pen.SetLineCap(LineCapRound, LineCapRound, DashCapRound); Gr->DrawPath(&pen, &path); } Gr->SetSmoothingMode(oldSmoothingMode); } if (Visible == 2) { GraphicsState state = Gr->Save(); Gr->SetSmoothingMode(SmoothingModeHighQuality); Gr->SetClip(rectDraw); RectF temp = rectDraw; FontFamily family; font->GetFamily(&family); GraphicsPath path; path.AddString(Text, len, &family, font->GetStyle(), font->GetSize(), temp, format); int offset = int(Dist); for (int i = 1; i <= offset; i++) { Gdiplus::Pen pen(Gdiplus::Color((BYTE)(Alpha*i/offset), GetRValue(Color), GetGValue(Color), GetBValue(Color)), (REAL) 2*(offset - i + 1)); pen.SetLineCap(LineCapRound, LineCapRound, DashCapRound); Gr->DrawPath(&pen, &path); } Gr->Restore(state); } } void Draw(Graphics* Gr, Gdiplus::Font* font, StringFormat* format, BSTR Text, int len, RectF& rectDraw, BYTE alpha) { if (!Visible || !Gr) return; if (Visible == -1) { Gdiplus::Color color((BYTE)((double)(Alpha*alpha/255.), GetRValue(Color), GetGValue(Color), GetBValue(Color))); SolidBrush solid(color); RectF temp = rectDraw; for(int i = 1; i <= Dist; i++) { int iAlpha = (int)((double)(Alpha*alpha/255./8/(i)/1.1)); solid.SetColor(Gdiplus::Color((BYTE)iAlpha, GetRValue(Color), GetGValue(Color), GetBValue(Color))); DrawBlurString(i, Gr, font, format, &solid, Text, len, temp); temp = rectDraw; } } if (Visible == 1) { SmoothingMode oldSmoothingMode = Gr->GetSmoothingMode(); Gr->SetSmoothingMode(SmoothingModeHighQuality); FontFamily family; font->GetFamily(&family); GraphicsPath path; path.AddString(Text, len, &family, font->GetStyle(), font->GetSize(), rectDraw, format); int offset = int(Dist); for (int i = 1; i <= offset; i++) { Gdiplus::Pen pen(Gdiplus::Color((BYTE)(Alpha*i*alpha/(offset*255)), GetRValue(Color), GetGValue(Color), GetBValue(Color)), (REAL) 2*(offset - i + 1)); pen.SetLineCap(LineCapRound, LineCapRound, DashCapRound); Gr->DrawPath(&pen, &path); } Gr->SetSmoothingMode(oldSmoothingMode); } } }; class CLine { public: double X1; double Y1; double X2; double Y2; public: int GetSize() { return 4*sizeof(double) + (4); } void Write(CStream& stream) { stream.WriteDouble(X1); stream.WriteDouble(Y1); stream.WriteDouble(X2); stream.WriteDouble(Y2); } void Read(CStream& stream) { Clear(); X1 = stream.ReadDouble(); Y1 = stream.ReadDouble(); X2 = stream.ReadDouble(); Y2 = stream.ReadDouble(); } CString ToXmlString(CString strRootNodeName = _T("line"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("x1"), X1); oXmlWriter.WriteNode(_T("y1"), Y1); oXmlWriter.WriteNode(_T("x2"), X2); oXmlWriter.WriteNode(_T("y2"), Y2); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); oXmlWriter.WriteAttribute(_T("x1"), X1); oXmlWriter.WriteAttribute(_T("y1"), Y1); oXmlWriter.WriteAttribute(_T("x2"), X2); oXmlWriter.WriteAttribute(_T("y2"), Y2); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { Clear(); XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); X1 = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("x1"), _T("0"))); Y1 = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("y1"), _T("0"))); X2 = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("x2"), _T("0"))); Y2 = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("y2"), _T("0"))); } public: CLine() { X1 = 0; Y1 = 0; X2 = 0; Y2 = 0; } CLine& operator=(const CLine& line) { Clear(); X1 = line.X1; Y1 = line.Y1; X2 = line.X2; Y2 = line.Y2; return *this; } ~CLine() { Clear(); } void Clear() { X1 = 0; Y1 = 0; X2 = 0; Y2 = 0; } }; class CRectangle { public: double Left; double Top; double Width; double Height; public: int GetSize() { return 4*sizeof(double) + (4); } void Write(CStream& stream) { stream.WriteDouble(Left); stream.WriteDouble(Top); stream.WriteDouble(Width); stream.WriteDouble(Height); } void Read(CStream& stream) { Clear(); Left = stream.ReadDouble(); Top = stream.ReadDouble(); Width = stream.ReadDouble(); Height = stream.ReadDouble(); } CString ToXmlString(CString strRootNodeName = _T("rectangle"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("left"), Left); oXmlWriter.WriteNode(_T("top"), Top); oXmlWriter.WriteNode(_T("width"), Width); oXmlWriter.WriteNode(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); oXmlWriter.WriteAttribute(_T("left"), Left); oXmlWriter.WriteAttribute(_T("top"), Top); oXmlWriter.WriteAttribute(_T("width"), Width); oXmlWriter.WriteAttribute(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { Clear(); XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); Left = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("left"), _T("0"))); Top = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("top"), _T("0"))); Width = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("width"), _T("0"))); Height = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("height"), _T("0"))); } public: CRectangle() { Left = 0; Top = 0; Width = 0; Height = 0; } CRectangle& operator=(const CRectangle& rectangle) { Clear(); Left = rectangle.Left; Top = rectangle.Top; Width = rectangle.Width; Height = rectangle.Height; return *this; } ~CRectangle() { Clear(); } void Clear() { Left = 0; Top = 0; Width = 0; Height = 0; } }; class CEllipse { public: double Left; double Top; double Width; double Height; public: int GetSize() { return 4*sizeof(double) + (4); } void Write(CStream& stream) { stream.WriteDouble(Left); stream.WriteDouble(Top); stream.WriteDouble(Width); stream.WriteDouble(Height); } void Read(CStream& stream) { Clear(); Left = stream.ReadDouble(); Top = stream.ReadDouble(); Width = stream.ReadDouble(); Height = stream.ReadDouble(); } CString ToXmlString(CString strRootNodeName = _T("ellipse"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("left"), Left); oXmlWriter.WriteNode(_T("top"), Top); oXmlWriter.WriteNode(_T("width"), Width); oXmlWriter.WriteNode(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); oXmlWriter.WriteAttribute(_T("left"), Left); oXmlWriter.WriteAttribute(_T("top"), Top); oXmlWriter.WriteAttribute(_T("width"), Width); oXmlWriter.WriteAttribute(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { Clear(); XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); Left = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("left"), _T("0"))); Top = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("top"), _T("0"))); Width = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("width"), _T("0"))); Height = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("height"), _T("0"))); } public: CEllipse() { Left = 0; Top = 0; Width = 0; Height = 0; } CEllipse& operator=(const CEllipse& ellipse) { Clear(); Left = ellipse.Left; Top = ellipse.Top; Width = ellipse.Width; Height = ellipse.Height; return *this; } ~CEllipse() { Clear(); } void Clear() { Left = 0; Top = 0; Width = 0; Height = 0; } }; class CText { public: double Left; double Top; double Width; double Height; CString Text; public: int GetSize() { return 4*sizeof(double) + Text.GetLength() + 1 + (4); } void Write(CStream& stream) { stream.WriteDouble(Left); stream.WriteDouble(Top); stream.WriteDouble(Width); stream.WriteDouble(Height); stream.WriteString(Text); } void Read(CStream& stream) { Clear(); Left = stream.ReadDouble(); Top = stream.ReadDouble(); Width = stream.ReadDouble(); Height = stream.ReadDouble(); Text = stream.ReadString(); } CString ToXmlString(CString strRootNodeName = _T("text"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("left"), Left); oXmlWriter.WriteNode(_T("top"), Top); oXmlWriter.WriteNode(_T("width"), Width); oXmlWriter.WriteNode(_T("height"), Height); oXmlWriter.WriteNode(_T("text"), Text); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); oXmlWriter.WriteAttribute(_T("left"), Left); oXmlWriter.WriteAttribute(_T("top"), Top); oXmlWriter.WriteAttribute(_T("width"), Width); oXmlWriter.WriteAttribute(_T("height"), Height); oXmlWriter.WriteAttribute(_T("text"), Text); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { Clear(); XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); Left = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("left"), _T("0"))); Top = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("top"), _T("0"))); Width = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("width"), _T("0"))); Height = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("height"), _T("0"))); Text = oXmlReader.ReadNodeAttributeOrValue(_T("text"), _T("")); } public: CText() { Left = 0; Top = 0; Width = 0; Height = 0; Text = ""; } CText& operator=(const CText& text) { Clear(); Left = text.Left; Top = text.Top; Width = text.Width; Height = text.Height; Text = text.Text; return *this; } ~CText() { Clear(); } void Clear() { Left = 0; Top = 0; Width = 0; Height = 0; Text = ""; } }; class CTransformCrop { public: BOOL ClearBackground; double Left; double Top; double Width; double Height; public: int GetSize() { return 4*sizeof(double) + sizeof(long) + (4); } void Write(CStream& stream) { stream.WriteLong(ClearBackground); stream.WriteDouble(Left); stream.WriteDouble(Top); stream.WriteDouble(Width); stream.WriteDouble(Height); } void Read(CStream& stream) { Clear(); ClearBackground = stream.ReadLong(); Left = stream.ReadDouble(); Top = stream.ReadDouble(); Width = stream.ReadDouble(); Height = stream.ReadDouble(); } CString ToXmlString(CString strRootNodeName = _T("transform-crop"), BOOL bAttributed = FALSE) { XmlUtils::CXmlWriter oXmlWriter; if (!bAttributed) { oXmlWriter.WriteNodeBegin(strRootNodeName); oXmlWriter.WriteNode(_T("clear"), ClearBackground); oXmlWriter.WriteNode(_T("left"), Left); oXmlWriter.WriteNode(_T("top"), Top); oXmlWriter.WriteNode(_T("width"), Width); oXmlWriter.WriteNode(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName); } else { oXmlWriter.WriteNodeBegin(strRootNodeName, TRUE); oXmlWriter.WriteAttribute(_T("clear"), ClearBackground); oXmlWriter.WriteAttribute(_T("left"), Left); oXmlWriter.WriteAttribute(_T("top"), Top); oXmlWriter.WriteAttribute(_T("width"), Width); oXmlWriter.WriteAttribute(_T("height"), Height); oXmlWriter.WriteNodeEnd(strRootNodeName, TRUE); } return oXmlWriter.GetXmlString(); } void FromXmlString(CString strXml) { Clear(); XmlUtils::CXmlReader oXmlReader; oXmlReader.SetXmlString(strXml); oXmlReader.ReadRootNode(); ClearBackground = XmlUtils::GetInteger(oXmlReader.ReadNodeAttributeOrValue(_T("clear"), _T("0"))); Left = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("left"), _T("0"))); Top = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("top"), _T("0"))); Width = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("width"), _T("0"))); Height = XmlUtils::GetDouble(oXmlReader.ReadNodeAttributeOrValue(_T("height"), _T("0"))); } public: CTransformCrop() { ClearBackground = 1; Left = 0; Top = 0; Width = 0; Height = 0; } CTransformCrop& operator=(const CTransformCrop& transform) { Clear(); ClearBackground = transform.ClearBackground; Left = transform.Left; Top = transform.Top; Width = transform.Width; Height = transform.Height; return *this; } ~CTransformCrop() { Clear(); } void Clear() { ClearBackground = 1; Left = 0; Top = 0; Width = 0; Height = 0; } }; }