| // 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 "pre.h" | |
| #include "fx_path_generator.h" | |
| class CAGG_Graphics : public CFX_Object | |
| { | |
| public: | |
| CAGG_Graphics(); | |
| FX_ERR Create(CFX_Graphics * owner, | |
| FX_INT32 width, | |
| FX_INT32 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.Reset(); | |
| _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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(renderDevice, 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(FX_INT32 width, | |
| FX_INT32 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 = FX_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 FX_INT32 capID, FX_DeviceCap & capVal) | |
| { | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| FX_INT32 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| _renderDevice->SaveState(); | |
| TInfo * info = FX_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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| _renderDevice->RestoreState(); | |
| FX_INT32 size = _infoStack.GetSize(); | |
| if (size <= 0) { | |
| return FX_ERR_Intermediate_Value_Invalid; | |
| } | |
| FX_INT32 topIndex = size - 1; | |
| TInfo * info = (TInfo *) _infoStack.GetAt(topIndex); | |
| _FX_RETURN_VALUE_IF_FAIL(info, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| _info._graphState.m_LineCap = lineCap; | |
| return FX_ERR_Succeeded; | |
| } | |
| default: { | |
| return FX_ERR_Property_Invalid; | |
| } | |
| } | |
| } | |
| FX_ERR CFX_Graphics::GetDashCount(FX_INT32 & dashCount) | |
| { | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(dashArray, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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, | |
| FX_INT32 dashCount) | |
| { | |
| if (dashCount > 0 && !dashArray) { | |
| return FX_ERR_Parameter_Invalid; | |
| } | |
| dashCount = dashCount < 0 ? 0 : dashCount; | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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 (FX_INT32 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| FX_BOOL result = _renderDevice->SetClip_PathFill(path->GetPathData(), | |
| (CFX_AffineMatrix *) matrix, | |
| fillMode); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| return RenderDeviceStretchImage(source, rect, matrix); | |
| } | |
| default: { | |
| return FX_ERR_Property_Invalid; | |
| } | |
| } | |
| } | |
| FX_ERR CFX_Graphics::ConcatMatrix(CFX_Matrix * matrix) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(matrix, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, NULL); | |
| return &_info._CTM; | |
| } | |
| default: { | |
| return NULL; | |
| } | |
| } | |
| } | |
| FX_ERR CFX_Graphics::GetClipRect(CFX_RectF & rect) | |
| { | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| FX_RECT r(FXSYS_round(rect.left), | |
| FXSYS_round(rect.top), | |
| FXSYS_round(rect.right()), | |
| FXSYS_round(rect.bottom())); | |
| FX_BOOL result = _renderDevice->SetClip_Rect(&r); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| FX_BOOL result = FX_ERR_Succeeded; | |
| _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); | |
| return FX_ERR_Succeeded; | |
| } | |
| default: { | |
| return FX_ERR_Property_Invalid; | |
| } | |
| } | |
| } | |
| FX_ERR CFX_Graphics::SetFont(CFX_Font * font) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(font, FX_ERR_Parameter_Invalid); | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| _info._fontSpacing = fontSpacing; | |
| return FX_ERR_Succeeded; | |
| } | |
| default: { | |
| return FX_ERR_Property_Invalid; | |
| } | |
| } | |
| } | |
| FX_ERR CFX_Graphics::SetTextDrawingMode(const FX_INT32 mode) | |
| { | |
| switch (_type) { | |
| case FX_CONTEXT_Device: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| FX_INT32 length = text.GetLength(); | |
| FX_DWORD * charCodes = FX_Alloc(FX_DWORD, length); | |
| FXTEXT_CHARPOS * charPos = FX_Alloc(FXTEXT_CHARPOS, | |
| length * sizeof (FXTEXT_CHARPOS)); | |
| 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, CFX_Matrix * matrix ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(graphics, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice, | |
| FX_ERR_Parameter_Invalid); | |
| CFX_DIBitmap * bitmap = graphics->_renderDevice->GetBitmap(); | |
| FX_BOOL result = _renderDevice->SetDIBits(bitmap, 0, 0); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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, | |
| CFX_Matrix * matrix ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(graphics, 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: { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice, | |
| FX_ERR_Parameter_Invalid); | |
| CFX_DIBitmap * bitmap = graphics->_renderDevice->GetBitmap(); | |
| FX_BOOL result = FX_ERR_Indefinite; | |
| CFX_DIBitmap bmp; | |
| result = bmp.Create((FX_INT32) dstRect.width, | |
| (FX_INT32) dstRect.height, | |
| bitmap->GetFormat()); | |
| _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Intermediate_Value_Invalid); | |
| result = graphics->_renderDevice->GetDIBits(&bmp, | |
| (FX_INT32) srcLeft, | |
| (FX_INT32) srcTop); | |
| _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); | |
| result = _renderDevice->SetDIBits(&bmp, | |
| (FX_INT32) dstRect.left, | |
| (FX_INT32) dstRect.top); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| CFX_DIBitmap * bitmap = _renderDevice->GetBitmap(); | |
| _FX_RETURN_VALUE_IF_FAIL(bitmap, 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() + FX_INT32(r.top) * bitmap->GetPitch()); | |
| FX_INT32 bottom = (FX_INT32)r.bottom(); | |
| FX_INT32 right = (FX_INT32)r.right(); | |
| for (FX_INT32 i = (FX_INT32)r.top; i < bottom; i ++) { | |
| FX_ARGB* pLine = pBuf + (FX_INT32)r.left; | |
| for (FX_INT32 j = (FX_INT32)r.left; j < right; j ++) { | |
| FX_ARGB c = *pLine; | |
| *pLine ++ = (c & 0xFF000000) | (0xFFFFFF - (c & 0x00FFFFFF)); | |
| } | |
| pBuf = (FX_ARGB*)((FX_LPBYTE)pBuf + bitmap->GetPitch()); | |
| } | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_ERR CFX_Graphics::XorDIBitmap(const CFX_DIBitmap * srcBitmap, const CFX_RectF & rect) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| CFX_DIBitmap * dst = _renderDevice->GetBitmap(); | |
| _FX_RETURN_VALUE_IF_FAIL(dst, 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() + FX_INT32(r.top) * srcBitmap->GetPitch()); | |
| FX_ARGB* pDstBuf = (FX_ARGB*)(dst->GetBuffer() + FX_INT32(r.top) * dst->GetPitch()); | |
| FX_INT32 bottom = (FX_INT32)r.bottom(); | |
| FX_INT32 right = (FX_INT32)r.right(); | |
| for (FX_INT32 i = (FX_INT32)r.top; i < bottom; i ++) { | |
| FX_ARGB* pSrcLine = pSrcBuf + (FX_INT32)r.left; | |
| FX_ARGB* pDstLine = pDstBuf + (FX_INT32)r.left; | |
| for (FX_INT32 j = (FX_INT32)r.left; j < right; j ++) { | |
| FX_ARGB c = *pDstLine; | |
| *pDstLine ++ = ArgbEncode(FXARGB_A(c), (c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF)); | |
| pSrcLine ++; | |
| } | |
| pSrcBuf = (FX_ARGB*)((FX_LPBYTE)pSrcBuf + srcBitmap->GetPitch()); | |
| pDstBuf = (FX_ARGB*)((FX_LPBYTE)pDstBuf + dst->GetPitch()); | |
| } | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_ERR CFX_Graphics::EqvDIBitmap(const CFX_DIBitmap * srcBitmap, const CFX_RectF & rect) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); | |
| CFX_DIBitmap * dst = _renderDevice->GetBitmap(); | |
| _FX_RETURN_VALUE_IF_FAIL(dst, 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() + FX_INT32(r.top) * srcBitmap->GetPitch()); | |
| FX_ARGB* pDstBuf = (FX_ARGB*)(dst->GetBuffer() + FX_INT32(r.top) * dst->GetPitch()); | |
| FX_INT32 bottom = (FX_INT32)r.bottom(); | |
| FX_INT32 right = (FX_INT32)r.right(); | |
| for (FX_INT32 i = (FX_INT32)r.top; i < bottom; i ++) { | |
| FX_ARGB* pSrcLine = pSrcBuf + (FX_INT32)r.left; | |
| FX_ARGB* pDstLine = pDstBuf + (FX_INT32)r.left; | |
| for (FX_INT32 j = (FX_INT32)r.left; j < right; j ++) { | |
| FX_ARGB c = *pDstLine; | |
| *pDstLine ++ = ArgbEncode(FXARGB_A(c), ~((c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF))); | |
| pSrcLine ++; | |
| } | |
| pSrcBuf = (FX_ARGB*)((FX_LPBYTE)pSrcBuf + srcBitmap->GetPitch()); | |
| pDstBuf = (FX_ARGB*)((FX_LPBYTE)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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_info._strokeColor, 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_AffineMatrix *) &m, | |
| &_info._graphState, | |
| 0x0, | |
| _info._strokeColor->_argb, | |
| 0); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_info._fillColor, 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_AffineMatrix *) &m, | |
| &_info._graphState, | |
| _info._fillColor->_argb, | |
| 0x0, | |
| fillMode); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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); | |
| FX_INT32 left, top; | |
| CFX_DIBitmap * bmp1 = source->FlipImage(FALSE, TRUE); | |
| CFX_DIBitmap * bmp2 = bmp1->TransformTo((CFX_AffineMatrix *) &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((FX_INT32) rect.Width(), | |
| (FX_INT32) rect.Height()); | |
| CFX_Matrix m2; | |
| m2.Set(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top); | |
| m2.Concat(m1); | |
| FX_INT32 left, top; | |
| CFX_DIBitmap * bmp2 = bmp1->FlipImage(FALSE, TRUE); | |
| CFX_DIBitmap * bmp3 = bmp2->TransformTo((CFX_AffineMatrix *) &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) | |
| { | |
| FX_INT32 length = text.GetLength(); | |
| FX_DWORD * charCodes = FX_Alloc(FX_DWORD, length); | |
| FXTEXT_CHARPOS * charPos = FX_Alloc(FXTEXT_CHARPOS, | |
| length * sizeof (FXTEXT_CHARPOS)); | |
| 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_AffineMatrix *) &m, | |
| _info._fillColor->_argb, | |
| FXTEXT_CLEARTYPE); | |
| _FX_RETURN_VALUE_IF_FAIL(result, 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(); | |
| FX_INT32 width = bitmap->GetWidth(); | |
| FX_INT32 height = bitmap->GetHeight(); | |
| CFX_DIBitmap bmp; | |
| bmp.Create(width, height, FXDIB_Argb); | |
| _renderDevice->GetDIBits(&bmp, 0, 0); | |
| switch (pattern->_type) { | |
| case FX_PATTERN_Bitmap: { | |
| FX_INT32 xStep = FXSYS_round(pattern->_x1Step); | |
| FX_INT32 yStep = FXSYS_round(pattern->_y1Step); | |
| FX_INT32 xCount = width / xStep + 1; | |
| FX_INT32 yCount = height / yStep + 1; | |
| for (FX_INT32 i = 0; i <= yCount; i++) { | |
| for (FX_INT32 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_AffineMatrix *) 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 (FX_INT32 j = rect.bottom; j < rect.top; j += mask.GetHeight()) { | |
| for (FX_INT32 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_AffineMatrix *) 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(); | |
| FX_INT32 width = bitmap->GetWidth(); | |
| FX_INT32 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); | |
| FX_INT32 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 = FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span); | |
| for (FX_INT32 row = 0; row < height; row++) { | |
| FX_DWORD * dib_buf = (FX_DWORD *) (bmp.GetBuffer() + row * pitch); | |
| for (FX_INT32 column = 0; column < width; column++) { | |
| FX_FLOAT x = (FX_FLOAT)(column); | |
| FX_FLOAT y = (FX_FLOAT)(row); | |
| FX_FLOAT scale = FXSYS_Div(FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(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; | |
| } | |
| FX_INT32 index = (FX_INT32)(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 = FXSYS_Mul(start_x - end_x, start_x - end_x) + FXSYS_Mul(start_y - end_y, start_y - end_y) - FXSYS_Mul(start_r - end_r, start_r - end_r); | |
| for (FX_INT32 row = 0; row < height; row++) { | |
| FX_DWORD * dib_buf = (FX_DWORD *) (bmp.GetBuffer() + row * pitch); | |
| for (FX_INT32 column = 0; column < width; column++) { | |
| FX_FLOAT x = (FX_FLOAT)(column); | |
| FX_FLOAT y = (FX_FLOAT)(row); | |
| FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + FXSYS_Mul(y - start_y, end_y - start_y) + | |
| FXSYS_Mul(start_r, end_r - start_r)); | |
| FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + FXSYS_Mul(y - start_y, y - start_y) - | |
| FXSYS_Mul(start_r, start_r); | |
| FX_FLOAT s; | |
| if (a == 0) { | |
| s = (FXSYS_Div(-c, b)); | |
| } else { | |
| FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); | |
| if (b2_4ac < 0) { | |
| continue; | |
| } | |
| FX_FLOAT root = (FXSYS_sqrt(b2_4ac)); | |
| FX_FLOAT s1, s2; | |
| if (a > 0) { | |
| s1 = FXSYS_Div(-b - root, 2 * a); | |
| s2 = FXSYS_Div(-b + root, 2 * a); | |
| } else { | |
| s2 = FXSYS_Div(-b - root, 2 * a); | |
| s1 = FXSYS_Div(-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 = (FX_INT32)(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_AffineMatrix *) 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); | |
| FX_INT32 left, top; | |
| CFX_DIBitmap * bmp1 = source->FlipImage(FALSE, TRUE); | |
| CFX_DIBitmap * bmp2 = bmp1->TransformTo((CFX_AffineMatrix *) &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) | |
| { | |
| IFX_FontEncoding * encoding = FXGE_CreateUnicodeEncoding(_info._font); | |
| FX_INT32 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 (FX_INT32 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; | |
| delete encoding; | |
| encoding = NULL; | |
| return FX_ERR_Succeeded; | |
| } | |
| CAGG_Graphics::CAGG_Graphics() | |
| { | |
| _owner = NULL; | |
| } | |
| FX_ERR CAGG_Graphics::Create(CFX_Graphics * owner, | |
| FX_INT32 width, | |
| FX_INT32 height, | |
| FXDIB_Format format) | |
| { | |
| if (owner->_renderDevice) { | |
| return FX_ERR_Parameter_Invalid; | |
| } | |
| if (_owner) { | |
| return FX_ERR_Property_Invalid; | |
| } | |
| CFX_FxgeDevice * device = FX_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 = FX_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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); | |
| _generator->MoveTo(x, y); | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_ERR CFX_Path::LineTo(FX_FLOAT x, FX_FLOAT y) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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() | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); | |
| _generator->AddPathData(path->GetPathData()); | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_ERR CFX_Path::Clear() | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); | |
| _generator->GetPathData()->SetPointCount(0); | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_BOOL CFX_Path::IsEmpty() | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); | |
| if (_generator->GetPathData()->GetPointCount() == 0) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| CFX_PathData * CFX_Path::GetPathData() | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(_generator, 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 ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(pattern, FX_ERR_Parameter_Invalid); | |
| _type = FX_COLOR_Pattern; | |
| _argb = argb; | |
| _pattern = pattern; | |
| return FX_ERR_Succeeded; | |
| } | |
| FX_ERR CFX_Color::Set(CFX_Shading * shading) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(shading, FX_ERR_Parameter_Invalid); | |
| _type = FX_COLOR_Shading; | |
| _shading = shading; | |
| return FX_ERR_Succeeded; | |
| } | |
| CFX_Pattern::CFX_Pattern() | |
| { | |
| _type = FX_PATTERN_None; | |
| _matrix.Reset(); | |
| } | |
| FX_ERR CFX_Pattern::Create(CFX_DIBitmap * bitmap, | |
| const FX_FLOAT xStep, | |
| const FX_FLOAT yStep, | |
| CFX_Matrix * matrix ) | |
| { | |
| _FX_RETURN_VALUE_IF_FAIL(bitmap, 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() | |
| { | |
| FX_INT32 a1, r1, g1, b1; | |
| ArgbDecode(_beginArgb, a1, r1, g1, b1); | |
| FX_INT32 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); | |
| FX_INT32 a3, r3, g3, b3; | |
| for (FX_INT32 i = 0; i < FX_SHADING_Steps; i++) { | |
| a3 = (FX_INT32) (i * aScale); | |
| r3 = (FX_INT32) (i * rScale); | |
| g3 = (FX_INT32) (i * gScale); | |
| b3 = (FX_INT32) (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; | |
| } | |
| }; |