1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "render_int.h"
8ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
9ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "core/include/fpdfapi/fpdf_pageobj.h"
10ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "core/include/fpdfapi/fpdf_render.h"
11ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "core/include/fxge/fx_ge.h"
12ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#include "core/src/fpdfapi/fpdf_page/pageint.h"
13ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define SHADING_STEPS 256
15ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawAxialShading(CFX_DIBitmap* pBitmap,
16ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             CFX_Matrix* pObject2Bitmap,
17ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             CPDF_Dictionary* pDict,
18ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             CPDF_Function** pFuncs,
19ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             int nFuncs,
20ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             CPDF_ColorSpace* pCS,
21ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             int alpha) {
22ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
23ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pCoords = pDict->GetArray("Coords");
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pCoords) {
25ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
26ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
27ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT start_x = pCoords->GetNumber(0);
28ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT start_y = pCoords->GetNumber(1);
29ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT end_x = pCoords->GetNumber(2);
30ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT end_y = pCoords->GetNumber(3);
31ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT t_min = 0, t_max = 1.0f;
32ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pArray = pDict->GetArray("Domain");
33ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pArray) {
34ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    t_min = pArray->GetNumber(0);
35ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    t_max = pArray->GetNumber(1);
36ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
37ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
38ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pArray = pDict->GetArray("Extend");
39ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pArray) {
40ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    bStartExtend = pArray->GetInteger(0);
41ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    bEndExtend = pArray->GetInteger(1);
42ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
43ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int width = pBitmap->GetWidth();
44ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int height = pBitmap->GetHeight();
45ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT x_span = end_x - start_x;
46ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT y_span = end_y - start_y;
47ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT axis_len_square =
48ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span);
49ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix matrix;
50ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.SetReverse(*pObject2Bitmap);
51ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int total_results = 0;
52ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int j = 0; j < nFuncs; j++) {
53ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pFuncs[j]) {
54ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      total_results += pFuncs[j]->CountOutputs();
55ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
57ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pCS->CountComponents() > total_results) {
58ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    total_results = pCS->CountComponents();
59ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
60ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
61ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT* pResults = result_array;
62ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT));
63ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD rgb_array[SHADING_STEPS];
64ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < SHADING_STEPS; i++) {
65ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
66ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int offset = 0;
67ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int j = 0; j < nFuncs; j++) {
68ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (pFuncs[j]) {
69ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        int nresults = 0;
70ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
71ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          offset += nresults;
72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
73ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
74ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
75ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
76ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCS->GetRGB(pResults, R, G, B);
77ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rgb_array[i] =
78ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255),
79ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                 FXSYS_round(G * 255), FXSYS_round(B * 255)));
80ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
81ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pitch = pBitmap->GetPitch();
82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < height; row++) {
83ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
84ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int column = 0; column < width; column++) {
85ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
86ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.Transform(x, y);
87ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT scale = FXSYS_Div(
88ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span),
89ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          axis_len_square);
90ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int index = (int32_t)(scale * (SHADING_STEPS - 1));
91ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (index < 0) {
92ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (!bStartExtend) {
93ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
95ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        index = 0;
96ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else if (index >= SHADING_STEPS) {
97ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (!bEndExtend) {
98ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
100ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        index = SHADING_STEPS - 1;
101ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dib_buf[column] = rgb_array[index];
103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
104ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
106ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawRadialShading(CFX_DIBitmap* pBitmap,
107ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              CFX_Matrix* pObject2Bitmap,
108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              CPDF_Dictionary* pDict,
109ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              CPDF_Function** pFuncs,
110ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              int nFuncs,
111ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              CPDF_ColorSpace* pCS,
112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              int alpha) {
113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
114ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pCoords = pDict->GetArray("Coords");
115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pCoords) {
116ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
117ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT start_x = pCoords->GetNumber(0);
119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT start_y = pCoords->GetNumber(1);
120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT start_r = pCoords->GetNumber(2);
121ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT end_x = pCoords->GetNumber(3);
122ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT end_y = pCoords->GetNumber(4);
123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT end_r = pCoords->GetNumber(5);
124ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix matrix;
125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.SetReverse(*pObject2Bitmap);
126ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT t_min = 0, t_max = 1.0f;
127ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pArray = pDict->GetArray("Domain");
128ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pArray) {
129ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    t_min = pArray->GetNumber(0);
130ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    t_max = pArray->GetNumber(1);
131ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
132ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bStartExtend = FALSE, bEndExtend = FALSE;
133ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pArray = pDict->GetArray("Extend");
134ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pArray) {
135ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    bStartExtend = pArray->GetInteger(0);
136ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    bEndExtend = pArray->GetInteger(1);
137ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
138ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int total_results = 0;
139ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int j = 0; j < nFuncs; j++) {
140ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pFuncs[j]) {
141ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      total_results += pFuncs[j]->CountOutputs();
142ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
143ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
144ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pCS->CountComponents() > total_results) {
145ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    total_results = pCS->CountComponents();
146ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
147ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
148ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT* pResults = result_array;
149ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT));
150ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD rgb_array[SHADING_STEPS];
151ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < SHADING_STEPS; i++) {
152ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT input = (t_max - t_min) * i / SHADING_STEPS + t_min;
153ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int offset = 0;
154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int j = 0; j < nFuncs; j++) {
155ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (pFuncs[j]) {
156ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        int nresults;
157ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pFuncs[j]->Call(&input, 1, pResults + offset, nresults)) {
158ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          offset += nresults;
159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
160ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
161ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
162ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
163ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pCS->GetRGB(pResults, R, G, B);
164ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rgb_array[i] =
165ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255),
166ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                 FXSYS_round(G * 255), FXSYS_round(B * 255)));
167ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
168ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) +
169ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               FXSYS_Mul(start_y - end_y, start_y - end_y) -
170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann               FXSYS_Mul(start_r - end_r, start_r - end_r);
171ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int width = pBitmap->GetWidth();
172ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int height = pBitmap->GetHeight();
173ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pitch = pBitmap->GetPitch();
174ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bDecreasing = FALSE;
175ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (start_r > end_r) {
176ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int length = (int)FXSYS_sqrt((FXSYS_Mul(start_x - end_x, start_x - end_x) +
177ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                  FXSYS_Mul(start_y - end_y, start_y - end_y)));
178ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (length < start_r - end_r) {
179ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      bDecreasing = TRUE;
180ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
181ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
182ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < height; row++) {
183ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
184ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int column = 0; column < width; column++) {
185ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
186ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.Transform(x, y);
187ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) +
188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         FXSYS_Mul(y - start_y, end_y - start_y) +
189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         FXSYS_Mul(start_r, end_r - start_r));
190ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) +
191ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   FXSYS_Mul(y - start_y, y - start_y) -
192ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   FXSYS_Mul(start_r, start_r);
193ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT s;
194ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (a == 0) {
195ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        s = FXSYS_Div(-c, b);
196ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
197ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c);
198ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (b2_4ac < 0) {
199ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
201ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT root = FXSYS_sqrt(b2_4ac);
202ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT s1, s2;
203ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (a > 0) {
204ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          s1 = FXSYS_Div(-b - root, 2 * a);
205ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          s2 = FXSYS_Div(-b + root, 2 * a);
206ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        } else {
207ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          s2 = FXSYS_Div(-b - root, 2 * a);
208ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          s1 = FXSYS_Div(-b + root, 2 * a);
209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
210ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (bDecreasing) {
211ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (s1 >= 0 || bStartExtend) {
212ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            s = s1;
213ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          } else {
214ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            s = s2;
215ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
216ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        } else {
217ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (s2 <= 1.0f || bEndExtend) {
218ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            s = s2;
219ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          } else {
220ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            s = s1;
221ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
223ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if ((start_r + s * (end_r - start_r)) < 0) {
224ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
226ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
227ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int index = (int32_t)(s * (SHADING_STEPS - 1));
228ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (index < 0) {
229ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (!bStartExtend) {
230ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
232ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        index = 0;
233ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
234ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (index >= SHADING_STEPS) {
235ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (!bEndExtend) {
236ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
238ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        index = SHADING_STEPS - 1;
239ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
240ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dib_buf[column] = rgb_array[index];
241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
242ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
244ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawFuncShading(CFX_DIBitmap* pBitmap,
245ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            CFX_Matrix* pObject2Bitmap,
246ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            CPDF_Dictionary* pDict,
247ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            CPDF_Function** pFuncs,
248ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            int nFuncs,
249ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            CPDF_ColorSpace* pCS,
250ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                            int alpha) {
251ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
252ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Array* pDomain = pDict->GetArray("Domain");
253ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT xmin = 0, ymin = 0, xmax = 1.0f, ymax = 1.0f;
254ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pDomain) {
255ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    xmin = pDomain->GetNumber(0);
256ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    xmax = pDomain->GetNumber(1);
257ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    ymin = pDomain->GetNumber(2);
258ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    ymax = pDomain->GetNumber(3);
259ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
260ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix mtDomain2Target = pDict->GetMatrix("Matrix");
261ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix matrix, reverse_matrix;
262ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.SetReverse(*pObject2Bitmap);
263ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  reverse_matrix.SetReverse(mtDomain2Target);
264ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.Concat(reverse_matrix);
265ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int width = pBitmap->GetWidth();
266ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int height = pBitmap->GetHeight();
267ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int pitch = pBitmap->GetPitch();
268ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int total_results = 0;
269ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int j = 0; j < nFuncs; j++) {
270ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pFuncs[j]) {
271ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      total_results += pFuncs[j]->CountOutputs();
272ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
273ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
274ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pCS->CountComponents() > total_results) {
275ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    total_results = pCS->CountComponents();
276ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
277ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FixedBufGrow<FX_FLOAT, 16> result_array(total_results);
278ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT* pResults = result_array;
279ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memset(pResults, 0, total_results * sizeof(FX_FLOAT));
280ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int row = 0; row < height; row++) {
281ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD* dib_buf = (FX_DWORD*)(pBitmap->GetBuffer() + row * pitch);
282ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int column = 0; column < width; column++) {
283ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT x = (FX_FLOAT)column, y = (FX_FLOAT)row;
284ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      matrix.Transform(x, y);
285ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (x < xmin || x > xmax || y < ymin || y > ymax) {
286ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        continue;
287ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
288ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT input[2];
289ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int offset = 0;
290ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      input[0] = x;
291ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      input[1] = y;
292ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int j = 0; j < nFuncs; j++) {
293ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pFuncs[j]) {
294ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          int nresults;
295ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          if (pFuncs[j]->Call(input, 2, pResults + offset, nresults)) {
296ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            offset += nresults;
297ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
299ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
300ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
301ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pCS->GetRGB(pResults, R, G, B);
302ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dib_buf[column] = FXARGB_TODIB(FXARGB_MAKE(
303ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          alpha, (int32_t)(R * 255), (int32_t)(G * 255), (int32_t)(B * 255)));
304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
305ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
307ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_BOOL _GetScanlineIntersect(int y,
308ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              FX_FLOAT x1,
309ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              FX_FLOAT y1,
310ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              FX_FLOAT x2,
311ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              FX_FLOAT y2,
312ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              FX_FLOAT& x) {
313ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (y1 == y2) {
314ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return FALSE;
315ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
316ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (y1 < y2) {
317ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (y < y1 || y > y2) {
318ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return FALSE;
319ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
320ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
321ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (y < y2 || y > y1) {
322ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return FALSE;
323ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
324ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
325ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  x = x1 + FXSYS_MulDiv(x2 - x1, y - y1, y2 - y1);
326ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return TRUE;
327ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
328ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawGouraud(CFX_DIBitmap* pBitmap,
329ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        int alpha,
330ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        CPDF_MeshVertex triangle[3]) {
331ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT min_y = triangle[0].y, max_y = triangle[0].y;
332ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 1; i < 3; i++) {
333ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (min_y > triangle[i].y) {
334ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      min_y = triangle[i].y;
335ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
336ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (max_y < triangle[i].y) {
337ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max_y = triangle[i].y;
338ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
339ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
340ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (min_y == max_y) {
341ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
342ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
343ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int min_yi = (int)FXSYS_floor(min_y), max_yi = (int)FXSYS_ceil(max_y);
344ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (min_yi < 0) {
345ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    min_yi = 0;
346ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
347ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (max_yi >= pBitmap->GetHeight()) {
348ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    max_yi = pBitmap->GetHeight() - 1;
349ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
350ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int y = min_yi; y <= max_yi; y++) {
351ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int nIntersects = 0;
352ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT inter_x[3], r[3], g[3], b[3];
353ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 0; i < 3; i++) {
354ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_MeshVertex& vertex1 = triangle[i];
355ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3];
356ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_BOOL bIntersect = _GetScanlineIntersect(
357ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          y, vertex1.x, vertex1.y, vertex2.x, vertex2.y, inter_x[nIntersects]);
358ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (!bIntersect) {
359ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        continue;
360ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
361ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      r[nIntersects] =
362ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          vertex1.r + FXSYS_MulDiv(vertex2.r - vertex1.r, y - vertex1.y,
363ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   vertex2.y - vertex1.y);
364ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      g[nIntersects] =
365ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          vertex1.g + FXSYS_MulDiv(vertex2.g - vertex1.g, y - vertex1.y,
366ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   vertex2.y - vertex1.y);
367ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      b[nIntersects] =
368ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          vertex1.b + FXSYS_MulDiv(vertex2.b - vertex1.b, y - vertex1.y,
369ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   vertex2.y - vertex1.y);
370ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      nIntersects++;
371ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
372ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (nIntersects != 2) {
373ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
374ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
375ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int min_x, max_x, start_index, end_index;
376ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (inter_x[0] < inter_x[1]) {
377ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      min_x = (int)FXSYS_floor(inter_x[0]);
378ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max_x = (int)FXSYS_ceil(inter_x[1]);
379ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      start_index = 0;
380ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      end_index = 1;
381ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
382ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      min_x = (int)FXSYS_floor(inter_x[1]);
383ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max_x = (int)FXSYS_ceil(inter_x[0]);
384ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      start_index = 1;
385ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      end_index = 0;
386ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
387ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int start_x = min_x, end_x = max_x;
388ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (start_x < 0) {
389ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      start_x = 0;
390ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
391ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (end_x > pBitmap->GetWidth()) {
392ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      end_x = pBitmap->GetWidth();
393ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
394ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t* dib_buf =
395ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4;
396ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT r_unit = (r[end_index] - r[start_index]) / (max_x - min_x);
397ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT g_unit = (g[end_index] - g[start_index]) / (max_x - min_x);
398ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT b_unit = (b[end_index] - b[start_index]) / (max_x - min_x);
399ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT R = r[start_index] + (start_x - min_x) * r_unit;
400ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT G = g[start_index] + (start_x - min_x) * g_unit;
401ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_FLOAT B = b[start_index] + (start_x - min_x) * b_unit;
402ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int x = start_x; x < end_x; x++) {
403ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      R += r_unit;
404ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      G += g_unit;
405ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      B += b_unit;
406ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXARGB_SETDIB(dib_buf,
407ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                    FXARGB_MAKE(alpha, (int32_t)(R * 255), (int32_t)(G * 255),
408ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                (int32_t)(B * 255)));
409ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dib_buf += 4;
410ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
411ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
412ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
413ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawFreeGouraudShading(CFX_DIBitmap* pBitmap,
414ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   CFX_Matrix* pObject2Bitmap,
415ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   CPDF_Stream* pShadingStream,
416ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   CPDF_Function** pFuncs,
417ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   int nFuncs,
418ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   CPDF_ColorSpace* pCS,
419ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                   int alpha) {
420ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
422ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_MeshStream stream;
423ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS))
424ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
425ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
426ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_MeshVertex triangle[3];
427ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FXSYS_memset(triangle, 0, sizeof(triangle));
428ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
429ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (!stream.m_BitStream.IsEOF()) {
430ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_MeshVertex vertex;
431ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD flag = stream.GetVertex(vertex, pObject2Bitmap);
432ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (flag == 0) {
433ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[0] = vertex;
434ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int j = 1; j < 3; j++) {
435ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        stream.GetVertex(triangle[j], pObject2Bitmap);
436ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
437ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
438ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (flag == 1) {
439ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        triangle[0] = triangle[1];
440ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
441ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[1] = triangle[2];
442ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[2] = vertex;
443ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
444ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    DrawGouraud(pBitmap, alpha, triangle);
445ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
447ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawLatticeGouraudShading(CFX_DIBitmap* pBitmap,
448ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      CFX_Matrix* pObject2Bitmap,
449ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      CPDF_Stream* pShadingStream,
450ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      CPDF_Function** pFuncs,
451ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      int nFuncs,
452ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      CPDF_ColorSpace* pCS,
453ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      int alpha) {
454ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
455ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
456ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int row_verts = pShadingStream->GetDict()->GetInteger("VerticesPerRow");
457ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (row_verts < 2)
458ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
459ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
460ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_MeshStream stream;
461ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS))
462ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
463ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
464ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_MeshVertex* vertex = FX_Alloc2D(CPDF_MeshVertex, row_verts, 2);
465ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!stream.GetVertexRow(vertex, row_verts, pObject2Bitmap)) {
466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_Free(vertex);
467ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
468ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
469ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int last_index = 0;
470ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
471ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_MeshVertex* last_row = vertex + last_index * row_verts;
472ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_MeshVertex* this_row = vertex + (1 - last_index) * row_verts;
473ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!stream.GetVertexRow(this_row, row_verts, pObject2Bitmap)) {
474ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_Free(vertex);
475ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
476ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
477ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_MeshVertex triangle[3];
478ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 1; i < row_verts; i++) {
479ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[0] = last_row[i];
480ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[1] = this_row[i - 1];
481ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[2] = last_row[i - 1];
482ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawGouraud(pBitmap, alpha, triangle);
483ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      triangle[2] = this_row[i];
484ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawGouraud(pBitmap, alpha, triangle);
485ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
486ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    last_index = 1 - last_index;
487ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
488ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(vertex);
489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstruct Coon_BezierCoeff {
491ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  float a, b, c, d;
492ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void FromPoints(float p0, float p1, float p2, float p3) {
493ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    a = -p0 + 3 * p1 - 3 * p2 + p3;
494ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    b = 3 * p0 - 6 * p1 + 3 * p2;
495ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    c = -3 * p0 + 3 * p1;
496ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    d = p0;
497ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
498ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_BezierCoeff first_half() {
499ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_BezierCoeff result;
500ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.a = a / 8;
501ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.b = b / 4;
502ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.c = c / 2;
503ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.d = d;
504ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return result;
505ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
506ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_BezierCoeff second_half() {
507ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_BezierCoeff result;
508ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.a = a / 8;
509ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.b = 3 * a / 8 + b / 4;
510ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.c = 3 * a / 8 + b / 2 + c / 2;
511ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.d = a / 8 + b / 4 + c / 2 + d;
512ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return result;
513ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
514ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void GetPoints(float p[4]) {
515ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[0] = d;
516ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[1] = c / 3 + p[0];
517ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[2] = b / 3 - p[0] + 2 * p[1];
518ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[3] = a + p[0] - 3 * p[1] + 3 * p[2];
519ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
520ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void GetPointsReverse(float p[4]) {
521ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[3] = d;
522ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[2] = c / 3 + p[3];
523ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[1] = b / 3 - p[3] + 2 * p[2];
524ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p[0] = a + p[3] - 3 * p[2] + 3 * p[1];
525ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
526ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void BezierInterpol(Coon_BezierCoeff& C1,
527ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_BezierCoeff& C2,
528ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_BezierCoeff& D1,
529ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_BezierCoeff& D2) {
530ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    a = (D1.a + D2.a) / 2;
531ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    b = (D1.b + D2.b) / 2;
532ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    c = (D1.c + D2.c) / 2 - (C1.a / 8 + C1.b / 4 + C1.c / 2) +
533ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        (C2.a / 8 + C2.b / 4) + (-C1.d + D2.d) / 2 - (C2.a + C2.b) / 2;
534ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    d = C1.a / 8 + C1.b / 4 + C1.c / 2 + C1.d;
535ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
536ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  float Distance() {
537ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    float dis = a + b + c;
538ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return dis < 0 ? -dis : dis;
539ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
540e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
541e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstruct Coon_Bezier {
542ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_BezierCoeff x, y;
543ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void FromPoints(float x0,
544ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float y0,
545ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float x1,
546ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float y1,
547ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float x2,
548ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float y2,
549ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float x3,
550ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  float y3) {
551ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    x.FromPoints(x0, x1, x2, x3);
552ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    y.FromPoints(y0, y1, y2, y3);
553ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
554ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_Bezier first_half() {
555ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_Bezier result;
556ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.x = x.first_half();
557ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.y = y.first_half();
558ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return result;
559ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
560ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_Bezier second_half() {
561ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_Bezier result;
562ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.x = x.second_half();
563ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    result.y = y.second_half();
564ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return result;
565ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
566ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void BezierInterpol(Coon_Bezier& C1,
567ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_Bezier& C2,
568ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_Bezier& D1,
569ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      Coon_Bezier& D2) {
570ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    x.BezierInterpol(C1.x, C2.x, D1.x, D2.x);
571ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    y.BezierInterpol(C1.y, C2.y, D1.y, D2.y);
572ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
573ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void GetPoints(FX_PATHPOINT* pPoints) {
574ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    float p[4];
575ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int i;
576ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    x.GetPoints(p);
577ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = 0; i < 4; i++) {
578ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPoints[i].m_PointX = p[i];
579ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
580ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    y.GetPoints(p);
581ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = 0; i < 4; i++) {
582ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPoints[i].m_PointY = p[i];
583ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
584ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
585ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void GetPointsReverse(FX_PATHPOINT* pPoints) {
586ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    float p[4];
587ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int i;
588ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    x.GetPointsReverse(p);
589ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = 0; i < 4; i++) {
590ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPoints[i].m_PointX = p[i];
591ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
592ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    y.GetPointsReverse(p);
593ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = 0; i < 4; i++) {
594ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPoints[i].m_PointY = p[i];
595ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
596ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
597ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  float Distance() { return x.Distance() + y.Distance(); }
598e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
599ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic int _BiInterpol(int c0,
600ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int c1,
601ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int c2,
602ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int c3,
603ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int x,
604ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int y,
605ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int x_scale,
606ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       int y_scale) {
607ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int x1 = c0 + (c3 - c0) * x / x_scale;
608ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int x2 = c1 + (c2 - c1) * x / x_scale;
609ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return x1 + (x2 - x1) * y / y_scale;
610e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstruct Coon_Color {
612ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_Color() { FXSYS_memset(comp, 0, sizeof(int) * 3); }
613ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int comp[3];
614ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void BiInterpol(Coon_Color colors[4],
615ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  int x,
616ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  int y,
617ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  int x_scale,
618ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  int y_scale) {
619ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int i = 0; i < 3; i++)
620ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      comp[i] =
621ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          _BiInterpol(colors[0].comp[i], colors[1].comp[i], colors[2].comp[i],
622ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      colors[3].comp[i], x, y, x_scale, y_scale);
623ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
624ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int Distance(Coon_Color& o) {
625ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int max, diff;
626ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    max = FXSYS_abs(comp[0] - o.comp[0]);
627ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    diff = FXSYS_abs(comp[1] - o.comp[1]);
628ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (max < diff) {
629ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max = diff;
630ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
631ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    diff = FXSYS_abs(comp[2] - o.comp[2]);
632ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (max < diff) {
633ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max = diff;
634ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
635ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return max;
636ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
637e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
638e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstruct CPDF_PatchDrawer {
639ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  Coon_Color patch_colors[4];
640ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int max_delta;
641ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_PathData path;
642ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_RenderDevice* pDevice;
643ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int fill_mode;
644ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int alpha;
645ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  void Draw(int x_scale,
646ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            int y_scale,
647ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            int left,
648ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            int bottom,
649ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            Coon_Bezier C1,
650ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            Coon_Bezier C2,
651ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            Coon_Bezier D1,
652ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            Coon_Bezier D2) {
653ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_BOOL bSmall = C1.Distance() < 2 && C2.Distance() < 2 &&
654ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     D1.Distance() < 2 && D2.Distance() < 2;
655ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_Color div_colors[4];
656ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int d_bottom, d_left, d_top, d_right;
657ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale);
658ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!bSmall) {
659ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale,
660ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                               y_scale);
661ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale,
662ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                               y_scale);
663ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale,
664ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                               y_scale);
665ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      d_bottom = div_colors[3].Distance(div_colors[0]);
666ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      d_left = div_colors[1].Distance(div_colors[0]);
667ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      d_top = div_colors[1].Distance(div_colors[2]);
668ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      d_right = div_colors[2].Distance(div_colors[3]);
669e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
670ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann#define COONCOLOR_THRESHOLD 4
671ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (bSmall ||
672ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        (d_bottom < COONCOLOR_THRESHOLD && d_left < COONCOLOR_THRESHOLD &&
673ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann         d_top < COONCOLOR_THRESHOLD && d_right < COONCOLOR_THRESHOLD)) {
674ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_PATHPOINT* pPoints = path.GetPoints();
675ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      C1.GetPoints(pPoints);
676ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      D2.GetPoints(pPoints + 3);
677ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      C2.GetPointsReverse(pPoints + 6);
678ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      D1.GetPointsReverse(pPoints + 9);
679ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int fillFlags = FXFILL_WINDING | FXFILL_FULLCOVER;
680ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (fill_mode & RENDER_NOPATHSMOOTH) {
681ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        fillFlags |= FXFILL_NOPATHSMOOTH;
682ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
683ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pDevice->DrawPath(
684ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          &path, NULL, NULL,
685ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FXARGB_MAKE(alpha, div_colors[0].comp[0], div_colors[0].comp[1],
686ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      div_colors[0].comp[2]),
687ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          0, fillFlags);
688ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
689ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (d_bottom < COONCOLOR_THRESHOLD && d_top < COONCOLOR_THRESHOLD) {
690ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m1;
691ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m1.BezierInterpol(D1, D2, C1, C2);
692ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        y_scale *= 2;
693ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        bottom *= 2;
694ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left, bottom, C1, m1, D1.first_half(),
695ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D2.first_half());
696ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left, bottom + 1, m1, C2, D1.second_half(),
697ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D2.second_half());
698ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else if (d_left < COONCOLOR_THRESHOLD &&
699ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                 d_right < COONCOLOR_THRESHOLD) {
700ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m2;
701ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m2.BezierInterpol(C1, C2, D1, D2);
702ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        x_scale *= 2;
703ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        left *= 2;
704ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left, bottom, C1.first_half(), C2.first_half(),
705ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D1, m2);
706ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(),
707ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             C2.second_half(), m2, D2);
708ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
709ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m1, m2;
710ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m1.BezierInterpol(D1, D2, C1, C2);
711ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m2.BezierInterpol(C1, C2, D1, D2);
712ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m1f = m1.first_half();
713ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m1s = m1.second_half();
714ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m2f = m2.first_half();
715ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Coon_Bezier m2s = m2.second_half();
716ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        x_scale *= 2;
717ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        y_scale *= 2;
718ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        left *= 2;
719ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        bottom *= 2;
720ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left, bottom, C1.first_half(), m1f,
721ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D1.first_half(), m2f);
722ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left, bottom + 1, m1f, C2.first_half(),
723ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D1.second_half(), m2s);
724ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left + 1, bottom, C1.second_half(), m1s, m2f,
725ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D2.first_half());
726ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        Draw(x_scale, y_scale, left + 1, bottom + 1, m1s, C2.second_half(), m2s,
727ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann             D2.second_half());
728ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
729ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
730ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
731e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
732e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
733ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_BOOL _CheckCoonTensorPara(const CPDF_MeshStream& stream) {
734ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bCoorBits = (stream.m_nCoordBits == 1 || stream.m_nCoordBits == 2 ||
735ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nCoordBits == 4 || stream.m_nCoordBits == 8 ||
736ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nCoordBits == 12 || stream.m_nCoordBits == 16 ||
737ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nCoordBits == 24 || stream.m_nCoordBits == 32);
738e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
739ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bCompBits = (stream.m_nCompBits == 1 || stream.m_nCompBits == 2 ||
740ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nCompBits == 4 || stream.m_nCompBits == 8 ||
741ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nCompBits == 12 || stream.m_nCompBits == 16);
742e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
743ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bFlagBits = (stream.m_nFlagBits == 2 || stream.m_nFlagBits == 4 ||
744ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       stream.m_nFlagBits == 8);
745e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
746ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return bCoorBits && bCompBits && bFlagBits;
747e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
748e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
749ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic void DrawCoonPatchMeshes(FX_BOOL bTensor,
750ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                CFX_DIBitmap* pBitmap,
751ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                CFX_Matrix* pObject2Bitmap,
752ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                CPDF_Stream* pShadingStream,
753ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                CPDF_Function** pFuncs,
754ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                int nFuncs,
755ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                CPDF_ColorSpace* pCS,
756ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                int fill_mode,
757ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                int alpha) {
758ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ASSERT(pBitmap->GetFormat() == FXDIB_Argb);
759e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
760ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FxgeDevice device;
761ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  device.Attach(pBitmap);
762ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_MeshStream stream;
763ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!stream.Load(pShadingStream, pFuncs, nFuncs, pCS))
764ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
765ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!_CheckCoonTensorPara(stream))
766ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
767e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
768ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_PatchDrawer patch;
769ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  patch.alpha = alpha;
770ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  patch.pDevice = &device;
771ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  patch.fill_mode = fill_mode;
772ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  patch.path.SetPointCount(13);
773ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_PATHPOINT* pPoints = patch.path.GetPoints();
774ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPoints[0].m_Flag = FXPT_MOVETO;
775ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 1; i < 13; i++) {
776ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPoints[i].m_Flag = FXPT_BEZIERTO;
777ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
778ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FloatPoint coords[16];
779ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < 16; i++) {
780ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    coords[i].Set(0.0f, 0.0f);
781ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
782ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
783ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int point_count = bTensor ? 16 : 12;
784ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (!stream.m_BitStream.IsEOF()) {
785ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_DWORD flag = stream.GetFlag();
786ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int iStartPoint = 0, iStartColor = 0, i = 0;
787ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (flag) {
788ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      iStartPoint = 4;
789ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      iStartColor = 2;
790ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CFX_FloatPoint tempCoords[4];
791ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (i = 0; i < 4; i++) {
792ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        tempCoords[i] = coords[(flag * 3 + i) % 12];
793ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
794ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_memcpy(coords, tempCoords, sizeof(CFX_FloatPoint) * 4);
795ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      Coon_Color tempColors[2];
796ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      tempColors[0] = patch.patch_colors[flag];
797ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      tempColors[1] = patch.patch_colors[(flag + 1) % 4];
798ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_memcpy(patch.patch_colors, tempColors, sizeof(Coon_Color) * 2);
799ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
800ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = iStartPoint; i < point_count; i++) {
801ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      stream.GetCoords(coords[i].x, coords[i].y);
802ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pObject2Bitmap->Transform(coords[i].x, coords[i].y);
803ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
804ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (i = iStartColor; i < 4; i++) {
805ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT r = 0.0f, g = 0.0f, b = 0.0f;
806ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      stream.GetColor(r, g, b);
807ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      patch.patch_colors[i].comp[0] = (int32_t)(r * 255);
808ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      patch.patch_colors[i].comp[1] = (int32_t)(g * 255);
809ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      patch.patch_colors[i].comp[2] = (int32_t)(b * 255);
810ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
811ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_FloatRect bbox = CFX_FloatRect::GetBBox(coords, point_count);
812ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (bbox.right <= 0 || bbox.left >= (FX_FLOAT)pBitmap->GetWidth() ||
813ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        bbox.top <= 0 || bbox.bottom >= (FX_FLOAT)pBitmap->GetHeight()) {
814ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      continue;
815ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
816ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    Coon_Bezier C1, C2, D1, D2;
817ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    C1.FromPoints(coords[0].x, coords[0].y, coords[11].x, coords[11].y,
818ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  coords[10].x, coords[10].y, coords[9].x, coords[9].y);
819ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    C2.FromPoints(coords[3].x, coords[3].y, coords[4].x, coords[4].y,
820ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  coords[5].x, coords[5].y, coords[6].x, coords[6].y);
821ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    D1.FromPoints(coords[0].x, coords[0].y, coords[1].x, coords[1].y,
822ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  coords[2].x, coords[2].y, coords[3].x, coords[3].y);
823ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    D2.FromPoints(coords[9].x, coords[9].y, coords[8].x, coords[8].y,
824ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                  coords[7].x, coords[7].y, coords[6].x, coords[6].y);
825ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    patch.Draw(1, 1, 0, 0, C1, C2, D1, D2);
826ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
827e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
828ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern,
829ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                    CFX_Matrix* pMatrix,
830ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                    FX_RECT& clip_rect,
831ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                    int alpha,
832ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                    FX_BOOL bAlphaMode) {
833ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Function** pFuncs = pPattern->m_pFunctions;
834ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int nFuncs = pPattern->m_nFuncs;
835ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Dictionary* pDict = pPattern->m_pShadingObj->GetDict();
836ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_ColorSpace* pColorSpace = pPattern->m_pCS;
837ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pColorSpace) {
838ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
839ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
840ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_ARGB background = 0;
841ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pPattern->m_bShadingObj &&
842ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPattern->m_pShadingObj->GetDict()->KeyExist("Background")) {
843ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Array* pBackColor =
844ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pPattern->m_pShadingObj->GetDict()->GetArray("Background");
845ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pBackColor &&
846ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pBackColor->GetCount() >= (FX_DWORD)pColorSpace->CountComponents()) {
847ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      CFX_FixedBufGrow<FX_FLOAT, 16> comps(pColorSpace->CountComponents());
848ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int i = 0; i < pColorSpace->CountComponents(); i++) {
849ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        comps[i] = pBackColor->GetNumber(i);
850ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
851ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
852ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pColorSpace->GetRGB(comps, R, G, B);
853ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      background = ArgbEncode(255, (int32_t)(R * 255), (int32_t)(G * 255),
854ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              (int32_t)(B * 255));
855ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
856ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
857ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pDict->KeyExist("BBox")) {
858ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_FloatRect rect = pDict->GetRect("BBox");
859ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    rect.Transform(pMatrix);
860ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    clip_rect.Intersect(rect.GetOutterRect());
861ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
862ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_DeviceBuffer buffer;
863ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  buffer.Initialize(m_pContext, m_pDevice, &clip_rect, m_pCurObj, 150);
864ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix FinalMatrix = *pMatrix;
865ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FinalMatrix.Concat(*buffer.GetMatrix());
866ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_DIBitmap* pBitmap = buffer.GetBitmap();
867ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pBitmap->GetBuffer()) {
868ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
869ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
870ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pBitmap->Clear(background);
871ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int fill_mode = m_Options.m_Flags;
872ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  switch (pPattern->m_ShadingType) {
873ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kInvalidShading:
874ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kMaxShading:
875ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
876ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kFunctionBasedShading:
877ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawFuncShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs, pColorSpace,
878ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      alpha);
879ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
880ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kAxialShading:
881ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawAxialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs,
882ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       pColorSpace, alpha);
883ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
884ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kRadialShading:
885ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawRadialShading(pBitmap, &FinalMatrix, pDict, pFuncs, nFuncs,
886ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        pColorSpace, alpha);
887ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
888ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kFreeFormGouraudTriangleMeshShading: {
889ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawFreeGouraudShading(pBitmap, &FinalMatrix,
890ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             ToStream(pPattern->m_pShadingObj), pFuncs, nFuncs,
891ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                             pColorSpace, alpha);
892ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } break;
893ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kLatticeFormGouraudTriangleMeshShading: {
894ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawLatticeGouraudShading(pBitmap, &FinalMatrix,
895ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                ToStream(pPattern->m_pShadingObj), pFuncs,
896ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                nFuncs, pColorSpace, alpha);
897ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } break;
898ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kCoonsPatchMeshShading:
899ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    case kTensorProductPatchMeshShading: {
900ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawCoonPatchMeshes(
901ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pPattern->m_ShadingType == kTensorProductPatchMeshShading, pBitmap,
902ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          &FinalMatrix, ToStream(pPattern->m_pShadingObj), pFuncs, nFuncs,
903ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          pColorSpace, fill_mode, alpha);
904ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } break;
905ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
906ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (bAlphaMode) {
907ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pBitmap->LoadChannel(FXDIB_Red, pBitmap, FXDIB_Alpha);
908ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
909ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
910ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pBitmap->ConvertColorScale(m_Options.m_ForeColor, m_Options.m_BackColor);
911ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
912ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  buffer.OutputToDevice();
913e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
914ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern,
915ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           CPDF_PageObject* pPageObj,
916ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           const CFX_Matrix* pObj2Device,
917ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           FX_BOOL bStroke) {
918ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pattern->Load()) {
919ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
920ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
921ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pDevice->SaveState();
922ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pPageObj->m_Type == PDFPAGE_PATH) {
923ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
924ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_pDevice->RestoreState();
925ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
926ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
927ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else if (pPageObj->m_Type == PDFPAGE_IMAGE) {
928ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_RECT rect = pPageObj->GetBBox(pObj2Device);
929ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pDevice->SetClip_Rect(&rect);
930ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
931ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
932ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
933ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_RECT rect;
934ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (GetObjectClippedRect(pPageObj, pObj2Device, FALSE, rect)) {
935e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pDevice->RestoreState();
936ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
937ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
938ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix matrix = pattern->m_Pattern2Form;
939ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.Concat(*pObj2Device);
940ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  GetScaledMatrix(matrix);
941ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke);
942ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  DrawShading(pattern, &matrix, rect, alpha,
943ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              m_Options.m_ColorMode == RENDER_COLOR_ALPHA);
944ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pDevice->RestoreState();
945e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
946ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannFX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj,
947ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                          const CFX_Matrix* pObj2Device) {
948ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_RECT rect = pShadingObj->GetBBox(pObj2Device);
949ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_RECT clip_box = m_pDevice->GetClipBox();
950ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  rect.Intersect(clip_box);
951ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (rect.IsEmpty()) {
952e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
953ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
954ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix matrix = pShadingObj->m_Matrix;
955ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  matrix.Concat(*pObj2Device);
956ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  DrawShading(pShadingObj->m_pShading, &matrix, rect,
957ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              pShadingObj->m_GeneralState.GetAlpha(FALSE),
958ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              m_Options.m_ColorMode == RENDER_COLOR_ALPHA);
959ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return TRUE;
960e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
961ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannstatic CFX_DIBitmap* DrawPatternBitmap(CPDF_Document* pDoc,
962ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       CPDF_PageRenderCache* pCache,
963ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       CPDF_TilingPattern* pPattern,
964ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       const CFX_Matrix* pObject2Device,
965ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       int width,
966ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       int height,
967ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                       int flags) {
968ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
969ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pBitmap->Create(width, height,
970ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) {
971ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    delete pBitmap;
972ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return NULL;
973ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
974ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FxgeDevice bitmap_device;
975ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  bitmap_device.Attach(pBitmap);
976ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pBitmap->Clear(0);
977ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FloatRect cell_bbox = pPattern->m_BBox;
978ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pPattern->m_Pattern2Form.TransformRect(cell_bbox);
979ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  pObject2Device->TransformRect(cell_bbox);
980ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height);
981ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix mtAdjust;
982ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  mtAdjust.MatchRect(bitmap_rect, cell_bbox);
983ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix mtPattern2Bitmap = *pObject2Device;
984ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  mtPattern2Bitmap.Concat(mtAdjust);
985ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_RenderOptions options;
986ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pPattern->m_bColored) {
987ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    options.m_ColorMode = RENDER_COLOR_ALPHA;
988ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
989ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  flags |= RENDER_FORCE_HALFTONE;
990ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  options.m_Flags = flags;
991ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_RenderContext context(pDoc, pCache);
992ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  context.DrawObjectList(&bitmap_device, pPattern->m_pForm, &mtPattern2Bitmap,
993ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         &options);
994ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  return pBitmap;
995e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
996ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern,
997ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                          CPDF_PageObject* pPageObj,
998ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                          const CFX_Matrix* pObj2Device,
999ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                          FX_BOOL bStroke) {
1000ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pPattern->Load()) {
1001ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1002ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1003ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pDevice->SaveState();
1004ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pPageObj->m_Type == PDFPAGE_PATH) {
1005ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
1006ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      m_pDevice->RestoreState();
1007ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
1008ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1009ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else if (pPageObj->m_Type == PDFPAGE_IMAGE) {
1010ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    FX_RECT rect = pPageObj->GetBBox(pObj2Device);
1011ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pDevice->SetClip_Rect(&rect);
1012ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
1013ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1014ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1015ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_RECT clip_box = m_pDevice->GetClipBox();
1016ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (clip_box.IsEmpty()) {
1017ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pDevice->RestoreState();
1018ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1019ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1020ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix dCTM = m_pDevice->GetCTM();
1021ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT sa = FXSYS_fabs(dCTM.a);
1022ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT sd = FXSYS_fabs(dCTM.d);
1023ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa);
1024ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd);
1025ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix mtPattern2Device = pPattern->m_Pattern2Form;
1026ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  mtPattern2Device.Concat(*pObj2Device);
1027ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  GetScaledMatrix(mtPattern2Device);
1028ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_BOOL bAligned = FALSE;
1029ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 &&
1030ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPattern->m_BBox.right == pPattern->m_XStep &&
1031ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pPattern->m_BBox.top == pPattern->m_YStep &&
1032ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) {
1033ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    bAligned = TRUE;
1034ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1035ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FloatRect cell_bbox = pPattern->m_BBox;
1036ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  mtPattern2Device.TransformRect(cell_bbox);
1037ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int width = (int)FXSYS_ceil(cell_bbox.Width());
1038ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int height = (int)FXSYS_ceil(cell_bbox.Height());
1039ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (width == 0) {
1040ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    width = 1;
1041ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1042ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (height == 0) {
1043ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    height = 1;
1044ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1045ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int min_col, max_col, min_row, max_row;
1046ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_Matrix mtDevice2Pattern;
1047ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  mtDevice2Pattern.SetReverse(mtPattern2Device);
1048ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_FloatRect clip_box_p(clip_box);
1049ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  clip_box_p.Transform(&mtDevice2Pattern);
1050ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  min_col = (int)FXSYS_ceil(
1051ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_Div(clip_box_p.left - pPattern->m_BBox.right, pPattern->m_XStep));
1052ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  max_col = (int)FXSYS_floor(
1053ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_Div(clip_box_p.right - pPattern->m_BBox.left, pPattern->m_XStep));
1054ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  min_row = (int)FXSYS_ceil(
1055ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_Div(clip_box_p.bottom - pPattern->m_BBox.top, pPattern->m_YStep));
1056ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  max_row = (int)FXSYS_floor(
1057ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FXSYS_Div(clip_box_p.top - pPattern->m_BBox.bottom, pPattern->m_YStep));
1058ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (width > clip_box.Width() || height > clip_box.Height() ||
1059ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      width * height > clip_box.Width() * clip_box.Height()) {
1060ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_GraphicStates* pStates = NULL;
1061ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (!pPattern->m_bColored) {
1062ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pStates = CloneObjStates(pPageObj, bStroke);
1063ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1064ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Dictionary* pFormResource = NULL;
1065ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (pPattern->m_pForm->m_pFormDict) {
1066ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      pFormResource = pPattern->m_pForm->m_pFormDict->GetDict("Resources");
1067ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1068ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int col = min_col; col <= max_col; col++)
1069ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      for (int row = min_row; row <= max_row; row++) {
1070ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT orig_x, orig_y;
1071ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        orig_x = col * pPattern->m_XStep;
1072ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        orig_y = row * pPattern->m_YStep;
1073ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        mtPattern2Device.Transform(orig_x, orig_y);
1074ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        CFX_Matrix matrix = *pObj2Device;
1075ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        matrix.Translate(orig_x - mtPattern2Device.e,
1076ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                         orig_y - mtPattern2Device.f);
1077ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m_pDevice->SaveState();
1078ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        CPDF_RenderStatus status;
1079ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates,
1080ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          &m_Options, pPattern->m_pForm->m_Transparency,
1081ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          m_bDropObjects, pFormResource);
1082ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        status.RenderObjectList(pPattern->m_pForm, &matrix);
1083e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_pDevice->RestoreState();
1084ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
1085ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pDevice->RestoreState();
1086ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    delete pStates;
1087ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1088ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1089ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (bAligned) {
1090ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int orig_x = FXSYS_round(mtPattern2Device.e);
1091ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int orig_y = FXSYS_round(mtPattern2Device.f);
1092ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    min_col = (clip_box.left - orig_x) / width;
1093ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (clip_box.left < orig_x) {
1094ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      min_col--;
1095ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1096ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    max_col = (clip_box.right - orig_x) / width;
1097ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (clip_box.right <= orig_x) {
1098ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max_col--;
1099ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1100ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    min_row = (clip_box.top - orig_y) / height;
1101ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (clip_box.top < orig_y) {
1102ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      min_row--;
1103ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1104ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    max_row = (clip_box.bottom - orig_y) / height;
1105ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (clip_box.bottom <= orig_y) {
1106ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      max_row--;
1107ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1109ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT left_offset = cell_bbox.left - mtPattern2Device.e;
1110ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_FLOAT top_offset = cell_bbox.bottom - mtPattern2Device.f;
1111ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_DIBitmap* pPatternBitmap = NULL;
1112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (width * height < 16) {
1113ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CFX_DIBitmap* pEnlargedBitmap =
1114ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        DrawPatternBitmap(m_pContext->m_pDocument, m_pContext->m_pPageCache,
1115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          pPattern, pObj2Device, 8, 8, m_Options.m_Flags);
1116ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPatternBitmap = pEnlargedBitmap->StretchTo(width, height);
1117ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    delete pEnlargedBitmap;
1118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
1119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPatternBitmap = DrawPatternBitmap(
1120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        m_pContext->m_pDocument, m_pContext->m_pPageCache, pPattern,
1121ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        pObj2Device, width, height, m_Options.m_Flags);
1122ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pPatternBitmap) {
1124ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pDevice->RestoreState();
1125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1126ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1127ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (m_Options.m_ColorMode == RENDER_COLOR_GRAY) {
1128ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    pPatternBitmap->ConvertColorScale(m_Options.m_ForeColor,
1129ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                      m_Options.m_BackColor);
1130ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1131ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_ARGB fill_argb = GetFillArgb(pPageObj);
1132ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int clip_width = clip_box.right - clip_box.left;
1133ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int clip_height = clip_box.bottom - clip_box.top;
1134ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_DIBitmap screen;
1135ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!screen.Create(clip_width, clip_height, FXDIB_Argb)) {
1136ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1137ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1138ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  screen.Clear(0);
1139ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_DWORD* src_buf = (FX_DWORD*)pPatternBitmap->GetBuffer();
1140ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int col = min_col; col <= max_col; col++) {
1141ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (int row = min_row; row <= max_row; row++) {
1142ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int start_x, start_y;
1143ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (bAligned) {
1144ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left;
1145ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top;
1146ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
1147ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT orig_x = col * pPattern->m_XStep;
1148ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_FLOAT orig_y = row * pPattern->m_YStep;
1149ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        mtPattern2Device.Transform(orig_x, orig_y);
1150ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        start_x = FXSYS_round(orig_x + left_offset) - clip_box.left;
1151ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        start_y = FXSYS_round(orig_y + top_offset) - clip_box.top;
1152ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
1153ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (width == 1 && height == 1) {
1154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (start_x < 0 || start_x >= clip_box.Width() || start_y < 0 ||
1155ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            start_y >= clip_box.Height()) {
1156ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
1157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
1158ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        FX_DWORD* dest_buf =
1159ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            (FX_DWORD*)(screen.GetBuffer() + screen.GetPitch() * start_y +
1160ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                        start_x * 4);
1161ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pPattern->m_bColored) {
1162ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          *dest_buf = *src_buf;
1163ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        } else {
1164ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff);
1165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
1166ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
1167ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        if (pPattern->m_bColored) {
1168ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          screen.CompositeBitmap(start_x, start_y, width, height,
1169ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                 pPatternBitmap, 0, 0);
1170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        } else {
1171ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          screen.CompositeMask(start_x, start_y, width, height, pPatternBitmap,
1172ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                               fill_argb, 0, 0);
1173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
1174ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
1175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
1176ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1177ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CompositeDIBitmap(&screen, clip_box.left, clip_box.top, 0, 255,
1178ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                    FXDIB_BLEND_NORMAL, FALSE);
1179ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pDevice->RestoreState();
1180ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  delete pPatternBitmap;
1181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
1182ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj,
1183ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                            const CFX_Matrix* pObj2Device,
1184ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                            CPDF_Color* pColor,
1185ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                            FX_BOOL bStroke) {
1186ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CPDF_Pattern* pattern = pColor->GetPattern();
1187ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (!pattern) {
1188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1190ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (pattern->m_PatternType == CPDF_Pattern::TILING) {
1191ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    DrawTilingPattern(static_cast<CPDF_TilingPattern*>(pattern), pPathObj,
1192ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                      pObj2Device, bStroke);
1193ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  } else {
1194ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    DrawShadingPattern(static_cast<CPDF_ShadingPattern*>(pattern), pPathObj,
1195ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                       pObj2Device, bStroke);
1196ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
1198ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj,
1199ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           const CFX_Matrix* pObj2Device,
1200ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           int& filltype,
1201ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                           FX_BOOL& bStroke) {
1202ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (filltype) {
1203ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Color& FillColor = *pPathObj->m_ColorState.GetFillColor();
1204ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (FillColor.m_pCS && FillColor.m_pCS->GetFamily() == PDFCS_PATTERN) {
1205ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawPathWithPattern(pPathObj, pObj2Device, &FillColor, FALSE);
1206ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      filltype = 0;
1207ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1208ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1209ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (bStroke) {
1210ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    CPDF_Color& StrokeColor = *pPathObj->m_ColorState.GetStrokeColor();
1211ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (StrokeColor.m_pCS && StrokeColor.m_pCS->GetFamily() == PDFCS_PATTERN) {
1212ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      DrawPathWithPattern(pPathObj, pObj2Device, &StrokeColor, TRUE);
1213ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      bStroke = FALSE;
1214ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
1215ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
1217