summaryrefslogtreecommitdiff
path: root/xfa/src/fxgraphics
diff options
context:
space:
mode:
authorBo Xu <bo_xu@foxitsoftware.com>2014-10-28 23:03:33 -0700
committerBo Xu <bo_xu@foxitsoftware.com>2014-11-03 11:10:11 -0800
commitfdc00a7042d912aafaabddae4d9c84199921ef23 (patch)
tree32ab8ac91cc68d2cd15b9168782a71b3f3f5e7b9 /xfa/src/fxgraphics
parente9b38fa38de2c95d8260be31c57d9272c4d127ed (diff)
downloadpdfium-fdc00a7042d912aafaabddae4d9c84199921ef23.tar.xz
Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
Diffstat (limited to 'xfa/src/fxgraphics')
-rw-r--r--xfa/src/fxgraphics/src/fx_graphics.cpp1670
-rw-r--r--xfa/src/fxgraphics/src/fx_metafile_interpreter.cpp281
-rw-r--r--xfa/src/fxgraphics/src/fx_metafile_interpreter.h54
-rw-r--r--xfa/src/fxgraphics/src/fx_path_generator.cpp222
-rw-r--r--xfa/src/fxgraphics/src/fx_path_generator.h42
-rw-r--r--xfa/src/fxgraphics/src/pre.h115
6 files changed, 2384 insertions, 0 deletions
diff --git a/xfa/src/fxgraphics/src/fx_graphics.cpp b/xfa/src/fxgraphics/src/fx_graphics.cpp
new file mode 100644
index 0000000000..340d46dfa9
--- /dev/null
+++ b/xfa/src/fxgraphics/src/fx_graphics.cpp
@@ -0,0 +1,1670 @@
+// 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;
+ }
+};
diff --git a/xfa/src/fxgraphics/src/fx_metafile_interpreter.cpp b/xfa/src/fxgraphics/src/fx_metafile_interpreter.cpp
new file mode 100644
index 0000000000..388fbc5ad5
--- /dev/null
+++ b/xfa/src/fxgraphics/src/fx_metafile_interpreter.cpp
@@ -0,0 +1,281 @@
+// 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 "../include/fx_graphics.h"
+#include "fx_metafile_interpreter.h"
+CFX_MetafileInterpreter::CFX_MetafileInterpreter()
+{
+ _element = NULL;
+}
+CFX_MetafileInterpreter::~CFX_MetafileInterpreter()
+{
+ _element = NULL;
+}
+FX_BOOL CFX_MetafileInterpreter::SetCurrentElement(CXML_Element * element)
+{
+ _FX_RETURN_VALUE_IF_FAIL(element, FALSE);
+ _element = element;
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetLineCap(FX_INT32 & lineCap)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * lineCapElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(lineCapElement, FALSE);
+ lineCap = lineCapElement->GetAttrInteger("CFX_GraphStateData::LineCap");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetLineDash(FX_FLOAT & dashPhase,
+ FX_INT32 & dashArray,
+ FX_INT32 & dashCount)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * dashPhaseElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(dashPhaseElement, FALSE);
+ dashPhase = dashPhaseElement->GetAttrFloat("FX_FLOAT");
+ CXML_Element * dashArrayElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(dashArrayElement, FALSE);
+ dashArray = dashArrayElement->GetAttrInteger("FX_FLOAT *");
+ CXML_Element * dashCountElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(dashCountElement, FALSE);
+ dashCount = dashCountElement->GetAttrInteger("FX_INT32");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetLineDash(FX_INT32 & dashStyle)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * dashStyleElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(dashStyleElement, FALSE);
+ dashStyle = dashStyleElement->GetAttrInteger("FX_DashStyle");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetLineJoin(FX_INT32 & lineJoin)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * lineJoinElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(lineJoinElement, FALSE);
+ lineJoin = lineJoinElement->GetAttrInteger("CFX_GraphStateData::LineJoin");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetMiterLimit(FX_FLOAT & miterLimit)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * miterLimitElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(miterLimitElement, FALSE);
+ miterLimit = miterLimitElement->GetAttrFloat("FX_FLOAT");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetLineWidth(FX_FLOAT & lineWidth,
+ FX_INT32 & isActOnDash)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * lineWidthElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(lineWidthElement, FALSE);
+ lineWidth = lineWidthElement->GetAttrFloat("FX_FLOAT");
+ CXML_Element * isActOnDashElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(isActOnDashElement, FALSE);
+ isActOnDash = isActOnDashElement->GetAttrInteger("FX_BOOL");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetStrokeColor(FX_INT32 & color)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * colorElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(colorElement, FALSE);
+ color = colorElement->GetAttrInteger("CFX_Color *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetFillColor(FX_INT32 & color)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * colorElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(colorElement, FALSE);
+ color = colorElement->GetAttrInteger("CFX_Color *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_StrokePath(FX_INT32 & path, FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * pathElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(pathElement, FALSE);
+ path = pathElement->GetAttrInteger("CFX_Path *");
+ CXML_Element * matrixElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_FillPath(FX_INT32 & path,
+ FX_INT32 & fillMode,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * pathElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(pathElement, FALSE);
+ path = pathElement->GetAttrInteger("CFX_Path *");
+ CXML_Element * fillModeElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(fillModeElement, FALSE);
+ fillMode = fillModeElement->GetAttrInteger("FX_FillMode");
+ CXML_Element * matrixElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_ClipPath(FX_INT32 & path,
+ FX_INT32 & fillMode,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * pathElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(pathElement, FALSE);
+ path = pathElement->GetAttrInteger("CFX_Path *");
+ CXML_Element * fillModeElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(fillModeElement, FALSE);
+ fillMode = fillModeElement->GetAttrInteger("FX_FillMode");
+ CXML_Element * matrixElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_DrawImage(FX_INT32 & source,
+ FX_INT32 & point,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * sourceElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(sourceElement, FALSE);
+ source = sourceElement->GetAttrInteger("CFX_DIBSource *");
+ CXML_Element * pointElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(pointElement, FALSE);
+ point = pointElement->GetAttrInteger("CFX_PointF *");
+ CXML_Element * matrixElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_StretchImage(FX_INT32 & source,
+ FX_INT32 & rect,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * sourceElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(sourceElement, FALSE);
+ source = sourceElement->GetAttrInteger("CFX_DIBSource *");
+ CXML_Element * rectElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(rectElement, FALSE);
+ rect = rectElement->GetAttrInteger("CFX_RectF *");
+ CXML_Element * matrixElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_ConcatMatrix(FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * matrixElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetClipRect(FX_INT32 & rect)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * rectElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(rectElement, FALSE);
+ rect = rectElement->GetAttrInteger("CFX_RectF *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetFont(FX_INT32 & font)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * fontElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(fontElement, FALSE);
+ font = fontElement->GetAttrInteger("CFX_Font *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetFontSize(FX_FLOAT & size)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * sizeElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(sizeElement, FALSE);
+ size = sizeElement->GetAttrFloat("FX_FLOAT");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetFontHScale(FX_FLOAT & scale)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * scaleElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(scaleElement, FALSE);
+ scale = scaleElement->GetAttrFloat("FX_FLOAT");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetCharSpacing(FX_FLOAT & spacing)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * spacingElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(spacingElement, FALSE);
+ spacing = spacingElement->GetAttrFloat("FX_FLOAT");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetTextDrawingMode(FX_INT32 & mode)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * modeElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(modeElement, FALSE);
+ mode = modeElement->GetAttrInteger("FX_INT32");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_SetText(FX_INT32 & point,
+ FX_INT32 & text,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * pointElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(pointElement, FALSE);
+ point = pointElement->GetAttrInteger("CFX_PointF *");
+ CXML_Element * textElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(textElement, FALSE);
+ text = textElement->GetAttrInteger("CFX_WideString *");
+ CXML_Element * matrixElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_Transfer(FX_INT32 & graphics, FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * graphicsElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(graphicsElement, FALSE);
+ graphics = graphicsElement->GetAttrInteger("CFX_Graphics *");
+ CXML_Element * matrixElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
+FX_BOOL CFX_MetafileInterpreter::ParamOf_Transfer(FX_INT32 & graphics,
+ FX_FLOAT & srcLeft,
+ FX_FLOAT & srcTop,
+ FX_INT32 & dstRect,
+ FX_INT32 & matrix)
+{
+ _FX_RETURN_VALUE_IF_FAIL(_element, FALSE);
+ CXML_Element * graphicsElement = _element->GetElement(0);
+ _FX_RETURN_VALUE_IF_FAIL(graphicsElement, FALSE);
+ graphics = graphicsElement->GetAttrInteger("CFX_Graphics *");
+ CXML_Element * srcLeftElement = _element->GetElement(2);
+ _FX_RETURN_VALUE_IF_FAIL(srcLeftElement, FALSE);
+ srcLeft = srcLeftElement->GetAttrFloat("FX_FLOAT");
+ CXML_Element * srcTopElement = _element->GetElement(3);
+ _FX_RETURN_VALUE_IF_FAIL(srcTopElement, FALSE);
+ srcTop = srcTopElement->GetAttrFloat("FX_FLOAT");
+ CXML_Element * dstRectElement = _element->GetElement(1);
+ _FX_RETURN_VALUE_IF_FAIL(dstRectElement, FALSE);
+ dstRect = dstRectElement->GetAttrInteger("CFX_RectF *");
+ CXML_Element * matrixElement = _element->GetElement(4);
+ _FX_RETURN_VALUE_IF_FAIL(matrixElement, FALSE);
+ matrix = matrixElement->GetAttrInteger("CFX_Matrix *");
+ return TRUE;
+}
diff --git a/xfa/src/fxgraphics/src/fx_metafile_interpreter.h b/xfa/src/fxgraphics/src/fx_metafile_interpreter.h
new file mode 100644
index 0000000000..6d827b6f30
--- /dev/null
+++ b/xfa/src/fxgraphics/src/fx_metafile_interpreter.h
@@ -0,0 +1,54 @@
+// 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
+
+#ifndef __H_FX_METAFILE_INTERPRETER__
+#define __H_FX_METAFILE_INTERPRETER__
+class CFX_MetafileInterpreter : public CFX_Object
+{
+public:
+ CFX_MetafileInterpreter();
+ virtual ~CFX_MetafileInterpreter();
+
+ FX_BOOL SetCurrentElement(CXML_Element * element);
+
+ FX_BOOL ParamOf_SetLineCap(FX_INT32 & lineCap);
+ FX_BOOL ParamOf_SetLineDash(FX_FLOAT & dashPhase,
+ FX_INT32 & dashArray,
+ FX_INT32 & dashCount);
+ FX_BOOL ParamOf_SetLineDash(FX_INT32 & dashStyle);
+ FX_BOOL ParamOf_SetLineJoin(FX_INT32 & lineJoin);
+ FX_BOOL ParamOf_SetMiterLimit(FX_FLOAT & miterLimit);
+ FX_BOOL ParamOf_SetLineWidth(FX_FLOAT & lineWidth, FX_INT32 & isActOnDash);
+
+ FX_BOOL ParamOf_SetStrokeColor(FX_INT32 & color);
+ FX_BOOL ParamOf_SetFillColor(FX_INT32 & color);
+
+ FX_BOOL ParamOf_StrokePath(FX_INT32 & path, FX_INT32 & matrix);
+ FX_BOOL ParamOf_FillPath(FX_INT32 & path, FX_INT32 & fillMode, FX_INT32 & matrix);
+ FX_BOOL ParamOf_ClipPath(FX_INT32 & path, FX_INT32 & fillMode, FX_INT32 & matrix);
+
+ FX_BOOL ParamOf_DrawImage(FX_INT32 & source, FX_INT32 & point, FX_INT32 & matrix);
+ FX_BOOL ParamOf_StretchImage(FX_INT32 & source, FX_INT32 & rect, FX_INT32 & matrix);
+
+ FX_BOOL ParamOf_ConcatMatrix(FX_INT32 & matrix);
+ FX_BOOL ParamOf_SetClipRect(FX_INT32 & rect);
+ FX_BOOL ParamOf_SetFont(FX_INT32 & font);
+ FX_BOOL ParamOf_SetFontSize(FX_FLOAT & size);
+ FX_BOOL ParamOf_SetFontHScale(FX_FLOAT & scale);
+ FX_BOOL ParamOf_SetCharSpacing(FX_FLOAT & spacing);
+ FX_BOOL ParamOf_SetTextDrawingMode(FX_INT32 & mode);
+ FX_BOOL ParamOf_SetText(FX_INT32 & point, FX_INT32 & text, FX_INT32 & matrix);
+ FX_BOOL ParamOf_Transfer(FX_INT32 & graphics, FX_INT32 & matrix);
+ FX_BOOL ParamOf_Transfer(FX_INT32 & graphics,
+ FX_FLOAT & srcLeft,
+ FX_FLOAT & srcTop,
+ FX_INT32 & dstRect,
+ FX_INT32 & matrix);
+
+private:
+ CXML_Element * _element;
+};
+#endif
diff --git a/xfa/src/fxgraphics/src/fx_path_generator.cpp b/xfa/src/fxgraphics/src/fx_path_generator.cpp
new file mode 100644
index 0000000000..da9d3df063
--- /dev/null
+++ b/xfa/src/fxgraphics/src/fx_path_generator.cpp
@@ -0,0 +1,222 @@
+// 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"
+CFX_PathGenerator::CFX_PathGenerator()
+{
+ m_pPathData = NULL;
+}
+void CFX_PathGenerator::Create()
+{
+ m_pPathData = FX_NEW CFX_PathData;
+}
+CFX_PathGenerator::~CFX_PathGenerator()
+{
+ if ( m_pPathData) {
+ delete m_pPathData;
+ m_pPathData = NULL;
+ }
+}
+void CFX_PathGenerator::AddPathData(CFX_PathData *pPathData)
+{
+ if (pPathData && pPathData->GetPointCount() > 0) {
+ int nCount = pPathData->GetPointCount();
+ FX_PATHPOINT *pPoints = pPathData->GetPoints();
+ AddPathData(pPoints, nCount);
+ }
+}
+void CFX_PathGenerator::AddPathData(FX_PATHPOINT *pPoints, int nCount)
+{
+ if (pPoints && nCount > 0) {
+ int nOldCount = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(nCount);
+ FX_PATHPOINT *pDstPoints = m_pPathData->GetPoints();
+ FXSYS_memcpy(pDstPoints + nOldCount, pPoints, sizeof(FX_PATHPOINT) * nCount);
+ }
+}
+void CFX_PathGenerator::MoveTo(FX_FLOAT x, FX_FLOAT y)
+{
+ m_pPathData->AddPointCount(1);
+ m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_MOVETO);
+}
+void CFX_PathGenerator::LineTo(FX_FLOAT x, FX_FLOAT y)
+{
+ m_pPathData->AddPointCount(1);
+ m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_LINETO);
+}
+void CFX_PathGenerator::BezierTo(FX_FLOAT ctrl_x1, FX_FLOAT ctrl_y1,
+ FX_FLOAT ctrl_x2, FX_FLOAT ctrl_y2, FX_FLOAT to_x, FX_FLOAT to_y)
+{
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(3);
+ m_pPathData->SetPoint(old_count, ctrl_x1, ctrl_y1, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 1, ctrl_x2, ctrl_y2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 2, to_x, to_y, FXPT_BEZIERTO);
+}
+void CFX_PathGenerator::Close()
+{
+ if (m_pPathData->GetPointCount() > 0) {
+ int index = m_pPathData->GetPointCount() - 1;
+ FX_PATHPOINT *pPoints = m_pPathData->GetPoints();
+ pPoints[index].m_Flag |= FXPT_CLOSEFIGURE;
+ }
+}
+void CFX_PathGenerator::AddLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2)
+{
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(2);
+ m_pPathData->SetPoint(old_count, x1, y1, FXPT_MOVETO);
+ m_pPathData->SetPoint(old_count + 1, x2, y2, FXPT_LINETO);
+}
+void CFX_PathGenerator::AddBezier(FX_FLOAT start_x, FX_FLOAT start_y,
+ FX_FLOAT ctrl_x1, FX_FLOAT ctrl_y1, FX_FLOAT ctrl_x2, FX_FLOAT ctrl_y2,
+ FX_FLOAT end_x, FX_FLOAT end_y)
+{
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(4);
+ m_pPathData->SetPoint(old_count, start_x, start_y, FXPT_MOVETO);
+ m_pPathData->SetPoint(old_count + 1, ctrl_x1, ctrl_y1, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 2, ctrl_x2, ctrl_y2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 3, end_x, end_y, FXPT_BEZIERTO);
+}
+void CFX_PathGenerator::AddRectangle(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2)
+{
+ m_pPathData->AppendRect(x1, y1, x2, y2);
+}
+void CFX_PathGenerator::AddEllipse(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height)
+{
+#if 0
+ FX_FIXFLOAT16 k;
+ k = fix16_to_8(fixsqrt_32_to_16(fixmul_8_8_to_32(width, width) + fixmul_8_8_to_32(height, height)) / 2);
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(7);
+ m_pPathData->SetPoint(old_count, x, y - height / 2, FXPT_MOVETO);
+ m_pPathData->SetPoint(old_count + 1, x + k, y - height / 2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 2, x + k, y + height / 2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 3, x, y + height / 2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 4, x - k, y + height / 2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 5, x - k, y - height / 2, FXPT_BEZIERTO);
+ m_pPathData->SetPoint(old_count + 6, x, y - height / 2, FXPT_BEZIERTO);
+#else
+ AddArc(x, y, width, height, 0, FX_PI * 2);
+#endif
+}
+void CFX_PathGenerator::ArcTo(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle)
+{
+ FX_FLOAT x0 = FXSYS_cos(sweep_angle / 2);
+ FX_FLOAT y0 = FXSYS_sin(sweep_angle / 2);
+ FX_FLOAT tx = FXSYS_Div((1.0f - x0) * 4, 3 * 1.0f);
+ FX_FLOAT ty = y0 - FXSYS_Div(FXSYS_Mul(tx, x0), y0);
+ FX_FLOAT px[3], py[3];
+ px[0] = x0 + tx;
+ py[0] = -ty;
+ px[1] = x0 + tx;
+ py[1] = ty;
+ FX_FLOAT sn = FXSYS_sin(start_angle + sweep_angle / 2);
+ FX_FLOAT cs = FXSYS_cos(start_angle + sweep_angle / 2);
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(3);
+ FX_FLOAT bezier_x, bezier_y;
+ bezier_x = x + FXSYS_Mul(width, FXSYS_Mul(px[0], cs) - FXSYS_Mul(py[0], sn));
+ bezier_y = y + FXSYS_Mul(height, FXSYS_Mul(px[0], sn) + FXSYS_Mul(py[0], cs));
+ m_pPathData->SetPoint(old_count, bezier_x, bezier_y, FXPT_BEZIERTO);
+ bezier_x = x + FXSYS_Mul(width, FXSYS_Mul(px[1], cs) - FXSYS_Mul(py[1], sn));
+ bezier_y = y + FXSYS_Mul(height, FXSYS_Mul(px[1], sn) + FXSYS_Mul(py[1], cs));
+ m_pPathData->SetPoint(old_count + 1, bezier_x, bezier_y, FXPT_BEZIERTO);
+ bezier_x = x + FXSYS_Mul(width, FXSYS_cos(start_angle + sweep_angle)),
+ bezier_y = y + FXSYS_Mul(height, FXSYS_sin(start_angle + sweep_angle));
+ m_pPathData->SetPoint(old_count + 2, bezier_x, bezier_y, FXPT_BEZIERTO);
+}
+void CFX_PathGenerator::AddArc(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle)
+{
+#if 0
+ FX_FIXFLOAT32 sweep = sweep_angle;
+ while (sweep > FIXFLOAT32_PI * 2) {
+ sweep -= FIXFLOAT32_PI * 2;
+ }
+ if (sweep == 0) {
+ return;
+ }
+ m_pPathData->AddPointCount(1);
+ m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1,
+ x + fixmul_8_32_to_8(width, fixcos(start_angle)),
+ y + fixmul_8_32_to_8(height, fixsin(start_angle)), FXPT_MOVETO);
+ FX_FIXFLOAT32 angle1 = 0, angle2;
+ FX_BOOL bDone = FALSE;
+ do {
+ angle2 = angle1 + FIXFLOAT32_PI / 2;
+ if (angle2 >= sweep) {
+ angle2 = sweep;
+ bDone = TRUE;
+ }
+ ArcTo(x, y, width, height, start_angle + angle1, angle2 - angle1);
+ angle1 = angle2;
+ } while (!bDone);
+#else
+ if (sweep_angle == 0) {
+ return;
+ }
+ static const FX_FLOAT bezier_arc_angle_epsilon = (FX_FLOAT)(0.01f);
+ while (start_angle > FX_PI * 2) {
+ start_angle -= FX_PI * 2;
+ }
+ while (start_angle < 0) {
+ start_angle += FX_PI * 2;
+ }
+ if(sweep_angle >= FX_PI * 2) {
+ sweep_angle = FX_PI * 2;
+ }
+ if(sweep_angle <= -FX_PI * 2) {
+ sweep_angle = -FX_PI * 2;
+ }
+ m_pPathData->AddPointCount(1);
+ m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1,
+ x + FXSYS_Mul(width, FXSYS_cos(start_angle)),
+ y + FXSYS_Mul(height, FXSYS_sin(start_angle)), FXPT_MOVETO);
+ FX_FLOAT total_sweep = 0, local_sweep = 0, prev_sweep = 0;
+ FX_BOOL done = FALSE;
+ do {
+ if (sweep_angle < 0) {
+ prev_sweep = total_sweep;
+ local_sweep = -FX_PI / 2;
+ total_sweep -= FX_PI / 2;
+ if (total_sweep <= sweep_angle + bezier_arc_angle_epsilon) {
+ local_sweep = sweep_angle - prev_sweep;
+ done = TRUE;
+ }
+ } else {
+ prev_sweep = total_sweep;
+ local_sweep = FX_PI / 2;
+ total_sweep += FX_PI / 2;
+ if (total_sweep >= sweep_angle - bezier_arc_angle_epsilon) {
+ local_sweep = sweep_angle - prev_sweep;
+ done = TRUE;
+ }
+ }
+ ArcTo(x, y, width, height, start_angle, local_sweep);
+ start_angle += local_sweep;
+ } while (!done);
+#endif
+}
+void CFX_PathGenerator::AddPie(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle)
+{
+ if (sweep_angle == 0) {
+ int old_count = m_pPathData->GetPointCount();
+ m_pPathData->AddPointCount(2);
+ m_pPathData->SetPoint(old_count, x, y, FXPT_MOVETO);
+ m_pPathData->SetPoint(old_count + 1,
+ x + FXSYS_Mul(width, FXSYS_cos(start_angle)),
+ y + FXSYS_Mul(height, FXSYS_sin(start_angle)), FXPT_LINETO);
+ return;
+ }
+ AddArc(x, y, width, height, start_angle, sweep_angle);
+ m_pPathData->AddPointCount(1);
+ m_pPathData->SetPoint(m_pPathData->GetPointCount() - 1, x, y, FXPT_LINETO | FXPT_CLOSEFIGURE);
+}
diff --git a/xfa/src/fxgraphics/src/fx_path_generator.h b/xfa/src/fxgraphics/src/fx_path_generator.h
new file mode 100644
index 0000000000..c1447f6c3a
--- /dev/null
+++ b/xfa/src/fxgraphics/src/fx_path_generator.h
@@ -0,0 +1,42 @@
+// 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
+
+#ifndef __H_FX_PATH_GENERATOR__
+#define __H_FX_PATH_GENERATOR__
+class CFX_PathGenerator : public CFX_Object
+{
+public:
+ CFX_PathGenerator();
+ void Create();
+ ~CFX_PathGenerator();
+ CFX_PathData *GetPathData() const
+ {
+ return m_pPathData;
+ }
+ void AddPathData(CFX_PathData *path_data);
+ void AddPathData(FX_PATHPOINT *points, int count);
+ void MoveTo(FX_FLOAT x, FX_FLOAT y);
+ void LineTo(FX_FLOAT x, FX_FLOAT y);
+ void BezierTo(FX_FLOAT ctrl_x1, FX_FLOAT ctrl_y1,
+ FX_FLOAT ctrl_x2, FX_FLOAT ctrl_y2, FX_FLOAT to_x, FX_FLOAT to_y);
+ void Close();
+ void ArcTo(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle);
+
+ void AddLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2);
+ void AddBezier(FX_FLOAT start_x, FX_FLOAT start_y,
+ FX_FLOAT ctrl_x1, FX_FLOAT ctrl_y1, FX_FLOAT ctrl_x2, FX_FLOAT ctrl_y2,
+ FX_FLOAT end_x, FX_FLOAT end_y);
+ void AddRectangle(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2);
+ void AddEllipse(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height);
+ void AddArc(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle);
+ void AddPie(FX_FLOAT x, FX_FLOAT y, FX_FLOAT width, FX_FLOAT height,
+ FX_FLOAT start_angle, FX_FLOAT sweep_angle);
+protected:
+ CFX_PathData *m_pPathData;
+};
+#endif
diff --git a/xfa/src/fxgraphics/src/pre.h b/xfa/src/fxgraphics/src/pre.h
new file mode 100644
index 0000000000..dc82b35a74
--- /dev/null
+++ b/xfa/src/fxgraphics/src/pre.h
@@ -0,0 +1,115 @@
+// 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 "../../foxitlib.h"
+#ifndef FXSYS_Mul
+#define FXSYS_Mul(a, b) ((a) * (b))
+#define FXSYS_Div(a, b) ((a) / (b))
+#define FXSYS_MulDiv(a, b, c) ((a) * (b) / (c))
+#define FXSYS_sqrt2(a, b) (FX_FLOAT)FXSYS_sqrt((a)*(a) + (b)*(b))
+#endif
+enum {
+ FX_CONTEXT_None = 0,
+ FX_CONTEXT_Device,
+};
+enum {
+ FX_COLOR_None = 0,
+ FX_COLOR_Solid,
+ FX_COLOR_Pattern,
+ FX_COLOR_Shading
+};
+enum {
+ FX_PATTERN_None = 0,
+ FX_PATTERN_Bitmap,
+ FX_PATTERN_Hatch
+};
+enum {
+ FX_SHADING_None = 0,
+ FX_SHADING_Axial,
+ FX_SHADING_Radial
+};
+#define FX_HATCHSTYLE_Total 53
+struct FX_HATCHDATA {
+ FX_INT32 width;
+ FX_INT32 height;
+ FX_BYTE maskBits[64];
+};
+typedef FX_HATCHDATA const * FX_LPCHATCHDATA;
+static const FX_HATCHDATA hatchBitmapData[FX_HATCHSTYLE_Total] = {
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,}},
+ {16, 16, {0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,}},
+ {16, 16, {0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00,}},
+ {16, 16, {0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,}},
+ {16, 16, {0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x15, 0x15, 0x00, 0x00,}},
+ {16, 16, {0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,}},
+ {16, 16, {0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xee, 0xee, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xbb, 0xbb, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,}},
+ {16, 16, {0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00,}},
+ {16, 16, {0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xdd, 0xdd, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,}},
+ {16, 16, {0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xef, 0xef, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xf7, 0xf7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,}},
+ {16, 16, {0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00,}},
+ {16, 16, {0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,}},
+ {16, 16, {0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,}},
+ {16, 16, {0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,}},
+ {16, 16, {0xc1, 0xc1, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x83, 0x83, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x83, 0x83, 0x00, 0x00,}},
+ {16, 16, {0x83, 0x83, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x83, 0x83, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00,}},
+ {16, 16, {0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,}},
+ {16, 16, {0xb1, 0xb1, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0xd8, 0xd8, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x8d, 0x8d, 0x00, 0x00, 0xb1, 0xb1, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0xd8, 0xd8, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x8d, 0x8d, 0x00, 0x00,}},
+ {16, 16, {0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,}},
+ {16, 16, {0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00,}},
+ {16, 16, {0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x81, 0x81, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,}},
+ {16, 16, {0x88, 0x88, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x45, 0x45, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x45, 0x45, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x14, 0x14, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x51, 0x51, 0x00, 0x00,}},
+ {16, 16, {0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00,}},
+ {16, 16, {0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,}},
+ {16, 16, {0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+ {16, 16, {0x03, 0x03, 0x00, 0x00, 0x84, 0x84, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x84, 0x84, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,}},
+ {16, 16, {0x77, 0x77, 0x00, 0x00, 0x89, 0x89, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x98, 0x98, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x89, 0x89, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00, 0x8f, 0x8f, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x98, 0x98, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00,}},
+ {16, 16, {0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00, 0x88, 0x88, 0x00, 0x00,}},
+ {16, 16, {0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x99, 0x99, 0x00, 0x00,}},
+ {16, 16, {0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,}},
+ {16, 16, {0x82, 0x82, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x82, 0x82, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x82, 0x82, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x28, 0x28, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x82, 0x82, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,}},
+ {16, 16, {0x10, 0x10, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x7c, 0x7c, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}},
+};
+#if defined (__WIN32__) || defined (_WIN32)
+#define FX_START_TIMER SYSTEMTIME start, stop; \
+ ::GetLocalTime(&start);
+#define FX_STOP_TIMER ::GetLocalTime(&stop); \
+ WORD wSecond = stop.wSecond - start.wSecond; \
+ WORD wMilliseconds = stop.wMilliseconds - start.wMilliseconds; \
+ char buf[256]; \
+ sprintf(buf, "duration is %d millisecond\n", wSecond * 1000 + wMilliseconds); \
+ ::OutputDebugString(buf);
+#elif defined (__linux) || defined (linux)
+#define FX_START_TIMER
+#define FX_STOP_TIMER
+#elif defined (__APPLE__) || defined (__MACOSX__)
+#define FX_START_TIMER NSTimeInterval start, stop; \
+ start = [NSDate timeIntervalSinceReferenceDate];
+#define FX_STOP_TIMER stop = [NSDate timeIntervalSinceReferenceDate]; \
+ NSTimeInterval duration = stop - start; \
+ printf("duration is %f millisecond\n", duration * 1000);
+#else
+#endif