diff options
Diffstat (limited to 'xfa/fxgraphics/fx_graphics.cpp')
-rw-r--r-- | xfa/fxgraphics/fx_graphics.cpp | 1548 |
1 files changed, 1548 insertions, 0 deletions
diff --git a/xfa/fxgraphics/fx_graphics.cpp b/xfa/fxgraphics/fx_graphics.cpp new file mode 100644 index 0000000000..a3fb84dbb0 --- /dev/null +++ b/xfa/fxgraphics/fx_graphics.cpp @@ -0,0 +1,1548 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/include/fxgraphics/fx_graphics.h" + +#include <memory> + +#include "xfa/fxgraphics/fx_path_generator.h" +#include "xfa/fxgraphics/pre.h" + +class CAGG_Graphics { + public: + CAGG_Graphics(); + FX_ERR Create(CFX_Graphics* owner, + int32_t width, + int32_t height, + FXDIB_Format format); + virtual ~CAGG_Graphics(); + + private: + CFX_Graphics* _owner; +}; +CFX_Graphics::CFX_Graphics() { + _type = FX_CONTEXT_None; + _info._graphState.SetDashCount(0); + _info._isAntialiasing = TRUE; + _info._strokeAlignment = FX_STROKEALIGNMENT_Center; + _info._CTM.SetIdentity(); + _info._isActOnDash = FALSE; + _info._strokeColor = NULL; + _info._fillColor = NULL; + _info._font = NULL; + _info._fontSize = 40.0; + _info._fontHScale = 1.0; + _info._fontSpacing = 0.0; + _renderDevice = NULL; + _aggGraphics = NULL; +} +FX_ERR CFX_Graphics::Create(CFX_RenderDevice* renderDevice, + FX_BOOL isAntialiasing) { + if (!renderDevice) + return FX_ERR_Parameter_Invalid; + if (_type != FX_CONTEXT_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_CONTEXT_Device; + _info._isAntialiasing = isAntialiasing; + _renderDevice = renderDevice; + if (_renderDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP) { + return FX_ERR_Succeeded; + } + return FX_ERR_Indefinite; +} +FX_ERR CFX_Graphics::Create(int32_t width, + int32_t height, + FXDIB_Format format, + FX_BOOL isNative, + FX_BOOL isAntialiasing) { + if (_type != FX_CONTEXT_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_CONTEXT_Device; + _info._isAntialiasing = isAntialiasing; + { + _aggGraphics = new CAGG_Graphics; + return _aggGraphics->Create(this, width, height, format); + } +} +CFX_Graphics::~CFX_Graphics() { + if (_aggGraphics) { + delete _aggGraphics; + _aggGraphics = NULL; + } + _renderDevice = NULL; + _info._graphState.SetDashCount(0); + _type = FX_CONTEXT_None; +} +FX_ERR CFX_Graphics::GetDeviceCap(const int32_t capID, FX_DeviceCap& capVal) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + capVal = _renderDevice->GetDeviceCaps(capID); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::IsPrinterDevice(FX_BOOL& isPrinter) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + int32_t deviceClass = _renderDevice->GetDeviceClass(); + if (deviceClass == FXDC_PRINTER) { + isPrinter = TRUE; + } else { + isPrinter = FALSE; + } + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::EnableAntialiasing(FX_BOOL isAntialiasing) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._isAntialiasing = isAntialiasing; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SaveGraphState() { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _renderDevice->SaveState(); + TInfo* info = new TInfo; + info->_graphState.Copy(_info._graphState); + info->_isAntialiasing = _info._isAntialiasing; + info->_strokeAlignment = _info._strokeAlignment; + info->_CTM = _info._CTM; + info->_isActOnDash = _info._isActOnDash; + info->_strokeColor = _info._strokeColor; + info->_fillColor = _info._fillColor; + info->_font = _info._font; + info->_fontSize = _info._fontSize; + info->_fontHScale = _info._fontHScale; + info->_fontSpacing = _info._fontSpacing; + _infoStack.Add(info); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::RestoreGraphState() { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _renderDevice->RestoreState(); + int32_t size = _infoStack.GetSize(); + if (size <= 0) { + return FX_ERR_Intermediate_Value_Invalid; + } + int32_t topIndex = size - 1; + TInfo* info = (TInfo*)_infoStack.GetAt(topIndex); + if (!info) + return FX_ERR_Intermediate_Value_Invalid; + _info._graphState.Copy(info->_graphState); + _info._isAntialiasing = info->_isAntialiasing; + _info._strokeAlignment = info->_strokeAlignment; + _info._CTM = info->_CTM; + _info._isActOnDash = info->_isActOnDash; + _info._strokeColor = info->_strokeColor; + _info._fillColor = info->_fillColor; + _info._font = info->_font; + _info._fontSize = info->_fontSize; + _info._fontHScale = info->_fontHScale; + _info._fontSpacing = info->_fontSpacing; + delete info; + info = NULL; + _infoStack.RemoveAt(topIndex); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetLineCap(CFX_GraphStateData::LineCap& lineCap) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + lineCap = _info._graphState.m_LineCap; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._graphState.m_LineCap = lineCap; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetDashCount(int32_t& dashCount) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + dashCount = _info._graphState.m_DashCount; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetLineDash(FX_FLOAT& dashPhase, FX_FLOAT* dashArray) { + if (!dashArray) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + dashPhase = _info._graphState.m_DashPhase; + FXSYS_memcpy(dashArray, _info._graphState.m_DashArray, + _info._graphState.m_DashCount * sizeof(FX_FLOAT)); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetLineDash(FX_FLOAT dashPhase, + FX_FLOAT* dashArray, + int32_t dashCount) { + if (dashCount > 0 && !dashArray) { + return FX_ERR_Parameter_Invalid; + } + dashCount = dashCount < 0 ? 0 : dashCount; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + FX_FLOAT scale = 1.0; + if (_info._isActOnDash) { + scale = _info._graphState.m_LineWidth; + } + _info._graphState.m_DashPhase = dashPhase; + _info._graphState.SetDashCount(dashCount); + for (int32_t i = 0; i < dashCount; i++) { + _info._graphState.m_DashArray[i] = dashArray[i] * scale; + } + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetLineDash(FX_DashStyle dashStyle) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceSetLineDash(dashStyle); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetLineJoin(CFX_GraphStateData::LineJoin& lineJoin) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + lineJoin = _info._graphState.m_LineJoin; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetLineJoin(CFX_GraphStateData::LineJoin lineJoin) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._graphState.m_LineJoin = lineJoin; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetMiterLimit(FX_FLOAT& miterLimit) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + miterLimit = _info._graphState.m_MiterLimit; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetMiterLimit(FX_FLOAT miterLimit) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._graphState.m_MiterLimit = miterLimit; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetLineWidth(FX_FLOAT& lineWidth) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + lineWidth = _info._graphState.m_LineWidth; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetLineWidth(FX_FLOAT lineWidth, FX_BOOL isActOnDash) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._graphState.m_LineWidth = lineWidth; + _info._isActOnDash = isActOnDash; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::GetStrokeAlignment(FX_StrokeAlignment& strokeAlignment) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + strokeAlignment = _info._strokeAlignment; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetStrokeAlignment(FX_StrokeAlignment strokeAlignment) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._strokeAlignment = strokeAlignment; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetStrokeColor(CFX_Color* color) { + if (!color) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._strokeColor = color; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetFillColor(CFX_Color* color) { + if (!color) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._fillColor = color; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::StrokePath(CFX_Path* path, CFX_Matrix* matrix) { + if (!path) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceStrokePath(path, matrix); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::FillPath(CFX_Path* path, + FX_FillMode fillMode, + CFX_Matrix* matrix) { + if (!path) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceFillPath(path, fillMode, matrix); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::ClipPath(CFX_Path* path, + FX_FillMode fillMode, + CFX_Matrix* matrix) { + if (!path) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + FX_BOOL result = _renderDevice->SetClip_PathFill( + path->GetPathData(), (CFX_Matrix*)matrix, fillMode); + if (!result) + return FX_ERR_Indefinite; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::DrawImage(CFX_DIBSource* source, + const CFX_PointF& point, + CFX_Matrix* matrix) { + if (!source) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceDrawImage(source, point, matrix); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::StretchImage(CFX_DIBSource* source, + const CFX_RectF& rect, + CFX_Matrix* matrix) { + if (!source) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceStretchImage(source, rect, matrix); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::ConcatMatrix(const CFX_Matrix* matrix) { + if (!matrix) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._CTM.Concat(*matrix); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +CFX_Matrix* CFX_Graphics::GetMatrix() { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return NULL; + return &_info._CTM; + } + default: { return NULL; } + } +} +FX_ERR CFX_Graphics::GetClipRect(CFX_RectF& rect) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + FX_RECT r = _renderDevice->GetClipBox(); + rect.left = (FX_FLOAT)r.left; + rect.top = (FX_FLOAT)r.top; + rect.width = (FX_FLOAT)r.Width(); + rect.height = (FX_FLOAT)r.Height(); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetClipRect(const CFX_RectF& rect) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + if (!_renderDevice->SetClip_Rect( + FX_RECT(FXSYS_round(rect.left), FXSYS_round(rect.top), + FXSYS_round(rect.right()), FXSYS_round(rect.bottom())))) { + return FX_ERR_Method_Not_Supported; + } + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::ClearClip() { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetFont(CFX_Font* font) { + if (!font) + return FX_ERR_Parameter_Invalid; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._font = font; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetFontSize(const FX_FLOAT size) { + FX_FLOAT fontSize = size <= 0 ? 1.0f : size; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._fontSize = fontSize; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetFontHScale(const FX_FLOAT scale) { + FX_FLOAT fontHScale = scale <= 0 ? 1.0f : scale; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._fontHScale = fontHScale; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetCharSpacing(const FX_FLOAT spacing) { + FX_FLOAT fontSpacing = spacing < 0 ? 0 : spacing; + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + _info._fontSpacing = fontSpacing; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::SetTextDrawingMode(const int32_t mode) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::ShowText(const CFX_PointF& point, + const CFX_WideString& text, + CFX_Matrix* matrix) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + return RenderDeviceShowText(point, text, matrix); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::CalcTextRect(CFX_RectF& rect, + const CFX_WideString& text, + FX_BOOL isMultiline, + CFX_Matrix* matrix) { + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + int32_t length = text.GetLength(); + FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length); + FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length); + CalcTextInfo(text, charCodes, charPos, rect); + FX_Free(charPos); + FX_Free(charCodes); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics, + const CFX_Matrix* matrix) { + if (!graphics) + return FX_ERR_Parameter_Invalid; + CFX_Matrix m; + m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m.Concat(*matrix); + } + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + { + if (!graphics->_renderDevice) + return FX_ERR_Parameter_Invalid; + CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap(); + FX_BOOL result = _renderDevice->SetDIBits(bitmap, 0, 0); + if (!result) + return FX_ERR_Method_Not_Supported; + } + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics, + FX_FLOAT srcLeft, + FX_FLOAT srcTop, + const CFX_RectF& dstRect, + const CFX_Matrix* matrix) { + if (!graphics) + return FX_ERR_Parameter_Invalid; + CFX_Matrix m; + m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m.Concat(*matrix); + } + switch (_type) { + case FX_CONTEXT_Device: { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + { + if (!graphics->_renderDevice) + return FX_ERR_Parameter_Invalid; + CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap(); + CFX_DIBitmap bmp; + FX_BOOL result = + bmp.Create((int32_t)dstRect.width, (int32_t)dstRect.height, + bitmap->GetFormat()); + if (!result) + return FX_ERR_Intermediate_Value_Invalid; + result = graphics->_renderDevice->GetDIBits(&bmp, (int32_t)srcLeft, + (int32_t)srcTop); + if (!result) + return FX_ERR_Method_Not_Supported; + result = _renderDevice->SetDIBits(&bmp, (int32_t)dstRect.left, + (int32_t)dstRect.top); + if (!result) + return FX_ERR_Method_Not_Supported; + return FX_ERR_Succeeded; + } + } + default: { return FX_ERR_Property_Invalid; } + } +} +CFX_RenderDevice* CFX_Graphics::GetRenderDevice() { + return _renderDevice; +} +FX_ERR CFX_Graphics::InverseRect(const CFX_RectF& rect) { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); + if (!bitmap) + return FX_ERR_Property_Invalid; + CFX_RectF temp(rect); + _info._CTM.TransformRect(temp); + CFX_RectF r; + r.Set(0, 0, (FX_FLOAT)bitmap->GetWidth(), (FX_FLOAT)bitmap->GetWidth()); + r.Intersect(temp); + if (r.IsEmpty()) { + return FX_ERR_Parameter_Invalid; + } + FX_ARGB* pBuf = + (FX_ARGB*)(bitmap->GetBuffer() + int32_t(r.top) * bitmap->GetPitch()); + int32_t bottom = (int32_t)r.bottom(); + int32_t right = (int32_t)r.right(); + for (int32_t i = (int32_t)r.top; i < bottom; i++) { + FX_ARGB* pLine = pBuf + (int32_t)r.left; + for (int32_t j = (int32_t)r.left; j < right; j++) { + FX_ARGB c = *pLine; + *pLine++ = (c & 0xFF000000) | (0xFFFFFF - (c & 0x00FFFFFF)); + } + pBuf = (FX_ARGB*)((uint8_t*)pBuf + bitmap->GetPitch()); + } + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::XorDIBitmap(const CFX_DIBitmap* srcBitmap, + const CFX_RectF& rect) { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + CFX_DIBitmap* dst = _renderDevice->GetBitmap(); + if (!dst) + return FX_ERR_Property_Invalid; + CFX_RectF temp(rect); + _info._CTM.TransformRect(temp); + CFX_RectF r; + r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth()); + r.Intersect(temp); + if (r.IsEmpty()) { + return FX_ERR_Parameter_Invalid; + } + FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() + + int32_t(r.top) * srcBitmap->GetPitch()); + FX_ARGB* pDstBuf = + (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch()); + int32_t bottom = (int32_t)r.bottom(); + int32_t right = (int32_t)r.right(); + for (int32_t i = (int32_t)r.top; i < bottom; i++) { + FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left; + FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left; + for (int32_t j = (int32_t)r.left; j < right; j++) { + FX_ARGB c = *pDstLine; + *pDstLine++ = + ArgbEncode(FXARGB_A(c), (c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF)); + pSrcLine++; + } + pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch()); + pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch()); + } + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::EqvDIBitmap(const CFX_DIBitmap* srcBitmap, + const CFX_RectF& rect) { + if (!_renderDevice) + return FX_ERR_Property_Invalid; + CFX_DIBitmap* dst = _renderDevice->GetBitmap(); + if (!dst) + return FX_ERR_Property_Invalid; + CFX_RectF temp(rect); + _info._CTM.TransformRect(temp); + CFX_RectF r; + r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth()); + r.Intersect(temp); + if (r.IsEmpty()) { + return FX_ERR_Parameter_Invalid; + } + FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() + + int32_t(r.top) * srcBitmap->GetPitch()); + FX_ARGB* pDstBuf = + (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch()); + int32_t bottom = (int32_t)r.bottom(); + int32_t right = (int32_t)r.right(); + for (int32_t i = (int32_t)r.top; i < bottom; i++) { + FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left; + FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left; + for (int32_t j = (int32_t)r.left; j < right; j++) { + FX_ARGB c = *pDstLine; + *pDstLine++ = + ArgbEncode(FXARGB_A(c), ~((c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF))); + pSrcLine++; + } + pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch()); + pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch()); + } + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::RenderDeviceSetLineDash(FX_DashStyle dashStyle) { + switch (dashStyle) { + case FX_DASHSTYLE_Solid: { + _info._graphState.SetDashCount(0); + return FX_ERR_Succeeded; + } + case FX_DASHSTYLE_Dash: { + FX_FLOAT dashArray[] = {3, 1}; + SetLineDash(0, dashArray, 2); + return FX_ERR_Succeeded; + } + case FX_DASHSTYLE_Dot: { + FX_FLOAT dashArray[] = {1, 1}; + SetLineDash(0, dashArray, 2); + return FX_ERR_Succeeded; + } + case FX_DASHSTYLE_DashDot: { + FX_FLOAT dashArray[] = {3, 1, 1, 1}; + SetLineDash(0, dashArray, 4); + return FX_ERR_Succeeded; + } + case FX_DASHSTYLE_DashDotDot: { + FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; + SetLineDash(0, dashArray, 6); + return FX_ERR_Succeeded; + } + default: { return FX_ERR_Parameter_Invalid; } + } +} +FX_ERR CFX_Graphics::RenderDeviceStrokePath(CFX_Path* path, + CFX_Matrix* matrix) { + if (!_info._strokeColor) + return FX_ERR_Property_Invalid; + CFX_Matrix m; + m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m.Concat(*matrix); + } + switch (_info._strokeColor->_type) { + case FX_COLOR_Solid: { + FX_BOOL result = _renderDevice->DrawPath( + path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState, 0x0, + _info._strokeColor->_argb, 0); + if (!result) + return FX_ERR_Indefinite; + return FX_ERR_Succeeded; + } + case FX_COLOR_Pattern: { + return StrokePathWithPattern(path, &m); + } + case FX_COLOR_Shading: { + return StrokePathWithShading(path, &m); + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::RenderDeviceFillPath(CFX_Path* path, + FX_FillMode fillMode, + CFX_Matrix* matrix) { + if (!_info._fillColor) + return FX_ERR_Property_Invalid; + CFX_Matrix m; + m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m.Concat(*matrix); + } + switch (_info._fillColor->_type) { + case FX_COLOR_Solid: { + FX_BOOL result = _renderDevice->DrawPath( + path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState, + _info._fillColor->_argb, 0x0, fillMode); + if (!result) + return FX_ERR_Indefinite; + return FX_ERR_Succeeded; + } + case FX_COLOR_Pattern: { + { return FillPathWithPattern(path, fillMode, &m); } + } + case FX_COLOR_Shading: { + { return FillPathWithShading(path, fillMode, &m); } + } + default: { return FX_ERR_Property_Invalid; } + } +} +FX_ERR CFX_Graphics::RenderDeviceDrawImage(CFX_DIBSource* source, + const CFX_PointF& point, + CFX_Matrix* matrix) { + CFX_Matrix m1; + m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m1.Concat(*matrix); + } + CFX_Matrix m2; + m2.Set((FX_FLOAT)source->GetWidth(), 0.0, 0.0, (FX_FLOAT)source->GetHeight(), + point.x, point.y); + m2.Concat(m1); + int32_t left, top; + CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE); + CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m2, left, top); + CFX_RectF r; + GetClipRect(r); + FX_ERR result = FX_ERR_Indefinite; + { + CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); + CFX_DIBitmap bmp; + bmp.Create(bitmap->GetWidth(), bitmap->GetHeight(), FXDIB_Argb); + _renderDevice->GetDIBits(&bmp, 0, 0); + bmp.TransferBitmap(FXSYS_round(r.left), FXSYS_round(r.top), + FXSYS_round(r.Width()), FXSYS_round(r.Height()), bmp2, + FXSYS_round(r.left - left), FXSYS_round(r.top - top)); + _renderDevice->SetDIBits(&bmp, 0, 0); + result = FX_ERR_Succeeded; + } + if (bmp2) { + delete bmp2; + bmp2 = NULL; + } + if (bmp1) { + delete bmp1; + bmp1 = NULL; + } + return result; +} +FX_ERR CFX_Graphics::RenderDeviceStretchImage(CFX_DIBSource* source, + const CFX_RectF& rect, + CFX_Matrix* matrix) { + CFX_Matrix m1; + m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + if (matrix) { + m1.Concat(*matrix); + } + CFX_DIBitmap* bmp1 = + source->StretchTo((int32_t)rect.Width(), (int32_t)rect.Height()); + CFX_Matrix m2; + m2.Set(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top); + m2.Concat(m1); + int32_t left, top; + CFX_DIBitmap* bmp2 = bmp1->FlipImage(FALSE, TRUE); + CFX_DIBitmap* bmp3 = bmp2->TransformTo((CFX_Matrix*)&m2, left, top); + CFX_RectF r; + GetClipRect(r); + FX_ERR result = FX_ERR_Indefinite; + { + CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); + bitmap->CompositeBitmap(FXSYS_round(r.left), FXSYS_round(r.top), + FXSYS_round(r.Width()), FXSYS_round(r.Height()), + bmp3, FXSYS_round(r.left - left), + FXSYS_round(r.top - top)); + result = FX_ERR_Succeeded; + } + if (bmp3) { + delete bmp3; + bmp3 = NULL; + } + if (bmp2) { + delete bmp2; + bmp2 = NULL; + } + if (bmp1) { + delete bmp1; + bmp1 = NULL; + } + return result; +} +FX_ERR CFX_Graphics::RenderDeviceShowText(const CFX_PointF& point, + const CFX_WideString& text, + CFX_Matrix* matrix) { + int32_t length = text.GetLength(); + FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length); + FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length); + CFX_RectF rect; + rect.Set(point.x, point.y, 0, 0); + CalcTextInfo(text, charCodes, charPos, rect); + CFX_Matrix m; + m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, + _info._CTM.f); + m.Translate(0, _info._fontSize * _info._fontHScale); + if (matrix) { + m.Concat(*matrix); + } + FX_BOOL result = _renderDevice->DrawNormalText( + length, charPos, _info._font, CFX_GEModule::Get()->GetFontCache(), + -_info._fontSize * _info._fontHScale, (CFX_Matrix*)&m, + _info._fillColor->_argb, FXTEXT_CLEARTYPE); + if (!result) + return FX_ERR_Indefinite; + FX_Free(charPos); + FX_Free(charCodes); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::StrokePathWithPattern(CFX_Path* path, CFX_Matrix* matrix) { + return FX_ERR_Method_Not_Supported; +} +FX_ERR CFX_Graphics::StrokePathWithShading(CFX_Path* path, CFX_Matrix* matrix) { + return FX_ERR_Method_Not_Supported; +} +FX_ERR CFX_Graphics::FillPathWithPattern(CFX_Path* path, + FX_FillMode fillMode, + CFX_Matrix* matrix) { + CFX_Pattern* pattern = _info._fillColor->_pattern; + CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); + int32_t width = bitmap->GetWidth(); + int32_t height = bitmap->GetHeight(); + CFX_DIBitmap bmp; + bmp.Create(width, height, FXDIB_Argb); + _renderDevice->GetDIBits(&bmp, 0, 0); + switch (pattern->_type) { + case FX_PATTERN_Bitmap: { + int32_t xStep = FXSYS_round(pattern->_x1Step); + int32_t yStep = FXSYS_round(pattern->_y1Step); + int32_t xCount = width / xStep + 1; + int32_t yCount = height / yStep + 1; + for (int32_t i = 0; i <= yCount; i++) { + for (int32_t j = 0; j <= xCount; j++) { + bmp.TransferBitmap(j * xStep, i * yStep, xStep, yStep, + pattern->_bitmap, 0, 0); + } + } + break; + } + case FX_PATTERN_Hatch: { + FX_HatchStyle hatchStyle = _info._fillColor->_pattern->_hatchStyle; + if (hatchStyle < FX_HATCHSTYLE_Horizontal || + hatchStyle > FX_HATCHSTYLE_SolidDiamond) { + return FX_ERR_Intermediate_Value_Invalid; + } + const FX_HATCHDATA& data = hatchBitmapData[hatchStyle]; + CFX_DIBitmap mask; + mask.Create(data.width, data.height, FXDIB_1bppMask); + FXSYS_memcpy(mask.GetBuffer(), data.maskBits, + mask.GetPitch() * data.height); + CFX_FloatRect rectf = path->GetPathData()->GetBoundingBox(); + if (matrix) { + rectf.Transform((const CFX_Matrix*)matrix); + } + FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top), + FXSYS_round(rectf.right), FXSYS_round(rectf.bottom)); + CFX_FxgeDevice device; + device.Attach(&bmp); + device.FillRect(&rect, _info._fillColor->_pattern->_backArgb); + for (int32_t j = rect.bottom; j < rect.top; j += mask.GetHeight()) { + for (int32_t i = rect.left; i < rect.right; i += mask.GetWidth()) { + device.SetBitMask(&mask, i, j, _info._fillColor->_pattern->_foreArgb); + } + } + break; + } + } + _renderDevice->SaveState(); + _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix, + fillMode); + SetDIBitsWithMatrix(&bmp, &pattern->_matrix); + _renderDevice->RestoreState(); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::FillPathWithShading(CFX_Path* path, + FX_FillMode fillMode, + CFX_Matrix* matrix) { + CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); + int32_t width = bitmap->GetWidth(); + int32_t height = bitmap->GetHeight(); + FX_FLOAT start_x = _info._fillColor->_shading->_beginPoint.x; + FX_FLOAT start_y = _info._fillColor->_shading->_beginPoint.y; + FX_FLOAT end_x = _info._fillColor->_shading->_endPoint.x; + FX_FLOAT end_y = _info._fillColor->_shading->_endPoint.y; + CFX_DIBitmap bmp; + bmp.Create(width, height, FXDIB_Argb); + _renderDevice->GetDIBits(&bmp, 0, 0); + int32_t pitch = bmp.GetPitch(); + FX_BOOL result = FALSE; + switch (_info._fillColor->_shading->_type) { + case FX_SHADING_Axial: { + FX_FLOAT x_span = end_x - start_x; + FX_FLOAT y_span = end_y - start_y; + FX_FLOAT axis_len_square = (x_span * x_span) + (y_span * y_span); + for (int32_t row = 0; row < height; row++) { + FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch); + for (int32_t column = 0; column < width; column++) { + FX_FLOAT x = (FX_FLOAT)(column); + FX_FLOAT y = (FX_FLOAT)(row); + FX_FLOAT scale = + (((x - start_x) * x_span) + ((y - start_y) * y_span)) / + axis_len_square; + if (scale < 0) { + if (!_info._fillColor->_shading->_isExtendedBegin) { + continue; + } + scale = 0; + } else if (scale > 1.0f) { + if (!_info._fillColor->_shading->_isExtendedEnd) { + continue; + } + scale = 1.0f; + } + int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1)); + dib_buf[column] = _info._fillColor->_shading->_argbArray[index]; + } + } + result = TRUE; + break; + } + case FX_SHADING_Radial: { + FX_FLOAT start_r = _info._fillColor->_shading->_beginRadius; + FX_FLOAT end_r = _info._fillColor->_shading->_endRadius; + FX_FLOAT a = ((start_x - end_x) * (start_x - end_x)) + + ((start_y - end_y) * (start_y - end_y)) - + ((start_r - end_r) * (start_r - end_r)); + for (int32_t row = 0; row < height; row++) { + FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch); + for (int32_t column = 0; column < width; column++) { + FX_FLOAT x = (FX_FLOAT)(column); + FX_FLOAT y = (FX_FLOAT)(row); + FX_FLOAT b = -2 * (((x - start_x) * (end_x - start_x)) + + ((y - start_y) * (end_y - start_y)) + + (start_r * (end_r - start_r))); + FX_FLOAT c = ((x - start_x) * (x - start_x)) + + ((y - start_y) * (y - start_y)) - (start_r * start_r); + FX_FLOAT s; + if (a == 0) { + s = -c / b; + } else { + FX_FLOAT b2_4ac = (b * b) - 4 * (a * c); + if (b2_4ac < 0) { + continue; + } + FX_FLOAT root = (FXSYS_sqrt(b2_4ac)); + FX_FLOAT s1, s2; + if (a > 0) { + s1 = (-b - root) / (2 * a); + s2 = (-b + root) / (2 * a); + } else { + s2 = (-b - root) / (2 * a); + s1 = (-b + root) / (2 * a); + } + if (s2 <= 1.0f || _info._fillColor->_shading->_isExtendedEnd) { + s = (s2); + } else { + s = (s1); + } + if ((start_r) + s * (end_r - start_r) < 0) { + continue; + } + } + if (s < 0) { + if (!_info._fillColor->_shading->_isExtendedBegin) { + continue; + } + s = 0; + } + if (s > 1.0f) { + if (!_info._fillColor->_shading->_isExtendedEnd) { + continue; + } + s = 1.0f; + } + int index = (int32_t)(s * (FX_SHADING_Steps - 1)); + dib_buf[column] = _info._fillColor->_shading->_argbArray[index]; + } + } + result = TRUE; + break; + } + default: { result = FALSE; } + } + if (result) { + _renderDevice->SaveState(); + _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix, + fillMode); + SetDIBitsWithMatrix(&bmp, matrix); + _renderDevice->RestoreState(); + } + return result; +} +FX_ERR CFX_Graphics::SetDIBitsWithMatrix(CFX_DIBSource* source, + CFX_Matrix* matrix) { + if (matrix->IsIdentity()) { + _renderDevice->SetDIBits(source, 0, 0); + } else { + CFX_Matrix m; + m.Set((FX_FLOAT)source->GetWidth(), 0, 0, (FX_FLOAT)source->GetHeight(), 0, + 0); + m.Concat(*matrix); + int32_t left, top; + CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE); + CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m, left, top); + _renderDevice->SetDIBits(bmp2, left, top); + if (bmp2) { + delete bmp2; + bmp2 = NULL; + } + if (bmp1) { + delete bmp1; + bmp1 = NULL; + } + } + return FX_ERR_Succeeded; +} +FX_ERR CFX_Graphics::CalcTextInfo(const CFX_WideString& text, + FX_DWORD* charCodes, + FXTEXT_CHARPOS* charPos, + CFX_RectF& rect) { + std::unique_ptr<CFX_UnicodeEncoding> encoding( + new CFX_UnicodeEncoding(_info._font)); + int32_t length = text.GetLength(); + FX_FLOAT penX = (FX_FLOAT)rect.left; + FX_FLOAT penY = (FX_FLOAT)rect.top; + FX_FLOAT left = (FX_FLOAT)(0); + FX_FLOAT top = (FX_FLOAT)(0); + charCodes[0] = text.GetAt(0); + charPos[0].m_OriginX = penX + left; + charPos[0].m_OriginY = penY + top; + charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[0]); + charPos[0].m_FontCharWidth = FXSYS_round( + _info._font->GetGlyphWidth(charPos[0].m_GlyphIndex) * _info._fontHScale); + charPos[0].m_bGlyphAdjust = TRUE; + charPos[0].m_AdjustMatrix[0] = -1; + charPos[0].m_AdjustMatrix[1] = 0; + charPos[0].m_AdjustMatrix[2] = 0; + charPos[0].m_AdjustMatrix[3] = 1; + penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * _info._fontSize / 1000 + + _info._fontSpacing; + for (int32_t i = 1; i < length; i++) { + charCodes[i] = text.GetAt(i); + charPos[i].m_OriginX = penX + left; + charPos[i].m_OriginY = penY + top; + charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[i]); + charPos[i].m_FontCharWidth = + FXSYS_round(_info._font->GetGlyphWidth(charPos[i].m_GlyphIndex) * + _info._fontHScale); + charPos[i].m_bGlyphAdjust = TRUE; + charPos[i].m_AdjustMatrix[0] = -1; + charPos[i].m_AdjustMatrix[1] = 0; + charPos[i].m_AdjustMatrix[2] = 0; + charPos[i].m_AdjustMatrix[3] = 1; + penX += (FX_FLOAT)(charPos[i].m_FontCharWidth) * _info._fontSize / 1000 + + _info._fontSpacing; + } + rect.width = (FX_FLOAT)penX - rect.left; + rect.height = rect.top + _info._fontSize * _info._fontHScale - rect.top; + return FX_ERR_Succeeded; +} +CAGG_Graphics::CAGG_Graphics() { + _owner = NULL; +} +FX_ERR CAGG_Graphics::Create(CFX_Graphics* owner, + int32_t width, + int32_t height, + FXDIB_Format format) { + if (owner->_renderDevice) { + return FX_ERR_Parameter_Invalid; + } + if (_owner) { + return FX_ERR_Property_Invalid; + } + CFX_FxgeDevice* device = new CFX_FxgeDevice; + device->Create(width, height, format); + _owner = owner; + _owner->_renderDevice = device; + _owner->_renderDevice->GetBitmap()->Clear(0xFFFFFFFF); + return FX_ERR_Succeeded; +} +CAGG_Graphics::~CAGG_Graphics() { + if (_owner->_renderDevice) { + delete (CFX_FxgeDevice*)_owner->_renderDevice; + } + _owner = NULL; +} +CFX_Path::CFX_Path() { + _generator = NULL; +} +FX_ERR CFX_Path::Create() { + if (_generator) { + return FX_ERR_Property_Invalid; + } + _generator = new CFX_PathGenerator; + _generator->Create(); + return FX_ERR_Succeeded; +} +CFX_Path::~CFX_Path() { + if (_generator) { + delete _generator; + _generator = NULL; + } +} +FX_ERR CFX_Path::MoveTo(FX_FLOAT x, FX_FLOAT y) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->MoveTo(x, y); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::LineTo(FX_FLOAT x, FX_FLOAT y) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->LineTo(x, y); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::BezierTo(FX_FLOAT ctrlX1, + FX_FLOAT ctrlY1, + FX_FLOAT ctrlX2, + FX_FLOAT ctrlY2, + FX_FLOAT toX, + FX_FLOAT toY) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->BezierTo(ctrlX1, ctrlY1, ctrlX2, ctrlY2, toX, toY); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::ArcTo(FX_FLOAT left, + FX_FLOAT top, + FX_FLOAT width, + FX_FLOAT height, + FX_FLOAT startAngle, + FX_FLOAT sweepAngle) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->ArcTo(left + width / 2, top + height / 2, width / 2, height / 2, + startAngle, sweepAngle); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::Close() { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->Close(); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddLine(x1, y1, x2, y2); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddBezier(FX_FLOAT startX, + FX_FLOAT startY, + FX_FLOAT ctrlX1, + FX_FLOAT ctrlY1, + FX_FLOAT ctrlX2, + FX_FLOAT ctrlY2, + FX_FLOAT endX, + FX_FLOAT endY) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddBezier(startX, startY, ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, + endY); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddRectangle(FX_FLOAT left, + FX_FLOAT top, + FX_FLOAT width, + FX_FLOAT height) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddRectangle(left, top, left + width, top + height); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddEllipse(FX_FLOAT left, + FX_FLOAT top, + FX_FLOAT width, + FX_FLOAT height) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddEllipse(left + width / 2, top + height / 2, width / 2, + height / 2); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddEllipse(const CFX_RectF& rect) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddEllipse(rect.left + rect.Width() / 2, + rect.top + rect.Height() / 2, rect.Width() / 2, + rect.Height() / 2); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddArc(FX_FLOAT left, + FX_FLOAT top, + FX_FLOAT width, + FX_FLOAT height, + FX_FLOAT startAngle, + FX_FLOAT sweepAngle) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddArc(left + width / 2, top + height / 2, width / 2, height / 2, + startAngle, sweepAngle); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddPie(FX_FLOAT left, + FX_FLOAT top, + FX_FLOAT width, + FX_FLOAT height, + FX_FLOAT startAngle, + FX_FLOAT sweepAngle) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddPie(left + width / 2, top + height / 2, width / 2, height / 2, + startAngle, sweepAngle); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::AddSubpath(CFX_Path* path) { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->AddPathData(path->GetPathData()); + return FX_ERR_Succeeded; +} +FX_ERR CFX_Path::Clear() { + if (!_generator) + return FX_ERR_Property_Invalid; + _generator->GetPathData()->SetPointCount(0); + return FX_ERR_Succeeded; +} +FX_BOOL CFX_Path::IsEmpty() { + if (!_generator) + return FX_ERR_Property_Invalid; + if (_generator->GetPathData()->GetPointCount() == 0) { + return TRUE; + } + return FALSE; +} +CFX_PathData* CFX_Path::GetPathData() { + if (!_generator) + return NULL; + return _generator->GetPathData(); +} +CFX_Color::CFX_Color() { + _type = FX_COLOR_None; +} +CFX_Color::CFX_Color(const FX_ARGB argb) { + _type = FX_COLOR_None; + Set(argb); +} +CFX_Color::CFX_Color(CFX_Pattern* pattern, const FX_ARGB argb) { + _type = FX_COLOR_None; + Set(pattern, argb); +} +CFX_Color::CFX_Color(CFX_Shading* shading) { + _type = FX_COLOR_None; + Set(shading); +} +CFX_Color::~CFX_Color() { + _type = FX_COLOR_None; +} +FX_ERR CFX_Color::Set(const FX_ARGB argb) { + _type = FX_COLOR_Solid; + _argb = argb; + _pattern = NULL; + return FX_ERR_Succeeded; +} +FX_ERR CFX_Color::Set(CFX_Pattern* pattern, const FX_ARGB argb) { + if (!pattern) + return FX_ERR_Parameter_Invalid; + _type = FX_COLOR_Pattern; + _argb = argb; + _pattern = pattern; + return FX_ERR_Succeeded; +} +FX_ERR CFX_Color::Set(CFX_Shading* shading) { + if (!shading) + return FX_ERR_Parameter_Invalid; + _type = FX_COLOR_Shading; + _shading = shading; + return FX_ERR_Succeeded; +} +CFX_Pattern::CFX_Pattern() { + _type = FX_PATTERN_None; + _matrix.SetIdentity(); +} +FX_ERR CFX_Pattern::Create(CFX_DIBitmap* bitmap, + const FX_FLOAT xStep, + const FX_FLOAT yStep, + CFX_Matrix* matrix) { + if (!bitmap) + return FX_ERR_Parameter_Invalid; + if (_type != FX_PATTERN_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_PATTERN_Bitmap; + _bitmap = bitmap; + _x1Step = xStep; + _y1Step = yStep; + if (matrix) { + _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, + matrix->f); + } + return FX_ERR_Succeeded; +} +FX_ERR CFX_Pattern::Create(FX_HatchStyle hatchStyle, + const FX_ARGB foreArgb, + const FX_ARGB backArgb, + CFX_Matrix* matrix) { + if (hatchStyle < FX_HATCHSTYLE_Horizontal || + hatchStyle > FX_HATCHSTYLE_SolidDiamond) { + return FX_ERR_Parameter_Invalid; + } + if (_type != FX_PATTERN_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_PATTERN_Hatch; + _hatchStyle = hatchStyle; + _foreArgb = foreArgb; + _backArgb = backArgb; + if (matrix) { + _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, + matrix->f); + } + return FX_ERR_Succeeded; +} +CFX_Pattern::~CFX_Pattern() { + _type = FX_PATTERN_None; +} +CFX_Shading::CFX_Shading() { + _type = FX_SHADING_None; +} +FX_ERR CFX_Shading::CreateAxial(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + FX_BOOL isExtendedBegin, + FX_BOOL isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb) { + if (_type != FX_SHADING_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_SHADING_Axial; + _beginPoint = beginPoint; + _endPoint = endPoint; + _isExtendedBegin = isExtendedBegin; + _isExtendedEnd = isExtendedEnd; + _beginArgb = beginArgb; + _endArgb = endArgb; + return InitArgbArray(); +} +FX_ERR CFX_Shading::CreateRadial(const CFX_PointF& beginPoint, + const CFX_PointF& endPoint, + const FX_FLOAT beginRadius, + const FX_FLOAT endRadius, + FX_BOOL isExtendedBegin, + FX_BOOL isExtendedEnd, + const FX_ARGB beginArgb, + const FX_ARGB endArgb) { + if (_type != FX_SHADING_None) { + return FX_ERR_Property_Invalid; + } + _type = FX_SHADING_Radial; + _beginPoint = beginPoint; + _endPoint = endPoint; + _beginRadius = beginRadius; + _endRadius = endRadius; + _isExtendedBegin = isExtendedBegin; + _isExtendedEnd = isExtendedEnd; + _beginArgb = beginArgb; + _endArgb = endArgb; + return InitArgbArray(); +} +CFX_Shading::~CFX_Shading() { + _type = FX_SHADING_None; +} +FX_ERR CFX_Shading::InitArgbArray() { + int32_t a1, r1, g1, b1; + ArgbDecode(_beginArgb, a1, r1, g1, b1); + int32_t a2, r2, g2, b2; + ArgbDecode(_endArgb, a2, r2, g2, b2); + FX_FLOAT f = (FX_FLOAT)(FX_SHADING_Steps - 1); + FX_FLOAT aScale = (FX_FLOAT)(1.0 * (a2 - a1) / f); + FX_FLOAT rScale = (FX_FLOAT)(1.0 * (r2 - r1) / f); + FX_FLOAT gScale = (FX_FLOAT)(1.0 * (g2 - g1) / f); + FX_FLOAT bScale = (FX_FLOAT)(1.0 * (b2 - b1) / f); + int32_t a3, r3, g3, b3; + for (int32_t i = 0; i < FX_SHADING_Steps; i++) { + a3 = (int32_t)(i * aScale); + r3 = (int32_t)(i * rScale); + g3 = (int32_t)(i * gScale); + b3 = (int32_t)(i * bScale); + _argbArray[i] = + FXARGB_TODIB(FXARGB_MAKE((a1 + a3), (r1 + r3), (g1 + g3), (b1 + b3))); + } + return FX_ERR_Succeeded; +} +class CFX_Pause : public IFX_Pause { + public: + virtual FX_BOOL NeedToPauseNow() { return TRUE; } +}; |