1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// found in the LICENSE file.
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../../include/fxge/fx_ge.h"
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../dib/dib_int.h"
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../ge/text_int.h"
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../../../include/fxcodec/fx_codec.h"
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_pixfmt_gray.h"
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_path_storage.h"
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_scanline_u.h"
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_rasterizer_scanline_aa.h"
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_renderer_scanline.h"
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_curves.h"
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_conv_stroke.h"
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "agg_conv_dash.h"
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../include/fx_agg_driver.h"
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _HardClip(FX_FLOAT& x, FX_FLOAT& y)
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (x > 50000) {
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x = 50000;
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (x < -50000) {
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x = -50000;
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (y > 50000) {
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y = 50000;
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (y < -50000) {
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y = -50000;
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CAgg_PathData::BuildPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device)
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int nPoints = pPathData->GetPointCount();
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_PATHPOINT* pPoints = pPathData->GetPoints();
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (int i = 0; i < nPoints; i ++) {
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_FLOAT x = pPoints[i].m_PointX, y = pPoints[i].m_PointY;
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pObject2Device) {
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pObject2Device->Transform(x, y);
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _HardClip(x, y);
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int point_type = pPoints[i].m_Flag & FXPT_TYPE;
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (point_type == FXPT_MOVETO) {
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_PathData.move_to(x, y);
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (point_type == FXPT_LINETO) {
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pPoints[i - 1].m_Flag == FXPT_MOVETO && (i == nPoints - 1 || pPoints[i + 1].m_Flag == FXPT_MOVETO) &&
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    pPoints[i].m_PointX == pPoints[i - 1].m_PointX && pPoints[i].m_PointY == pPoints[i - 1].m_PointY) {
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                x += 1;
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_PathData.line_to(x, y);
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (point_type == FXPT_BEZIERTO) {
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_FLOAT x0 = pPoints[i - 1].m_PointX, y0 = pPoints[i - 1].m_PointY;
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_FLOAT x2 = pPoints[i + 1].m_PointX, y2 = pPoints[i + 1].m_PointY;
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_FLOAT x3 = pPoints[i + 2].m_PointX, y3 = pPoints[i + 2].m_PointY;
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pObject2Device) {
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pObject2Device->Transform(x0, y0);
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pObject2Device->Transform(x2, y2);
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pObject2Device->Transform(x3, y3);
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            agg::curve4 curve(x0, y0, x, y, x2, y2, x3, y3);
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            i += 2;
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_PathData.add_path_curve(curve);
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE) {
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_PathData.end_poly();
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovnamespace agg
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtemplate<class BaseRenderer> class renderer_scanline_aa_offset
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    typedef BaseRenderer base_ren_type;
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    typedef typename base_ren_type::color_type color_type;
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    renderer_scanline_aa_offset(base_ren_type& ren, unsigned left, unsigned top) :
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_ren(&ren), m_left(left), m_top(top)
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {}
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void color(const color_type& c)
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_color = c;
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const color_type& color() const
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return m_color;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void prepare(unsigned) {}
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    template<class Scanline> void render(const Scanline& sl)
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int y = sl.y();
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        unsigned num_spans = sl.num_spans();
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        typename Scanline::const_iterator span = sl.begin();
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for(;;) {
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int x = span->x;
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if(span->len > 0) {
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_ren->blend_solid_hspan(x - m_left, y - m_top, (unsigned)span->len,
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                         m_color,
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                         span->covers);
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_ren->blend_hline(x - m_left, y - m_top, (unsigned)(x - span->len - 1),
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                   m_color,
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                   *(span->covers));
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if(--num_spans == 0) {
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ++span;
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovprivate:
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    base_ren_type* m_ren;
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    color_type m_color;
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    unsigned m_left, m_top;
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic void RasterizeStroke(agg::rasterizer_scanline_aa& rasterizer, agg::path_storage& path_data,
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            const CFX_AffineMatrix* pObject2Device,
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            const CFX_GraphStateData* pGraphState, FX_FLOAT scale = 1.0f,
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            FX_BOOL bStrokeAdjust = FALSE, FX_BOOL bTextMode = FALSE)
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::line_cap_e cap;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (pGraphState->m_LineCap) {
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case CFX_GraphStateData::LineCapRound:
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cap = agg::round_cap;
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case CFX_GraphStateData::LineCapSquare:
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cap = agg::square_cap;
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        default:
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cap = agg::butt_cap;
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::line_join_e join;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (pGraphState->m_LineJoin) {
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case CFX_GraphStateData::LineJoinRound:
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            join = agg::round_join;
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case CFX_GraphStateData::LineJoinBevel:
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            join = agg::bevel_join;
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        default:
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            join = agg::miter_join_revert;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            break;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_FLOAT width = pGraphState->m_LineWidth * scale;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_FLOAT unit = 1.f;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pObject2Device) {
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        unit = FXSYS_Div(1.0f, (pObject2Device->GetXUnit() + pObject2Device->GetYUnit()) / 2);
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (width < unit) {
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        width = unit;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pGraphState->m_DashArray == NULL) {
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        agg::conv_stroke<agg::path_storage> stroke(path_data);
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.line_join(join);
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.line_cap(cap);
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.miter_limit(pGraphState->m_MiterLimit);
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.width(width);
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.add_path_transformed(stroke, pObject2Device);
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        typedef agg::conv_dash<agg::path_storage> dash_converter;
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dash_converter dash(path_data);
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int i = 0; i < (pGraphState->m_DashCount + 1) / 2; i ++) {
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_FLOAT on = pGraphState->m_DashArray[i * 2];
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (on <= 0.000001f) {
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                on = 1.0f / 10;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount ? on :
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           pGraphState->m_DashArray[i * 2 + 1];
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (off < 0) {
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                off = 0;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dash.add_dash(on * scale, off * scale);
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dash.dash_start(pGraphState->m_DashPhase * scale);
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        typedef agg::conv_stroke<dash_converter> dash_stroke;
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dash_stroke stroke(dash);
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.line_join(join);
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.line_cap(cap);
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.miter_limit(pGraphState->m_MiterLimit);
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stroke.width(width);
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.add_path_transformed(stroke, pObject2Device);
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIFX_RenderDeviceDriver* IFX_RenderDeviceDriver::CreateFxgeDriver(CFX_DIBitmap* pBitmap, FX_BOOL bRgbByteOrder, CFX_DIBitmap* pOriDevice, FX_BOOL bGroupKnockout)
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FX_NEW CFX_AggDeviceDriver(pBitmap, 0, bRgbByteOrder, pOriDevice, bGroupKnockout);
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_AggDeviceDriver::CFX_AggDeviceDriver(CFX_DIBitmap* pBitmap, int dither_bits, FX_BOOL bRgbByteOrder, CFX_DIBitmap* pOriDevice, FX_BOOL bGroupKnockout)
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pBitmap = pBitmap;
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_DitherBits = dither_bits;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pClipRgn = NULL;
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pPlatformBitmap = NULL;
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pPlatformGraphics = NULL;
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pDwRenderTartget = NULL;
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bRgbByteOrder = bRgbByteOrder;
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pOriDevice = pOriDevice;
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bGroupKnockout = bGroupKnockout;
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FillFlags = 0;
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    InitPlatform();
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_AggDeviceDriver::~CFX_AggDeviceDriver()
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn) {
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete m_pClipRgn;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (int i = 0; i < m_StateStack.GetSize(); i ++)
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_StateStack[i]) {
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            delete (CFX_ClipRgn*)m_StateStack[i];
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DestroyPlatform();
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if ((_FXM_PLATFORM_  != _FXM_PLATFORM_APPLE_)|| defined(_FPDFAPI_MINI_))
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::InitPlatform()
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::DestroyPlatform()
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont,
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, FX_FLOAT font_size, FX_DWORD color,
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int alpha_flag, void* pIccTransform)
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint CFX_AggDeviceDriver::GetDeviceCaps(int caps_id)
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (caps_id) {
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_DEVICE_CLASS:
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FXDC_DISPLAY;
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_PIXEL_WIDTH:
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_pBitmap->GetWidth();
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_PIXEL_HEIGHT:
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_pBitmap->GetHeight();
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_BITS_PIXEL:
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_pBitmap->GetBPP();
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_HORZ_SIZE:
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_VERT_SIZE:
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return 0;
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_RENDER_CAPS: {
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | FXRC_BLEND_MODE | FXRC_SOFT_CLIP;
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_pBitmap->HasAlpha()) {
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    flags |= FXRC_ALPHA_OUTPUT;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else if (m_pBitmap->IsAlphaMask()) {
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (m_pBitmap->GetBPP() == 1) {
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        flags |= FXRC_BITMASK_OUTPUT;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        flags |= FXRC_BYTEMASK_OUTPUT;
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_pBitmap->IsCmykImage()) {
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    flags |= FXRC_CMYK_OUTPUT;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return flags;
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        case FXDC_DITHER_BITS:
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return m_DitherBits;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return 0;
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::SaveState()
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void* pClip = NULL;
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn) {
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pClip = FX_NEW CFX_ClipRgn(*m_pClipRgn);
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pClip) {
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_StateStack.Add(pClip);
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::RestoreState(FX_BOOL bKeepSaved)
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_StateStack.GetSize() == 0) {
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pClipRgn) {
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            delete m_pClipRgn;
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pClipRgn = NULL;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ClipRgn* pSavedClip = (CFX_ClipRgn*)m_StateStack[m_StateStack.GetSize() - 1];
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn) {
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete m_pClipRgn;
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipRgn = NULL;
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bKeepSaved) {
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pSavedClip) {
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pClipRgn = FX_NEW CFX_ClipRgn(*pSavedClip);
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_StateStack.RemoveAt(m_StateStack.GetSize() - 1);
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipRgn = pSavedClip;
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::SetClipMask(agg::rasterizer_scanline_aa& rasterizer)
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(),
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      rasterizer.max_x() + 1, rasterizer.max_y() + 1);
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    path_rect.Intersect(m_pClipRgn->GetBox());
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmapRef mask;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap* pThisLayer = mask.New();
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pThisLayer) {
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask);
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pThisLayer->Clear(0);
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::rendering_buffer raw_buf(pThisLayer->GetBuffer(), pThisLayer->GetWidth(), pThisLayer->GetHeight(), pThisLayer->GetPitch());
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::pixfmt_gray8 pixel_buf(raw_buf);
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::renderer_scanline_aa_offset<agg::renderer_base<agg::pixfmt_gray8> > final_render(base_buf, path_rect.left, path_rect.top);
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    final_render.color(agg::gray8(255));
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::scanline_u8 scanline;
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::render_scanlines(rasterizer, scanline, final_render, (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask);
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::SetClip_PathFill(const CFX_PathData* pPathData,
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const CFX_AffineMatrix* pObject2Device,
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int fill_mode
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             )
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FillFlags = fill_mode;
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn == NULL) {
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipRgn = FX_NEW CFX_ClipRgn(GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!m_pClipRgn) {
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) {
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_FloatRect rectf;
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pPathData->IsRect(pObject2Device, &rectf)) {
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rectf.Intersect(CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_RECT rect = rectf.GetOutterRect();
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pClipRgn->IntersectRect(rect);
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return TRUE;
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CAgg_PathData path_data;
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    path_data.BuildPath(pPathData, pObject2Device);
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    path_data.m_PathData.end_poly();
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::rasterizer_scanline_aa rasterizer;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rasterizer.add_path(path_data.m_PathData);
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING ? agg::fill_non_zero : agg::fill_even_odd);
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetClipMask(rasterizer);
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::SetClip_PathStroke(const CFX_PathData* pPathData,
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const CFX_AffineMatrix* pObject2Device,
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const CFX_GraphStateData* pGraphState
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                               )
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn == NULL) {
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipRgn = FX_NEW CFX_ClipRgn(GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!m_pClipRgn) {
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CAgg_PathData path_data;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    path_data.BuildPath(pPathData, NULL);
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::rasterizer_scanline_aa rasterizer;
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    RasterizeStroke(rasterizer, path_data.m_PathData, pObject2Device, pGraphState);
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rasterizer.filling_rule(agg::fill_non_zero);
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetClipMask(rasterizer);
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovclass CFX_Renderer : public CFX_Object
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovprivate:
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int			m_Alpha,
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Red,
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Green,
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Blue,
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Gray;
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_DWORD	m_Color;
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL		m_bFullCover;
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL     m_bRgbByteOrder;
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap* m_pOriDevice;
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT		m_ClipBox;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const CFX_DIBitmap*	m_pClipMask;
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap*	m_pDevice;
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const CFX_ClipRgn* m_pClipRgn;
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void (CFX_Renderer::*composite_span)(FX_LPBYTE, int, int, int, FX_LPBYTE, int, int, FX_LPBYTE, FX_LPBYTE);
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovpublic:
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void prepare(unsigned) {}
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpan(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan, int Bpp, FX_BOOL bDestAlpha,
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       int span_left, int span_len, FX_LPBYTE cover_scan,
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       int clip_left, int clip_right, FX_LPBYTE clip_scan)
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(!m_pDevice->IsCmykImage());
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Bpp) {
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_scan += col_start * Bpp;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ori_scan += col_start * Bpp;
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_scan += col_start / 8;
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ori_scan += col_start / 8;
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Bpp == 4 && bDestAlpha) {
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = col_start; col < col_end; col ++) {
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int src_alpha;
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_BYTE dest_alpha = ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255;
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan[3] = dest_alpha;
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int alpha_ratio = src_alpha * 255 / dest_alpha;
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (m_bFullCover) {
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan++;
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        ori_scan++;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio);
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio);
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio);
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        ori_scan ++;
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, r, cover_scan[col]);
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 2;
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return;
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else if (Bpp == 3 || Bpp == 4) {
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = col_start; col < col_end; col ++) {
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int src_alpha;
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255 ;
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha);
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    ori_scan += Bpp - 2;
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, r, cover_scan[col]);
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += Bpp - 2;
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Bpp == 4 && bDestAlpha) {
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * clip_scan[col] / 255;
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha;
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha_covered = src_alpha * cover_scan[col] / 255;
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha_covered == 0) {
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 4;
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    continue;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (cover_scan[col] == 255) {
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan[3] = src_alpha_covered;
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan ++ = m_Blue;
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan ++ = m_Green;
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = m_Red;
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 2;
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    continue;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (dest_scan[3] == 0) {
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan[3] = src_alpha_covered;
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan ++ = m_Blue;
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan ++ = m_Green;
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = m_Red;
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 2;
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_BYTE cover = cover_scan[col];
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 2;
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (Bpp == 3 || Bpp == 4) {
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * clip_scan[col] / 255;
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha;
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += Bpp - 2;
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    ori_scan += Bpp - 2;
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    continue;
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                ori_scan += Bpp - 2;
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan[col]);
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan ++;
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]);
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan ++;
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += Bpp - 2;
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                continue;
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (Bpp == 1) {
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * clip_scan[col] / 255;
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha;
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan++;
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int index = 0;
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_pDevice->GetPalette() == NULL) {
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                index = ((FX_BYTE)m_Color == 0xff) ? 1 : 0;
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int i = 0; i < 2; i ++)
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        index = i;
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE dest_scan1 = dest_scan;
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] / 255;
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (!index) {
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpan1bpp(FX_LPBYTE dest_scan, int Bpp,
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int span_left, int span_len, FX_LPBYTE cover_scan,
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int clip_left, int clip_right, FX_LPBYTE clip_scan,
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FX_LPBYTE dest_extra_alpha_scan)
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(!m_bRgbByteOrder);
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(!m_pDevice->IsCmykImage());
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_scan += col_start / 8;
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int index = 0;
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pDevice->GetPalette() == NULL) {
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            index = ((FX_BYTE)m_Color == 0xff) ? 1 : 0;
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int i = 0; i < 2; i ++)
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) {
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    index = i;
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_scan1 = dest_scan;
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int col = col_start; col < col_end; col ++) {
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int src_alpha;
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (clip_scan) {
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                src_alpha = m_Alpha * cover_scan[col] / 255;
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (src_alpha) {
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!index) {
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8));
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan1 |= 1 << (7 - (col + span_left) % 8);
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8;
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpanGray(FX_LPBYTE dest_scan, int Bpp,
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int span_left, int span_len, FX_LPBYTE cover_scan,
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int clip_left, int clip_right, FX_LPBYTE clip_scan,
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FX_LPBYTE dest_extra_alpha_scan)
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(!m_bRgbByteOrder);
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_scan += col_start;
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (dest_extra_alpha_scan) {
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] / 255;
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = m_Gray;
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan = m_Alpha;
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             (*dest_extra_alpha_scan) * src_alpha / 255;
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan++ = dest_alpha;
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int alpha_ratio = src_alpha * 255 / dest_alpha;
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_extra_alpha_scan ++;
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan ++;
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] / 255;
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = m_Gray;
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan ++;
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpanARGB(FX_LPBYTE dest_scan, int Bpp,
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int span_left, int span_len, FX_LPBYTE cover_scan,
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int clip_left, int clip_right, FX_LPBYTE clip_scan,
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FX_LPBYTE dest_extra_alpha_scan)
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_scan += col_start * Bpp;
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] / 255;
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *(FX_DWORD*)dest_scan = m_Color;
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FX_BYTE dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan[3] = dest_alpha;
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int alpha_ratio = src_alpha * 255 / dest_alpha;
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 2;
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += 4;
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int col = col_start; col < col_end; col ++) {
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int src_alpha;
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_bFullCover) {
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * clip_scan[col] / 255;
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha;
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] / 255;
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (src_alpha) {
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha == 255) {
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *(FX_DWORD*)dest_scan = m_Color;
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (dest_scan[3] == 0) {
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan[3] = src_alpha;
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = m_Blue;
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = m_Green;
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = m_Red;
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 2;
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_BYTE dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan[3] = dest_alpha;
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int alpha_ratio = src_alpha * 255 / dest_alpha;
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan ++;
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 2;
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    continue;
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_scan += Bpp;
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpanRGB(FX_LPBYTE dest_scan, int Bpp,
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          int span_left, int span_len, FX_LPBYTE cover_scan,
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          int clip_left, int clip_right, FX_LPBYTE clip_scan,
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                          FX_LPBYTE dest_extra_alpha_scan)
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_scan += col_start * Bpp;
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] / 255;
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (Bpp == 4) {
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *(FX_DWORD*)dest_scan = m_Color;
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        } else if (Bpp == 3) {
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Red;
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Green;
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Blue;
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            continue;
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan++;
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan++;
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += Bpp - 2;
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += Bpp;
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Bpp == 3 && dest_extra_alpha_scan) {
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] / 255;
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = (FX_BYTE)m_Blue;
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = (FX_BYTE)m_Green;
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan++ = (FX_BYTE)m_Red;
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan++ = (FX_BYTE)m_Alpha;
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             (*dest_extra_alpha_scan) * src_alpha / 255;
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan++ = dest_alpha;
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int alpha_ratio = src_alpha * 255 / dest_alpha;
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_extra_alpha_scan++;
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += Bpp;
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] / 255;
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (Bpp == 4) {
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *(FX_DWORD*)dest_scan = m_Color;
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        } else if (Bpp == 3) {
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Blue;
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Green;
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            *dest_scan++ = m_Red;
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            continue;
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        }
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += Bpp - 2;
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += Bpp;
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    void CompositeSpanCMYK(FX_LPBYTE dest_scan, int Bpp,
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int span_left, int span_len, FX_LPBYTE cover_scan,
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           int clip_left, int clip_right, FX_LPBYTE clip_scan,
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                           FX_LPBYTE dest_extra_alpha_scan)
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(!m_bRgbByteOrder);
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_start = span_left < clip_left ? clip_left - span_left : 0;
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        dest_scan += col_start * 4;
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (dest_extra_alpha_scan) {
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bFullCover) {
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * clip_scan[col] / 255;
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha;
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (clip_scan) {
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_alpha = m_Alpha * cover_scan[col] / 255;
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *(FX_CMYK*)dest_scan = m_Color;
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan = (FX_BYTE)m_Alpha;
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             (*dest_extra_alpha_scan) * src_alpha / 255;
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_extra_alpha_scan++ = dest_alpha;
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        int alpha_ratio = src_alpha * 255 / dest_alpha;
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_extra_alpha_scan++;
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += 4;
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = col_start; col < col_end; col ++) {
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int src_alpha;
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (clip_scan) {
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255;
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_alpha = m_Alpha * cover_scan[col] / 255;
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_alpha) {
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (src_alpha == 255) {
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *(FX_CMYK*)dest_scan = m_Color;
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan ++;
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        continue;
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += 4;
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    template<class Scanline> void render(const Scanline& sl)
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pOriDevice == NULL && composite_span == NULL) {
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int y = sl.y();
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (y < m_ClipBox.top || y >= m_ClipBox.bottom) {
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return;
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y;
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_scan_extra_alpha = NULL;
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask;
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pAlphaMask) {
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            dest_scan_extra_alpha = pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y;
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE ori_scan = NULL;
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pOriDevice) {
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y;
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int Bpp = m_pDevice->GetBPP() / 8;
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask();
973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        unsigned num_spans = sl.num_spans();
974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        typename Scanline::const_iterator span = sl.begin();
975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        while (1) {
976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int x = span->x;
977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ASSERT(span->len > 0);
978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE dest_pos = NULL;
979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE dest_extra_alpha_pos = NULL;
980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE ori_pos = NULL;
981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Bpp) {
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                ori_pos = ori_scan ? ori_scan + x * Bpp : NULL;
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_pos = dest_scan + x * Bpp;
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_extra_alpha_pos = dest_scan_extra_alpha ? dest_scan_extra_alpha + x : NULL;
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_pos = dest_scan + x / 8;
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                ori_pos = ori_scan ? ori_scan + x / 8 : NULL;
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE clip_pos = NULL;
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_pClipMask) {
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                clip_pos = m_pClipMask->GetBuffer() + (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - m_ClipBox.left;
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (ori_pos) {
994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos);
995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos, dest_extra_alpha_pos);
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if(--num_spans == 0) {
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ++span;
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL Init(CFX_DIBitmap* pDevice, CFX_DIBitmap* pOriDevice, const CFX_ClipRgn* pClipRgn, FX_DWORD color, FX_BOOL bFullCover, FX_BOOL bRgbByteOrder,
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 int alpha_flag = 0, void* pIccTransform = NULL)
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pDevice = pDevice;
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipRgn = pClipRgn;
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        composite_span = NULL;
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_bRgbByteOrder = bRgbByteOrder;
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pOriDevice = pOriDevice;
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pClipRgn) {
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_ClipBox = m_pClipRgn->GetBox();
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_ClipBox.left = m_ClipBox.top = 0;
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_ClipBox.right = m_pDevice->GetWidth();
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_ClipBox.bottom = m_pDevice->GetHeight();
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_pClipMask = NULL;
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) {
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pClipMask = m_pClipRgn->GetMask();
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_bFullCover = bFullCover;
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bObjectCMYK = FXGETFLAG_COLORTYPE(alpha_flag);
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_BOOL bDeviceCMYK = pDevice->IsCmykImage();
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ICodec_IccModule* pIccModule = NULL;
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pIccTransform = NULL;
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pDevice->GetBPP() == 8) {
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ASSERT(!m_bRgbByteOrder);
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            composite_span = &CFX_Renderer::CompositeSpanGray;
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_pDevice->IsAlphaMask()) {
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Gray = 255;
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (pIccTransform) {
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_BYTE gray;
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    pIccModule->TranslateScanline(pIccTransform, &gray, (FX_LPCBYTE)&color, 1);
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Gray = gray;
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (bObjectCMYK) {
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FX_BYTE r, g, b;
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                           r, g, b);
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Gray = FXRGB2GRAY(r, g, b);
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Gray = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return TRUE;
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bDeviceCMYK) {
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ASSERT(!m_bRgbByteOrder);
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            composite_span = &CFX_Renderer::CompositeSpanCMYK;
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (bObjectCMYK) {
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Color = FXCMYK_TODIB(color);
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (pIccTransform) {
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&m_Color, 1);
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!pIccTransform) {
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    return FALSE;
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                color = FXARGB_TODIB(color);
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&color, 1);
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_Red = ((FX_LPBYTE)&m_Color)[0];
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_Green = ((FX_LPBYTE)&m_Color)[1];
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_Blue = ((FX_LPBYTE)&m_Color)[2];
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_Gray = ((FX_LPBYTE)&m_Color)[3];
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            composite_span = (pDevice->GetFormat() == FXDIB_Argb) ? &CFX_Renderer::CompositeSpanARGB : &CFX_Renderer::CompositeSpanRGB;
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (pIccTransform) {
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&color, 1);
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                ((FX_LPBYTE)&m_Color)[3] = m_Alpha;
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Red = ((FX_LPBYTE)&m_Color)[2];
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Green = ((FX_LPBYTE)&m_Color)[1];
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                m_Blue = ((FX_LPBYTE)&m_Color)[0];
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (m_bRgbByteOrder) {
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Color = FXARGB_TODIB(m_Color);
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (bObjectCMYK) {
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FX_BYTE r, g, b;
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                       r, g, b);
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Color = FXARGB_MAKE(m_Alpha, r, g, b);
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (m_bRgbByteOrder) {
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Color = FXARGB_TODIB(m_Color);
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Red = r;
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Green = g;
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    m_Blue = b;
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (m_bRgbByteOrder) {
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Color = FXARGB_TOBGRORDERDIB(color);
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    } else {
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        m_Color = FXARGB_TODIB(color);
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue);
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pDevice->GetBPP() == 1) {
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            composite_span = &CFX_Renderer::CompositeSpan1bpp;
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::RenderRasterizer(agg::rasterizer_scanline_aa& rasterizer, FX_DWORD color, FX_BOOL bFullCover, FX_BOOL bGroupKnockout,
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int alpha_flag, void* pIccTransform)
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap* pt = bGroupKnockout ? m_pOriDevice : NULL;
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_Renderer render;
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!render.Init(m_pBitmap, pt, m_pClipRgn, color, bFullCover, m_bRgbByteOrder, alpha_flag, pIccTransform)) {
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::scanline_u8 scanline;
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    agg::render_scanlines(rasterizer, scanline, render, (m_FillFlags & FXFILL_NOPATHSMOOTH) != 0);
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::DrawPath(const CFX_PathData* pPathData,
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      const CFX_AffineMatrix* pObject2Device,
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      const CFX_GraphStateData* pGraphState,
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      FX_DWORD fill_color,
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      FX_DWORD stroke_color,
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      int fill_mode,
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      int alpha_flag,
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      void* pIccTransform,
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      int blend_type
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                     )
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (blend_type != FXDIB_BLEND_NORMAL) {
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (GetBuffer() == NULL) {
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_FillFlags = fill_mode;
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ((fill_mode & 3) && fill_color) {
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CAgg_PathData path_data;
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        path_data.BuildPath(pPathData, pObject2Device);
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        agg::rasterizer_scanline_aa rasterizer;
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.add_path(path_data.m_PathData);
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.filling_rule((fill_mode & 3) == FXFILL_WINDING ? agg::fill_non_zero : agg::fill_even_odd);
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!RenderRasterizer(rasterizer, fill_color, fill_mode & FXFILL_FULLCOVER, FALSE, alpha_flag, pIccTransform)) {
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_STROKE(alpha_flag) : FXARGB_A(stroke_color);
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pGraphState && stroke_alpha) {
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (fill_mode & FX_ZEROAREA_FILL) {
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CAgg_PathData path_data;
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            path_data.BuildPath(pPathData, pObject2Device);
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            agg::rasterizer_scanline_aa rasterizer;
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            RasterizeStroke(rasterizer, path_data.m_PathData, NULL, pGraphState, 1, FALSE, fill_mode & FX_STROKE_TEXT_MODE);
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int fill_flag = FXGETFLAG_COLORTYPE(alpha_flag) << 8 | FXGETFLAG_ALPHA_STROKE(alpha_flag);
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!RenderRasterizer(rasterizer, stroke_color, fill_mode & FXFILL_FULLCOVER, m_bGroupKnockout, fill_flag, pIccTransform)) {
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return TRUE;
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CFX_AffineMatrix matrix1, matrix2;
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pObject2Device) {
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            matrix1.a = FX_MAX(FXSYS_fabs(pObject2Device->a), FXSYS_fabs(pObject2Device->b));
1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            matrix1.d = matrix1.a;
1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            matrix2.Set(pObject2Device->a / matrix1.a, pObject2Device->b / matrix1.a,
1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        pObject2Device->c / matrix1.d, pObject2Device->d / matrix1.d,
1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        0, 0);
1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CFX_AffineMatrix mtRervese;
1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            mtRervese.SetReverse(matrix2);
1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            matrix1 = *pObject2Device;
1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            matrix1.Concat(mtRervese);
1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CAgg_PathData path_data;
1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        path_data.BuildPath(pPathData, &matrix1);
1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        agg::rasterizer_scanline_aa rasterizer;
1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rasterizer.clip_box(0.0f, 0.0f, (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_WIDTH)), (FX_FLOAT)(GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        RasterizeStroke(rasterizer, path_data.m_PathData, &matrix2, pGraphState, matrix1.a, FALSE, fill_mode & FX_STROKE_TEXT_MODE);
1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int fill_flag = FXGETFLAG_COLORTYPE(alpha_flag) << 8 | FXGETFLAG_ALPHA_STROKE(alpha_flag);
1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!RenderRasterizer(rasterizer, stroke_color, fill_mode & FXFILL_FULLCOVER, m_bGroupKnockout, fill_flag, pIccTransform)) {
1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid RgbByteOrderSetPixel(CFX_DIBitmap* pBitmap, int x, int y, FX_DWORD argb)
1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (x < 0 || x >= pBitmap->GetWidth() || y < 0 || y >= pBitmap->GetHeight()) {
1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE pos = (FX_BYTE*)pBitmap->GetBuffer() + y * pBitmap->GetPitch() + x * pBitmap->GetBPP() / 8;
1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pBitmap->GetFormat() == FXDIB_Argb) {
1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FXARGB_SETRGBORDERDIB(pos, ArgbGamma(argb));
1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int alpha = FXARGB_A(argb);
1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pos[0] = (FXARGB_R(argb) * alpha + pos[0] * (255 - alpha)) / 255;
1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pos[1] = (FXARGB_G(argb) * alpha + pos[1] * (255 - alpha)) / 255;
1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pos[2] = (FXARGB_B(argb) * alpha + pos[2] * (255 - alpha)) / 255;
1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid RgbByteOrderCompositeRect(CFX_DIBitmap* pBitmap, int left, int top, int width, int height, FX_ARGB argb)
1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int src_alpha = FXARGB_A(argb);
1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src_alpha == 0) {
1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT rect(left, top, left + width, top + height);
1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rect.Intersect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    width = rect.Width();
1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int src_r = FXARGB_R(argb), src_g = FXARGB_G(argb), src_b = FXARGB_B(argb);
1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Bpp = pBitmap->GetBPP() / 8;
1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL bAlpha = pBitmap->HasAlpha();
1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int dib_argb = FXARGB_TOBGRORDERDIB(argb);
1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE* pBuffer = pBitmap->GetBuffer();
1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src_alpha == 255) {
1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int row = rect.top; row < rect.bottom; row ++) {
1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Bpp == 4) {
1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_DWORD* scan = (FX_DWORD*)dest_scan;
1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col ++) {
1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *scan ++ = dib_argb;
1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col ++) {
1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan ++ = src_r;
1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan ++ = src_g;
1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan ++ = src_b;
1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    src_r = FX_GAMMA(src_r);
1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    src_g = FX_GAMMA(src_g);
1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    src_b = FX_GAMMA(src_b);
1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (int row = rect.top; row < rect.bottom; row ++) {
1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_LPBYTE dest_scan = pBuffer + row * pBitmap->GetPitch() + rect.left * Bpp;
1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (bAlpha) {
1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = 0; col < width; col ++) {
1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_BYTE back_alpha = dest_scan[3];
1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (back_alpha == 0) {
1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FXARGB_SETRGBORDERDIB(dest_scan, FXARGB_MAKE(src_alpha, src_r, src_g, src_b));
1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 4;
1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    continue;
1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_BYTE dest_alpha = back_alpha + src_alpha - back_alpha * src_alpha / 255;
1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan[3] = dest_alpha;
1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                int alpha_ratio = src_alpha * 255 / dest_alpha;
1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio);
1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan++;
1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio);
1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan++;
1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio);
1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan += 2;
1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int col = 0; col < width; col ++) {
1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(*dest_scan), src_r, src_alpha));
1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan++;
1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(*dest_scan), src_g, src_alpha));
1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan++;
1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                *dest_scan = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(*dest_scan), src_b, src_alpha));
1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                dest_scan++;
1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (Bpp == 4) {
1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan++;
1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, int dest_left, int dest_top, int width, int height,
1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                const CFX_DIBSource* pSrcBitmap, int src_left, int src_top)
1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pBitmap == NULL) {
1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pBitmap->GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(), src_left, src_top, NULL);
1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (width == 0 || height == 0) {
1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int Bpp = pBitmap->GetBPP() / 8;
1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXDIB_Format dest_format = pBitmap->GetFormat();
1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FXDIB_Format src_format = pSrcBitmap->GetFormat();
1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int pitch = pBitmap->GetPitch();
1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE* buffer = pBitmap->GetBuffer();
1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dest_format == src_format) {
1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (int row = 0; row < height; row ++) {
1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_LPBYTE src_scan = (FX_LPBYTE)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Bpp == 4) {
1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col ++) {
1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0], src_scan[1], src_scan[2]));
1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 4;
1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_scan += 4;
1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col ++) {
1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[2];
1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[1];
1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[0];
1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_scan += 3;
1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int src_pitch = pSrcBitmap->GetPitch();
1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_ARGB* src_pal = pSrcBitmap->GetPalette();
1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_LPBYTE dest_buf = buffer + dest_top * pitch + dest_left * Bpp;
1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dest_format == FXDIB_Rgb) {
1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (src_format == FXDIB_Rgb32) {
1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int row = 0; row < height; row ++) {
1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_LPBYTE dest_scan = dest_buf + row * pitch;
1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_LPBYTE src_scan = (FX_BYTE*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col ++) {
1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[2];
1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[1];
1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    *dest_scan++ = src_scan[0];
1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_scan += 4;
1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ASSERT(FALSE);
1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) {
1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (src_format == FXDIB_Rgb) {
1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int row = 0; row < height; row ++) {
1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_BYTE* dest_scan = (FX_BYTE*)(dest_buf + row * pitch);
1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_LPBYTE src_scan = (FX_BYTE*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (src_format == FXDIB_Argb) {
1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    for (int col = 0; col < width; col ++) {
1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, FX_GAMMA(src_scan[0]), FX_GAMMA(src_scan[1]), FX_GAMMA(src_scan[2])));
1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 4;
1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_scan += 3;
1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                } else {
1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    for (int col = 0; col < width; col ++) {
1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2]));
1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        dest_scan += 4;
1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        src_scan += 3;
1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (src_format == FXDIB_Rgb32) {
1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ASSERT(dest_format == FXDIB_Argb);
1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (int row = 0; row < height; row ++) {
1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_LPBYTE dest_scan = dest_buf + row * pitch;
1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FX_LPBYTE src_scan = (FX_LPBYTE)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4);
1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (int col = 0; col < width; col++) {
1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], src_scan[2]));
1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    src_scan  += 4;
1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    dest_scan += 4;
1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ASSERT(FALSE);
1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_ARGB _DefaultCMYK2ARGB(FX_CMYK cmyk, FX_BYTE alpha)
1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BYTE r, g, b;
1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    AdobeCMYK_to_sRGB1(FXSYS_GetCValue(cmyk), FXSYS_GetMValue(cmyk), FXSYS_GetYValue(cmyk), FXSYS_GetKValue(cmyk),
1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                       r, g, b);
1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ArgbEncode(alpha, r, g, b);
1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL _DibSetPixel(CFX_DIBitmap* pDevice, int x, int y, FX_DWORD color, int alpha_flag, void* pIccTransform)
1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL bObjCMYK = FXGETFLAG_COLORTYPE(alpha_flag);
1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int alpha = bObjCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pIccTransform) {
1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&color, (FX_LPBYTE)&color, 1);
1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        color = bObjCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pDevice->IsCmykImage()) {
1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            color = (color & 0xffffff) | (alpha << 24);
1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (pDevice->IsCmykImage()) {
1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!bObjCMYK) {
1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (bObjCMYK) {
1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                color = _DefaultCMYK2ARGB(color, alpha);
1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pDevice->SetPixel(x, y, color);
1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pDevice->m_pAlphaMask) {
1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pDevice->m_pAlphaMask->SetPixel(x, y, alpha << 24);
1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::SetPixel(int x, int y, FX_DWORD color, int alpha_flag, void* pIccTransform)
1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pIccTransform = NULL;
1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn == NULL) {
1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return _DibSetPixel(m_pBitmap, x, y, color, alpha_flag, pIccTransform);
1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else if (m_pClipRgn->GetBox().Contains(x, y)) {
1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_bRgbByteOrder) {
1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                RgbByteOrderSetPixel(m_pBitmap, x, y, color);
1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return _DibSetPixel(m_pBitmap, x, y, color, alpha_flag, pIccTransform);
1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else if (m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) {
1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            const CFX_DIBitmap* pMask = m_pClipRgn->GetMask();
1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FX_BOOL bCMYK = FXGETFLAG_COLORTYPE(alpha_flag);
1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int new_alpha = bCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            new_alpha = new_alpha * pMask->GetScanline(y)[x] / 255;
1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (m_bRgbByteOrder) {
1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                RgbByteOrderSetPixel(m_pBitmap, x, y, (color & 0xffffff) | (new_alpha << 24));
1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return TRUE;
1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (bCMYK) {
1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FXSETFLAG_ALPHA_FILL(alpha_flag, new_alpha);
1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            } else {
1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                color = (color & 0xffffff) | (new_alpha << 24);
1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return _DibSetPixel(m_pBitmap, x, y, color, alpha_flag, pIccTransform);
1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::FillRect(const FX_RECT* pRect, FX_DWORD fill_color, int alpha_flag, void* pIccTransform, int blend_type)
1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (blend_type != FXDIB_BLEND_NORMAL) {
1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT clip_rect;
1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    GetClipBox(&clip_rect);
1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT draw_rect = clip_rect;
1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pRect) {
1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        draw_rect.Intersect(*pRect);
1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (draw_rect.IsEmpty()) {
1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn == NULL || m_pClipRgn->GetType() == CFX_ClipRgn::RectI) {
1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            RgbByteOrderCompositeRect(m_pBitmap, draw_rect.left, draw_rect.top, draw_rect.Width(), draw_rect.Height(), fill_color);
1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            m_pBitmap->CompositeRect(draw_rect.left, draw_rect.top, draw_rect.Width(), draw_rect.Height(), fill_color, alpha_flag, pIccTransform);
1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_pBitmap->CompositeMask(draw_rect.left, draw_rect.top, draw_rect.Width(), draw_rect.Height(), (const CFX_DIBitmap*)m_pClipRgn->GetMask(),
1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             fill_color, draw_rect.left - clip_rect.left, draw_rect.top - clip_rect.top, FXDIB_BLEND_NORMAL, NULL, m_bRgbByteOrder, alpha_flag, pIccTransform);
1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_AggDeviceDriver::GetClipBox(FX_RECT* pRect)
1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pClipRgn == NULL) {
1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pRect->left = pRect->top = 0;
1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pRect->right = GetDeviceCaps(FXDC_PIXEL_WIDTH);
1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pRect->bottom = GetDeviceCaps(FXDC_PIXEL_HEIGHT);
1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *pRect = m_pClipRgn->GetBox();
1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top, void* pIccTransform, FX_BOOL bDEdge)
1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (bDEdge) {
1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (m_bRgbByteOrder) {
1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            RgbByteOrderTransferBitmap(pBitmap, 0, 0, pBitmap->GetWidth(), pBitmap->GetHeight(), m_pBitmap, left, top);
1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        } else {
1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return pBitmap->TransferBitmap(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight(), m_pBitmap, left, top, pIccTransform);
1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT rect(left, top, left + pBitmap->GetWidth(), top + pBitmap->GetHeight());
1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap *pBack = NULL;
1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pOriDevice) {
1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pBack = m_pOriDevice->Clone(&rect);
1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!pBack) {
1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return TRUE;
1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(), m_pBitmap, 0, 0);
1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        pBack = m_pBitmap->Clone(&rect);
1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pBack) {
1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_BOOL bRet = TRUE;
1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    left = left >= 0 ? 0 : left;
1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    top = top >= 0 ? 0 : top;
1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_bRgbByteOrder) {
1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), pBack, left, top);
1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack, left, top, pIccTransform);
1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    delete pBack;
1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return bRet;
1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, FX_DWORD argb, const FX_RECT* pSrcRect, int left, int top, int blend_type,
1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                       int alpha_flag, void* pIccTransform)
1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pBitmap->IsAlphaMask())
1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return m_pBitmap->CompositeMask(left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                        pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn, m_bRgbByteOrder, alpha_flag, pIccTransform);
1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return m_pBitmap->CompositeBitmap(left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap,
1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                      pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn, m_bRgbByteOrder, pIccTransform);
1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, FX_DWORD argb, int dest_left, int dest_top,
1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int dest_width, int dest_height, const FX_RECT* pClipRect, FX_DWORD flags,
1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int alpha_flag, void* pIccTransform, int blend_type)
1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (dest_width == pSource->GetWidth() && dest_height == pSource->GetHeight()) {
1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FX_RECT rect(0, 0, dest_width, dest_height);
1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type, alpha_flag, pIccTransform);
1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width, dest_top + dest_height);
1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dest_rect.Normalize();
1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FX_RECT dest_clip = dest_rect;
1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dest_clip.Intersect(*pClipRect);
1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_BitmapComposer composer;
1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    composer.Compose(m_pBitmap, m_pClipRgn, 255, argb, dest_clip, FALSE, FALSE, FALSE, m_bRgbByteOrder, alpha_flag, pIccTransform, blend_type);
1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    dest_clip.Offset(-dest_rect.left, -dest_rect.top);
1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ImageStretcher stretcher;
1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (stretcher.Start(&composer, pSource, dest_width, dest_height, dest_clip, flags)) {
1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        stretcher.Continue(NULL);
1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, int bitmap_alpha, FX_DWORD argb,
1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        const CFX_AffineMatrix* pMatrix, FX_DWORD render_flags, FX_LPVOID& handle,
1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        int alpha_flag, void* pIccTransform, int blend_type)
1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_ImageRenderer* pRenderer = FX_NEW CFX_ImageRenderer;
1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pRenderer) {
1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pRenderer->Start(m_pBitmap, m_pClipRgn, pSource, bitmap_alpha, argb, pMatrix, render_flags, m_bRgbByteOrder, alpha_flag, pIccTransform);
1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    handle = pRenderer;
1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL	CFX_AggDeviceDriver::ContinueDIBits(FX_LPVOID pHandle, IFX_Pause* pPause)
1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ((CFX_ImageRenderer*)pHandle)->Continue(pPause);
1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CFX_AggDeviceDriver::CancelDIBits(FX_LPVOID pHandle)
1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_pBitmap->GetBuffer() == NULL) {
1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return;
1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    delete (CFX_ImageRenderer*)pHandle;
1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_FxgeDevice::CFX_FxgeDevice()
1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bOwnedBitmap = FALSE;
1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, int dither_bits, FX_BOOL bRgbByteOrder, CFX_DIBitmap* pOriDevice, FX_BOOL bGroupKnockout)
1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pBitmap == NULL) {
1599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetBitmap(pBitmap);
1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    IFX_RenderDeviceDriver* pDriver = FX_NEW CFX_AggDeviceDriver(pBitmap, dither_bits, bRgbByteOrder, pOriDevice, bGroupKnockout);
1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pDriver) {
1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetDeviceDriver(pDriver);
1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovFX_BOOL CFX_FxgeDevice::Create(int width, int height, FXDIB_Format format, int dither_bits, CFX_DIBitmap* pOriDevice)
1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    m_bOwnedBitmap = TRUE;
1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap;
1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pBitmap) {
1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pBitmap->Create(width, height, format)) {
1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete pBitmap;
1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetBitmap(pBitmap);
1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    IFX_RenderDeviceDriver* pDriver = FX_NEW CFX_AggDeviceDriver(pBitmap, dither_bits, FALSE, pOriDevice, FALSE);
1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!pDriver) {
1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SetDeviceDriver(pDriver);
1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovCFX_FxgeDevice::~CFX_FxgeDevice()
1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m_bOwnedBitmap && GetBitmap()) {
1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        delete GetBitmap();
1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1634