1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include <memory> 8 9 #include "fx_path_generator.h" 10 #include "pre.h" 11 12 class CAGG_Graphics { 13 public: 14 CAGG_Graphics(); 15 FX_ERR Create(CFX_Graphics* owner, 16 int32_t width, 17 int32_t height, 18 FXDIB_Format format); 19 virtual ~CAGG_Graphics(); 20 21 private: 22 CFX_Graphics* _owner; 23 }; 24 CFX_Graphics::CFX_Graphics() { 25 _type = FX_CONTEXT_None; 26 _info._graphState.SetDashCount(0); 27 _info._isAntialiasing = TRUE; 28 _info._strokeAlignment = FX_STROKEALIGNMENT_Center; 29 _info._CTM.SetIdentity(); 30 _info._isActOnDash = FALSE; 31 _info._strokeColor = NULL; 32 _info._fillColor = NULL; 33 _info._font = NULL; 34 _info._fontSize = 40.0; 35 _info._fontHScale = 1.0; 36 _info._fontSpacing = 0.0; 37 _renderDevice = NULL; 38 _aggGraphics = NULL; 39 } 40 FX_ERR CFX_Graphics::Create(CFX_RenderDevice* renderDevice, 41 FX_BOOL isAntialiasing) { 42 _FX_RETURN_VALUE_IF_FAIL(renderDevice, FX_ERR_Parameter_Invalid); 43 if (_type != FX_CONTEXT_None) { 44 return FX_ERR_Property_Invalid; 45 } 46 _type = FX_CONTEXT_Device; 47 _info._isAntialiasing = isAntialiasing; 48 _renderDevice = renderDevice; 49 if (_renderDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP) { 50 return FX_ERR_Succeeded; 51 } 52 return FX_ERR_Indefinite; 53 } 54 FX_ERR CFX_Graphics::Create(int32_t width, 55 int32_t height, 56 FXDIB_Format format, 57 FX_BOOL isNative, 58 FX_BOOL isAntialiasing) { 59 if (_type != FX_CONTEXT_None) { 60 return FX_ERR_Property_Invalid; 61 } 62 _type = FX_CONTEXT_Device; 63 _info._isAntialiasing = isAntialiasing; 64 { 65 _aggGraphics = new CAGG_Graphics; 66 return _aggGraphics->Create(this, width, height, format); 67 } 68 } 69 CFX_Graphics::~CFX_Graphics() { 70 if (_aggGraphics) { 71 delete _aggGraphics; 72 _aggGraphics = NULL; 73 } 74 _renderDevice = NULL; 75 _info._graphState.SetDashCount(0); 76 _type = FX_CONTEXT_None; 77 } 78 FX_ERR CFX_Graphics::GetDeviceCap(const int32_t capID, FX_DeviceCap& capVal) { 79 switch (_type) { 80 case FX_CONTEXT_Device: { 81 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 82 capVal = _renderDevice->GetDeviceCaps(capID); 83 return FX_ERR_Succeeded; 84 } 85 default: { return FX_ERR_Property_Invalid; } 86 } 87 } 88 FX_ERR CFX_Graphics::IsPrinterDevice(FX_BOOL& isPrinter) { 89 switch (_type) { 90 case FX_CONTEXT_Device: { 91 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 92 int32_t deviceClass = _renderDevice->GetDeviceClass(); 93 if (deviceClass == FXDC_PRINTER) { 94 isPrinter = TRUE; 95 } else { 96 isPrinter = FALSE; 97 } 98 return FX_ERR_Succeeded; 99 } 100 default: { return FX_ERR_Property_Invalid; } 101 } 102 } 103 FX_ERR CFX_Graphics::EnableAntialiasing(FX_BOOL isAntialiasing) { 104 switch (_type) { 105 case FX_CONTEXT_Device: { 106 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 107 _info._isAntialiasing = isAntialiasing; 108 return FX_ERR_Succeeded; 109 } 110 default: { return FX_ERR_Property_Invalid; } 111 } 112 } 113 FX_ERR CFX_Graphics::SaveGraphState() { 114 switch (_type) { 115 case FX_CONTEXT_Device: { 116 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 117 _renderDevice->SaveState(); 118 TInfo* info = new TInfo; 119 info->_graphState.Copy(_info._graphState); 120 info->_isAntialiasing = _info._isAntialiasing; 121 info->_strokeAlignment = _info._strokeAlignment; 122 info->_CTM = _info._CTM; 123 info->_isActOnDash = _info._isActOnDash; 124 info->_strokeColor = _info._strokeColor; 125 info->_fillColor = _info._fillColor; 126 info->_font = _info._font; 127 info->_fontSize = _info._fontSize; 128 info->_fontHScale = _info._fontHScale; 129 info->_fontSpacing = _info._fontSpacing; 130 _infoStack.Add(info); 131 return FX_ERR_Succeeded; 132 } 133 default: { return FX_ERR_Property_Invalid; } 134 } 135 } 136 FX_ERR CFX_Graphics::RestoreGraphState() { 137 switch (_type) { 138 case FX_CONTEXT_Device: { 139 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 140 _renderDevice->RestoreState(); 141 int32_t size = _infoStack.GetSize(); 142 if (size <= 0) { 143 return FX_ERR_Intermediate_Value_Invalid; 144 } 145 int32_t topIndex = size - 1; 146 TInfo* info = (TInfo*)_infoStack.GetAt(topIndex); 147 _FX_RETURN_VALUE_IF_FAIL(info, FX_ERR_Intermediate_Value_Invalid); 148 _info._graphState.Copy(info->_graphState); 149 _info._isAntialiasing = info->_isAntialiasing; 150 _info._strokeAlignment = info->_strokeAlignment; 151 _info._CTM = info->_CTM; 152 _info._isActOnDash = info->_isActOnDash; 153 _info._strokeColor = info->_strokeColor; 154 _info._fillColor = info->_fillColor; 155 _info._font = info->_font; 156 _info._fontSize = info->_fontSize; 157 _info._fontHScale = info->_fontHScale; 158 _info._fontSpacing = info->_fontSpacing; 159 delete info; 160 info = NULL; 161 _infoStack.RemoveAt(topIndex); 162 return FX_ERR_Succeeded; 163 } 164 default: { return FX_ERR_Property_Invalid; } 165 } 166 } 167 FX_ERR CFX_Graphics::GetLineCap(CFX_GraphStateData::LineCap& lineCap) { 168 switch (_type) { 169 case FX_CONTEXT_Device: { 170 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 171 lineCap = _info._graphState.m_LineCap; 172 return FX_ERR_Succeeded; 173 } 174 default: { return FX_ERR_Property_Invalid; } 175 } 176 } 177 FX_ERR CFX_Graphics::SetLineCap(CFX_GraphStateData::LineCap lineCap) { 178 switch (_type) { 179 case FX_CONTEXT_Device: { 180 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 181 _info._graphState.m_LineCap = lineCap; 182 return FX_ERR_Succeeded; 183 } 184 default: { return FX_ERR_Property_Invalid; } 185 } 186 } 187 FX_ERR CFX_Graphics::GetDashCount(int32_t& dashCount) { 188 switch (_type) { 189 case FX_CONTEXT_Device: { 190 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 191 dashCount = _info._graphState.m_DashCount; 192 return FX_ERR_Succeeded; 193 } 194 default: { return FX_ERR_Property_Invalid; } 195 } 196 } 197 FX_ERR CFX_Graphics::GetLineDash(FX_FLOAT& dashPhase, FX_FLOAT* dashArray) { 198 _FX_RETURN_VALUE_IF_FAIL(dashArray, FX_ERR_Parameter_Invalid); 199 switch (_type) { 200 case FX_CONTEXT_Device: { 201 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 202 dashPhase = _info._graphState.m_DashPhase; 203 FXSYS_memcpy(dashArray, _info._graphState.m_DashArray, 204 _info._graphState.m_DashCount * sizeof(FX_FLOAT)); 205 return FX_ERR_Succeeded; 206 } 207 default: { return FX_ERR_Property_Invalid; } 208 } 209 } 210 FX_ERR CFX_Graphics::SetLineDash(FX_FLOAT dashPhase, 211 FX_FLOAT* dashArray, 212 int32_t dashCount) { 213 if (dashCount > 0 && !dashArray) { 214 return FX_ERR_Parameter_Invalid; 215 } 216 dashCount = dashCount < 0 ? 0 : dashCount; 217 switch (_type) { 218 case FX_CONTEXT_Device: { 219 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 220 FX_FLOAT scale = 1.0; 221 if (_info._isActOnDash) { 222 scale = _info._graphState.m_LineWidth; 223 } 224 _info._graphState.m_DashPhase = dashPhase; 225 _info._graphState.SetDashCount(dashCount); 226 for (int32_t i = 0; i < dashCount; i++) { 227 _info._graphState.m_DashArray[i] = dashArray[i] * scale; 228 } 229 return FX_ERR_Succeeded; 230 } 231 default: { return FX_ERR_Property_Invalid; } 232 } 233 } 234 FX_ERR CFX_Graphics::SetLineDash(FX_DashStyle dashStyle) { 235 switch (_type) { 236 case FX_CONTEXT_Device: { 237 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 238 return RenderDeviceSetLineDash(dashStyle); 239 } 240 default: { return FX_ERR_Property_Invalid; } 241 } 242 } 243 FX_ERR CFX_Graphics::GetLineJoin(CFX_GraphStateData::LineJoin& lineJoin) { 244 switch (_type) { 245 case FX_CONTEXT_Device: { 246 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 247 lineJoin = _info._graphState.m_LineJoin; 248 return FX_ERR_Succeeded; 249 } 250 default: { return FX_ERR_Property_Invalid; } 251 } 252 } 253 FX_ERR CFX_Graphics::SetLineJoin(CFX_GraphStateData::LineJoin lineJoin) { 254 switch (_type) { 255 case FX_CONTEXT_Device: { 256 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 257 _info._graphState.m_LineJoin = lineJoin; 258 return FX_ERR_Succeeded; 259 } 260 default: { return FX_ERR_Property_Invalid; } 261 } 262 } 263 FX_ERR CFX_Graphics::GetMiterLimit(FX_FLOAT& miterLimit) { 264 switch (_type) { 265 case FX_CONTEXT_Device: { 266 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 267 miterLimit = _info._graphState.m_MiterLimit; 268 return FX_ERR_Succeeded; 269 } 270 default: { return FX_ERR_Property_Invalid; } 271 } 272 } 273 FX_ERR CFX_Graphics::SetMiterLimit(FX_FLOAT miterLimit) { 274 switch (_type) { 275 case FX_CONTEXT_Device: { 276 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 277 _info._graphState.m_MiterLimit = miterLimit; 278 return FX_ERR_Succeeded; 279 } 280 default: { return FX_ERR_Property_Invalid; } 281 } 282 } 283 FX_ERR CFX_Graphics::GetLineWidth(FX_FLOAT& lineWidth) { 284 switch (_type) { 285 case FX_CONTEXT_Device: { 286 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 287 lineWidth = _info._graphState.m_LineWidth; 288 return FX_ERR_Succeeded; 289 } 290 default: { return FX_ERR_Property_Invalid; } 291 } 292 } 293 FX_ERR CFX_Graphics::SetLineWidth(FX_FLOAT lineWidth, FX_BOOL isActOnDash) { 294 switch (_type) { 295 case FX_CONTEXT_Device: { 296 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 297 _info._graphState.m_LineWidth = lineWidth; 298 _info._isActOnDash = isActOnDash; 299 return FX_ERR_Succeeded; 300 } 301 default: { return FX_ERR_Property_Invalid; } 302 } 303 } 304 FX_ERR CFX_Graphics::GetStrokeAlignment(FX_StrokeAlignment& strokeAlignment) { 305 switch (_type) { 306 case FX_CONTEXT_Device: { 307 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 308 strokeAlignment = _info._strokeAlignment; 309 return FX_ERR_Succeeded; 310 } 311 default: { return FX_ERR_Property_Invalid; } 312 } 313 } 314 FX_ERR CFX_Graphics::SetStrokeAlignment(FX_StrokeAlignment strokeAlignment) { 315 switch (_type) { 316 case FX_CONTEXT_Device: { 317 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 318 _info._strokeAlignment = strokeAlignment; 319 return FX_ERR_Succeeded; 320 } 321 default: { return FX_ERR_Property_Invalid; } 322 } 323 } 324 FX_ERR CFX_Graphics::SetStrokeColor(CFX_Color* color) { 325 _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid); 326 switch (_type) { 327 case FX_CONTEXT_Device: { 328 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 329 _info._strokeColor = color; 330 return FX_ERR_Succeeded; 331 } 332 default: { return FX_ERR_Property_Invalid; } 333 } 334 } 335 FX_ERR CFX_Graphics::SetFillColor(CFX_Color* color) { 336 _FX_RETURN_VALUE_IF_FAIL(color, FX_ERR_Parameter_Invalid); 337 switch (_type) { 338 case FX_CONTEXT_Device: { 339 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 340 _info._fillColor = color; 341 return FX_ERR_Succeeded; 342 } 343 default: { return FX_ERR_Property_Invalid; } 344 } 345 } 346 FX_ERR CFX_Graphics::StrokePath(CFX_Path* path, CFX_Matrix* matrix) { 347 _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); 348 switch (_type) { 349 case FX_CONTEXT_Device: { 350 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 351 return RenderDeviceStrokePath(path, matrix); 352 } 353 default: { return FX_ERR_Property_Invalid; } 354 } 355 } 356 FX_ERR CFX_Graphics::FillPath(CFX_Path* path, 357 FX_FillMode fillMode, 358 CFX_Matrix* matrix) { 359 _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); 360 switch (_type) { 361 case FX_CONTEXT_Device: { 362 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 363 return RenderDeviceFillPath(path, fillMode, matrix); 364 } 365 default: { return FX_ERR_Property_Invalid; } 366 } 367 } 368 FX_ERR CFX_Graphics::ClipPath(CFX_Path* path, 369 FX_FillMode fillMode, 370 CFX_Matrix* matrix) { 371 _FX_RETURN_VALUE_IF_FAIL(path, FX_ERR_Parameter_Invalid); 372 switch (_type) { 373 case FX_CONTEXT_Device: { 374 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 375 FX_BOOL result = _renderDevice->SetClip_PathFill( 376 path->GetPathData(), (CFX_Matrix*)matrix, fillMode); 377 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite); 378 return FX_ERR_Succeeded; 379 } 380 default: { return FX_ERR_Property_Invalid; } 381 } 382 } 383 FX_ERR CFX_Graphics::DrawImage(CFX_DIBSource* source, 384 const CFX_PointF& point, 385 CFX_Matrix* matrix) { 386 _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid); 387 switch (_type) { 388 case FX_CONTEXT_Device: { 389 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 390 return RenderDeviceDrawImage(source, point, matrix); 391 } 392 default: { return FX_ERR_Property_Invalid; } 393 } 394 } 395 FX_ERR CFX_Graphics::StretchImage(CFX_DIBSource* source, 396 const CFX_RectF& rect, 397 CFX_Matrix* matrix) { 398 _FX_RETURN_VALUE_IF_FAIL(source, FX_ERR_Parameter_Invalid); 399 switch (_type) { 400 case FX_CONTEXT_Device: { 401 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 402 return RenderDeviceStretchImage(source, rect, matrix); 403 } 404 default: { return FX_ERR_Property_Invalid; } 405 } 406 } 407 FX_ERR CFX_Graphics::ConcatMatrix(const CFX_Matrix* matrix) { 408 _FX_RETURN_VALUE_IF_FAIL(matrix, FX_ERR_Parameter_Invalid); 409 switch (_type) { 410 case FX_CONTEXT_Device: { 411 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 412 _info._CTM.Concat(*matrix); 413 return FX_ERR_Succeeded; 414 } 415 default: { return FX_ERR_Property_Invalid; } 416 } 417 } 418 CFX_Matrix* CFX_Graphics::GetMatrix() { 419 switch (_type) { 420 case FX_CONTEXT_Device: { 421 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, NULL); 422 return &_info._CTM; 423 } 424 default: { return NULL; } 425 } 426 } 427 FX_ERR CFX_Graphics::GetClipRect(CFX_RectF& rect) { 428 switch (_type) { 429 case FX_CONTEXT_Device: { 430 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 431 FX_RECT r = _renderDevice->GetClipBox(); 432 rect.left = (FX_FLOAT)r.left; 433 rect.top = (FX_FLOAT)r.top; 434 rect.width = (FX_FLOAT)r.Width(); 435 rect.height = (FX_FLOAT)r.Height(); 436 return FX_ERR_Succeeded; 437 } 438 default: { return FX_ERR_Property_Invalid; } 439 } 440 } 441 FX_ERR CFX_Graphics::SetClipRect(const CFX_RectF& rect) { 442 switch (_type) { 443 case FX_CONTEXT_Device: { 444 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 445 FX_RECT r(FXSYS_round(rect.left), FXSYS_round(rect.top), 446 FXSYS_round(rect.right()), FXSYS_round(rect.bottom())); 447 FX_BOOL result = _renderDevice->SetClip_Rect(&r); 448 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); 449 return FX_ERR_Succeeded; 450 } 451 default: { return FX_ERR_Property_Invalid; } 452 } 453 } 454 FX_ERR CFX_Graphics::ClearClip() { 455 switch (_type) { 456 case FX_CONTEXT_Device: { 457 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 458 FX_BOOL result = FX_ERR_Succeeded; 459 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); 460 return FX_ERR_Succeeded; 461 } 462 default: { return FX_ERR_Property_Invalid; } 463 } 464 } 465 FX_ERR CFX_Graphics::SetFont(CFX_Font* font) { 466 _FX_RETURN_VALUE_IF_FAIL(font, FX_ERR_Parameter_Invalid); 467 switch (_type) { 468 case FX_CONTEXT_Device: { 469 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 470 _info._font = font; 471 return FX_ERR_Succeeded; 472 } 473 default: { return FX_ERR_Property_Invalid; } 474 } 475 } 476 FX_ERR CFX_Graphics::SetFontSize(const FX_FLOAT size) { 477 FX_FLOAT fontSize = size <= 0 ? 1.0f : size; 478 switch (_type) { 479 case FX_CONTEXT_Device: { 480 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 481 _info._fontSize = fontSize; 482 return FX_ERR_Succeeded; 483 } 484 default: { return FX_ERR_Property_Invalid; } 485 } 486 } 487 FX_ERR CFX_Graphics::SetFontHScale(const FX_FLOAT scale) { 488 FX_FLOAT fontHScale = scale <= 0 ? 1.0f : scale; 489 switch (_type) { 490 case FX_CONTEXT_Device: { 491 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 492 _info._fontHScale = fontHScale; 493 return FX_ERR_Succeeded; 494 } 495 default: { return FX_ERR_Property_Invalid; } 496 } 497 } 498 FX_ERR CFX_Graphics::SetCharSpacing(const FX_FLOAT spacing) { 499 FX_FLOAT fontSpacing = spacing < 0 ? 0 : spacing; 500 switch (_type) { 501 case FX_CONTEXT_Device: { 502 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 503 _info._fontSpacing = fontSpacing; 504 return FX_ERR_Succeeded; 505 } 506 default: { return FX_ERR_Property_Invalid; } 507 } 508 } 509 FX_ERR CFX_Graphics::SetTextDrawingMode(const int32_t mode) { 510 switch (_type) { 511 case FX_CONTEXT_Device: { 512 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 513 return FX_ERR_Succeeded; 514 } 515 default: { return FX_ERR_Property_Invalid; } 516 } 517 } 518 FX_ERR CFX_Graphics::ShowText(const CFX_PointF& point, 519 const CFX_WideString& text, 520 CFX_Matrix* matrix) { 521 switch (_type) { 522 case FX_CONTEXT_Device: { 523 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 524 return RenderDeviceShowText(point, text, matrix); 525 } 526 default: { return FX_ERR_Property_Invalid; } 527 } 528 } 529 FX_ERR CFX_Graphics::CalcTextRect(CFX_RectF& rect, 530 const CFX_WideString& text, 531 FX_BOOL isMultiline, 532 CFX_Matrix* matrix) { 533 switch (_type) { 534 case FX_CONTEXT_Device: { 535 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 536 int32_t length = text.GetLength(); 537 FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length); 538 FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length); 539 CalcTextInfo(text, charCodes, charPos, rect); 540 FX_Free(charPos); 541 FX_Free(charCodes); 542 return FX_ERR_Succeeded; 543 } 544 default: { return FX_ERR_Property_Invalid; } 545 } 546 } 547 FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics, 548 const CFX_Matrix* matrix) { 549 _FX_RETURN_VALUE_IF_FAIL(graphics, FX_ERR_Parameter_Invalid); 550 CFX_Matrix m; 551 m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 552 _info._CTM.f); 553 if (matrix) { 554 m.Concat(*matrix); 555 } 556 switch (_type) { 557 case FX_CONTEXT_Device: { 558 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 559 { 560 _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice, 561 FX_ERR_Parameter_Invalid); 562 CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap(); 563 FX_BOOL result = _renderDevice->SetDIBits(bitmap, 0, 0); 564 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); 565 } 566 } 567 default: { return FX_ERR_Property_Invalid; } 568 } 569 } 570 FX_ERR CFX_Graphics::Transfer(CFX_Graphics* graphics, 571 FX_FLOAT srcLeft, 572 FX_FLOAT srcTop, 573 const CFX_RectF& dstRect, 574 const CFX_Matrix* matrix) { 575 _FX_RETURN_VALUE_IF_FAIL(graphics, FX_ERR_Parameter_Invalid); 576 CFX_Matrix m; 577 m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 578 _info._CTM.f); 579 if (matrix) { 580 m.Concat(*matrix); 581 } 582 switch (_type) { 583 case FX_CONTEXT_Device: { 584 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 585 { 586 _FX_RETURN_VALUE_IF_FAIL(graphics->_renderDevice, 587 FX_ERR_Parameter_Invalid); 588 CFX_DIBitmap* bitmap = graphics->_renderDevice->GetBitmap(); 589 FX_BOOL result = FX_ERR_Indefinite; 590 CFX_DIBitmap bmp; 591 result = bmp.Create((int32_t)dstRect.width, (int32_t)dstRect.height, 592 bitmap->GetFormat()); 593 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Intermediate_Value_Invalid); 594 result = graphics->_renderDevice->GetDIBits(&bmp, (int32_t)srcLeft, 595 (int32_t)srcTop); 596 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); 597 result = _renderDevice->SetDIBits(&bmp, (int32_t)dstRect.left, 598 (int32_t)dstRect.top); 599 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Method_Not_Supported); 600 return FX_ERR_Succeeded; 601 } 602 } 603 default: { return FX_ERR_Property_Invalid; } 604 } 605 } 606 CFX_RenderDevice* CFX_Graphics::GetRenderDevice() { 607 return _renderDevice; 608 } 609 FX_ERR CFX_Graphics::InverseRect(const CFX_RectF& rect) { 610 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 611 CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); 612 _FX_RETURN_VALUE_IF_FAIL(bitmap, FX_ERR_Property_Invalid); 613 CFX_RectF temp(rect); 614 _info._CTM.TransformRect(temp); 615 CFX_RectF r; 616 r.Set(0, 0, (FX_FLOAT)bitmap->GetWidth(), (FX_FLOAT)bitmap->GetWidth()); 617 r.Intersect(temp); 618 if (r.IsEmpty()) { 619 return FX_ERR_Parameter_Invalid; 620 } 621 FX_ARGB* pBuf = 622 (FX_ARGB*)(bitmap->GetBuffer() + int32_t(r.top) * bitmap->GetPitch()); 623 int32_t bottom = (int32_t)r.bottom(); 624 int32_t right = (int32_t)r.right(); 625 for (int32_t i = (int32_t)r.top; i < bottom; i++) { 626 FX_ARGB* pLine = pBuf + (int32_t)r.left; 627 for (int32_t j = (int32_t)r.left; j < right; j++) { 628 FX_ARGB c = *pLine; 629 *pLine++ = (c & 0xFF000000) | (0xFFFFFF - (c & 0x00FFFFFF)); 630 } 631 pBuf = (FX_ARGB*)((uint8_t*)pBuf + bitmap->GetPitch()); 632 } 633 return FX_ERR_Succeeded; 634 } 635 FX_ERR CFX_Graphics::XorDIBitmap(const CFX_DIBitmap* srcBitmap, 636 const CFX_RectF& rect) { 637 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 638 CFX_DIBitmap* dst = _renderDevice->GetBitmap(); 639 _FX_RETURN_VALUE_IF_FAIL(dst, FX_ERR_Property_Invalid); 640 CFX_RectF temp(rect); 641 _info._CTM.TransformRect(temp); 642 CFX_RectF r; 643 r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth()); 644 r.Intersect(temp); 645 if (r.IsEmpty()) { 646 return FX_ERR_Parameter_Invalid; 647 } 648 FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() + 649 int32_t(r.top) * srcBitmap->GetPitch()); 650 FX_ARGB* pDstBuf = 651 (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch()); 652 int32_t bottom = (int32_t)r.bottom(); 653 int32_t right = (int32_t)r.right(); 654 for (int32_t i = (int32_t)r.top; i < bottom; i++) { 655 FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left; 656 FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left; 657 for (int32_t j = (int32_t)r.left; j < right; j++) { 658 FX_ARGB c = *pDstLine; 659 *pDstLine++ = 660 ArgbEncode(FXARGB_A(c), (c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF)); 661 pSrcLine++; 662 } 663 pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch()); 664 pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch()); 665 } 666 return FX_ERR_Succeeded; 667 } 668 FX_ERR CFX_Graphics::EqvDIBitmap(const CFX_DIBitmap* srcBitmap, 669 const CFX_RectF& rect) { 670 _FX_RETURN_VALUE_IF_FAIL(_renderDevice, FX_ERR_Property_Invalid); 671 CFX_DIBitmap* dst = _renderDevice->GetBitmap(); 672 _FX_RETURN_VALUE_IF_FAIL(dst, FX_ERR_Property_Invalid); 673 CFX_RectF temp(rect); 674 _info._CTM.TransformRect(temp); 675 CFX_RectF r; 676 r.Set(0, 0, (FX_FLOAT)dst->GetWidth(), (FX_FLOAT)dst->GetWidth()); 677 r.Intersect(temp); 678 if (r.IsEmpty()) { 679 return FX_ERR_Parameter_Invalid; 680 } 681 FX_ARGB* pSrcBuf = (FX_ARGB*)(srcBitmap->GetBuffer() + 682 int32_t(r.top) * srcBitmap->GetPitch()); 683 FX_ARGB* pDstBuf = 684 (FX_ARGB*)(dst->GetBuffer() + int32_t(r.top) * dst->GetPitch()); 685 int32_t bottom = (int32_t)r.bottom(); 686 int32_t right = (int32_t)r.right(); 687 for (int32_t i = (int32_t)r.top; i < bottom; i++) { 688 FX_ARGB* pSrcLine = pSrcBuf + (int32_t)r.left; 689 FX_ARGB* pDstLine = pDstBuf + (int32_t)r.left; 690 for (int32_t j = (int32_t)r.left; j < right; j++) { 691 FX_ARGB c = *pDstLine; 692 *pDstLine++ = 693 ArgbEncode(FXARGB_A(c), ~((c & 0xFFFFFF) ^ (*pSrcLine & 0xFFFFFF))); 694 pSrcLine++; 695 } 696 pSrcBuf = (FX_ARGB*)((uint8_t*)pSrcBuf + srcBitmap->GetPitch()); 697 pDstBuf = (FX_ARGB*)((uint8_t*)pDstBuf + dst->GetPitch()); 698 } 699 return FX_ERR_Succeeded; 700 } 701 FX_ERR CFX_Graphics::RenderDeviceSetLineDash(FX_DashStyle dashStyle) { 702 switch (dashStyle) { 703 case FX_DASHSTYLE_Solid: { 704 _info._graphState.SetDashCount(0); 705 return FX_ERR_Succeeded; 706 } 707 case FX_DASHSTYLE_Dash: { 708 FX_FLOAT dashArray[] = {3, 1}; 709 SetLineDash(0, dashArray, 2); 710 return FX_ERR_Succeeded; 711 } 712 case FX_DASHSTYLE_Dot: { 713 FX_FLOAT dashArray[] = {1, 1}; 714 SetLineDash(0, dashArray, 2); 715 return FX_ERR_Succeeded; 716 } 717 case FX_DASHSTYLE_DashDot: { 718 FX_FLOAT dashArray[] = {3, 1, 1, 1}; 719 SetLineDash(0, dashArray, 4); 720 return FX_ERR_Succeeded; 721 } 722 case FX_DASHSTYLE_DashDotDot: { 723 FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1}; 724 SetLineDash(0, dashArray, 6); 725 return FX_ERR_Succeeded; 726 } 727 default: { return FX_ERR_Parameter_Invalid; } 728 } 729 } 730 FX_ERR CFX_Graphics::RenderDeviceStrokePath(CFX_Path* path, 731 CFX_Matrix* matrix) { 732 _FX_RETURN_VALUE_IF_FAIL(_info._strokeColor, FX_ERR_Property_Invalid); 733 CFX_Matrix m; 734 m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 735 _info._CTM.f); 736 if (matrix) { 737 m.Concat(*matrix); 738 } 739 switch (_info._strokeColor->_type) { 740 case FX_COLOR_Solid: { 741 FX_BOOL result = _renderDevice->DrawPath( 742 path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState, 0x0, 743 _info._strokeColor->_argb, 0); 744 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite); 745 return FX_ERR_Succeeded; 746 } 747 case FX_COLOR_Pattern: { 748 return StrokePathWithPattern(path, &m); 749 } 750 case FX_COLOR_Shading: { 751 return StrokePathWithShading(path, &m); 752 } 753 default: { return FX_ERR_Property_Invalid; } 754 } 755 } 756 FX_ERR CFX_Graphics::RenderDeviceFillPath(CFX_Path* path, 757 FX_FillMode fillMode, 758 CFX_Matrix* matrix) { 759 _FX_RETURN_VALUE_IF_FAIL(_info._fillColor, FX_ERR_Property_Invalid); 760 CFX_Matrix m; 761 m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 762 _info._CTM.f); 763 if (matrix) { 764 m.Concat(*matrix); 765 } 766 switch (_info._fillColor->_type) { 767 case FX_COLOR_Solid: { 768 FX_BOOL result = _renderDevice->DrawPath( 769 path->GetPathData(), (CFX_Matrix*)&m, &_info._graphState, 770 _info._fillColor->_argb, 0x0, fillMode); 771 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite); 772 return FX_ERR_Succeeded; 773 } 774 case FX_COLOR_Pattern: { 775 { return FillPathWithPattern(path, fillMode, &m); } 776 } 777 case FX_COLOR_Shading: { 778 { return FillPathWithShading(path, fillMode, &m); } 779 } 780 default: { return FX_ERR_Property_Invalid; } 781 } 782 } 783 FX_ERR CFX_Graphics::RenderDeviceDrawImage(CFX_DIBSource* source, 784 const CFX_PointF& point, 785 CFX_Matrix* matrix) { 786 CFX_Matrix m1; 787 m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 788 _info._CTM.f); 789 if (matrix) { 790 m1.Concat(*matrix); 791 } 792 CFX_Matrix m2; 793 m2.Set((FX_FLOAT)source->GetWidth(), 0.0, 0.0, (FX_FLOAT)source->GetHeight(), 794 point.x, point.y); 795 m2.Concat(m1); 796 int32_t left, top; 797 CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE); 798 CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m2, left, top); 799 CFX_RectF r; 800 GetClipRect(r); 801 FX_ERR result = FX_ERR_Indefinite; 802 { 803 CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); 804 CFX_DIBitmap bmp; 805 bmp.Create(bitmap->GetWidth(), bitmap->GetHeight(), FXDIB_Argb); 806 _renderDevice->GetDIBits(&bmp, 0, 0); 807 bmp.TransferBitmap(FXSYS_round(r.left), FXSYS_round(r.top), 808 FXSYS_round(r.Width()), FXSYS_round(r.Height()), bmp2, 809 FXSYS_round(r.left - left), FXSYS_round(r.top - top)); 810 _renderDevice->SetDIBits(&bmp, 0, 0); 811 result = FX_ERR_Succeeded; 812 } 813 if (bmp2) { 814 delete bmp2; 815 bmp2 = NULL; 816 } 817 if (bmp1) { 818 delete bmp1; 819 bmp1 = NULL; 820 } 821 return result; 822 } 823 FX_ERR CFX_Graphics::RenderDeviceStretchImage(CFX_DIBSource* source, 824 const CFX_RectF& rect, 825 CFX_Matrix* matrix) { 826 CFX_Matrix m1; 827 m1.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 828 _info._CTM.f); 829 if (matrix) { 830 m1.Concat(*matrix); 831 } 832 CFX_DIBitmap* bmp1 = 833 source->StretchTo((int32_t)rect.Width(), (int32_t)rect.Height()); 834 CFX_Matrix m2; 835 m2.Set(rect.Width(), 0.0, 0.0, rect.Height(), rect.left, rect.top); 836 m2.Concat(m1); 837 int32_t left, top; 838 CFX_DIBitmap* bmp2 = bmp1->FlipImage(FALSE, TRUE); 839 CFX_DIBitmap* bmp3 = bmp2->TransformTo((CFX_Matrix*)&m2, left, top); 840 CFX_RectF r; 841 GetClipRect(r); 842 FX_ERR result = FX_ERR_Indefinite; 843 { 844 CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); 845 bitmap->CompositeBitmap(FXSYS_round(r.left), FXSYS_round(r.top), 846 FXSYS_round(r.Width()), FXSYS_round(r.Height()), 847 bmp3, FXSYS_round(r.left - left), 848 FXSYS_round(r.top - top)); 849 result = FX_ERR_Succeeded; 850 } 851 if (bmp3) { 852 delete bmp3; 853 bmp3 = NULL; 854 } 855 if (bmp2) { 856 delete bmp2; 857 bmp2 = NULL; 858 } 859 if (bmp1) { 860 delete bmp1; 861 bmp1 = NULL; 862 } 863 return result; 864 } 865 FX_ERR CFX_Graphics::RenderDeviceShowText(const CFX_PointF& point, 866 const CFX_WideString& text, 867 CFX_Matrix* matrix) { 868 int32_t length = text.GetLength(); 869 FX_DWORD* charCodes = FX_Alloc(FX_DWORD, length); 870 FXTEXT_CHARPOS* charPos = FX_Alloc(FXTEXT_CHARPOS, length); 871 CFX_RectF rect; 872 rect.Set(point.x, point.y, 0, 0); 873 CalcTextInfo(text, charCodes, charPos, rect); 874 CFX_Matrix m; 875 m.Set(_info._CTM.a, _info._CTM.b, _info._CTM.c, _info._CTM.d, _info._CTM.e, 876 _info._CTM.f); 877 m.Translate(0, _info._fontSize * _info._fontHScale); 878 if (matrix) { 879 m.Concat(*matrix); 880 } 881 FX_BOOL result = _renderDevice->DrawNormalText( 882 length, charPos, _info._font, CFX_GEModule::Get()->GetFontCache(), 883 -_info._fontSize * _info._fontHScale, (CFX_Matrix*)&m, 884 _info._fillColor->_argb, FXTEXT_CLEARTYPE); 885 _FX_RETURN_VALUE_IF_FAIL(result, FX_ERR_Indefinite); 886 FX_Free(charPos); 887 FX_Free(charCodes); 888 return FX_ERR_Succeeded; 889 } 890 FX_ERR CFX_Graphics::StrokePathWithPattern(CFX_Path* path, CFX_Matrix* matrix) { 891 return FX_ERR_Method_Not_Supported; 892 } 893 FX_ERR CFX_Graphics::StrokePathWithShading(CFX_Path* path, CFX_Matrix* matrix) { 894 return FX_ERR_Method_Not_Supported; 895 } 896 FX_ERR CFX_Graphics::FillPathWithPattern(CFX_Path* path, 897 FX_FillMode fillMode, 898 CFX_Matrix* matrix) { 899 CFX_Pattern* pattern = _info._fillColor->_pattern; 900 CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); 901 int32_t width = bitmap->GetWidth(); 902 int32_t height = bitmap->GetHeight(); 903 CFX_DIBitmap bmp; 904 bmp.Create(width, height, FXDIB_Argb); 905 _renderDevice->GetDIBits(&bmp, 0, 0); 906 switch (pattern->_type) { 907 case FX_PATTERN_Bitmap: { 908 int32_t xStep = FXSYS_round(pattern->_x1Step); 909 int32_t yStep = FXSYS_round(pattern->_y1Step); 910 int32_t xCount = width / xStep + 1; 911 int32_t yCount = height / yStep + 1; 912 for (int32_t i = 0; i <= yCount; i++) { 913 for (int32_t j = 0; j <= xCount; j++) { 914 bmp.TransferBitmap(j * xStep, i * yStep, xStep, yStep, 915 pattern->_bitmap, 0, 0); 916 } 917 } 918 break; 919 } 920 case FX_PATTERN_Hatch: { 921 FX_HatchStyle hatchStyle = _info._fillColor->_pattern->_hatchStyle; 922 if (hatchStyle < FX_HATCHSTYLE_Horizontal || 923 hatchStyle > FX_HATCHSTYLE_SolidDiamond) { 924 return FX_ERR_Intermediate_Value_Invalid; 925 } 926 const FX_HATCHDATA& data = hatchBitmapData[hatchStyle]; 927 CFX_DIBitmap mask; 928 mask.Create(data.width, data.height, FXDIB_1bppMask); 929 FXSYS_memcpy(mask.GetBuffer(), data.maskBits, 930 mask.GetPitch() * data.height); 931 CFX_FloatRect rectf = path->GetPathData()->GetBoundingBox(); 932 if (matrix) { 933 rectf.Transform((const CFX_Matrix*)matrix); 934 } 935 FX_RECT rect(FXSYS_round(rectf.left), FXSYS_round(rectf.top), 936 FXSYS_round(rectf.right), FXSYS_round(rectf.bottom)); 937 CFX_FxgeDevice device; 938 device.Attach(&bmp); 939 device.FillRect(&rect, _info._fillColor->_pattern->_backArgb); 940 for (int32_t j = rect.bottom; j < rect.top; j += mask.GetHeight()) { 941 for (int32_t i = rect.left; i < rect.right; i += mask.GetWidth()) { 942 device.SetBitMask(&mask, i, j, _info._fillColor->_pattern->_foreArgb); 943 } 944 } 945 break; 946 } 947 } 948 _renderDevice->SaveState(); 949 _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix, 950 fillMode); 951 SetDIBitsWithMatrix(&bmp, &pattern->_matrix); 952 _renderDevice->RestoreState(); 953 return FX_ERR_Succeeded; 954 } 955 FX_ERR CFX_Graphics::FillPathWithShading(CFX_Path* path, 956 FX_FillMode fillMode, 957 CFX_Matrix* matrix) { 958 CFX_DIBitmap* bitmap = _renderDevice->GetBitmap(); 959 int32_t width = bitmap->GetWidth(); 960 int32_t height = bitmap->GetHeight(); 961 FX_FLOAT start_x = _info._fillColor->_shading->_beginPoint.x; 962 FX_FLOAT start_y = _info._fillColor->_shading->_beginPoint.y; 963 FX_FLOAT end_x = _info._fillColor->_shading->_endPoint.x; 964 FX_FLOAT end_y = _info._fillColor->_shading->_endPoint.y; 965 CFX_DIBitmap bmp; 966 bmp.Create(width, height, FXDIB_Argb); 967 _renderDevice->GetDIBits(&bmp, 0, 0); 968 int32_t pitch = bmp.GetPitch(); 969 FX_BOOL result = FALSE; 970 switch (_info._fillColor->_shading->_type) { 971 case FX_SHADING_Axial: { 972 FX_FLOAT x_span = end_x - start_x; 973 FX_FLOAT y_span = end_y - start_y; 974 FX_FLOAT axis_len_square = 975 FXSYS_Mul(x_span, x_span) + FXSYS_Mul(y_span, y_span); 976 for (int32_t row = 0; row < height; row++) { 977 FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch); 978 for (int32_t column = 0; column < width; column++) { 979 FX_FLOAT x = (FX_FLOAT)(column); 980 FX_FLOAT y = (FX_FLOAT)(row); 981 FX_FLOAT scale = FXSYS_Div( 982 FXSYS_Mul(x - start_x, x_span) + FXSYS_Mul(y - start_y, y_span), 983 axis_len_square); 984 if (scale < 0) { 985 if (!_info._fillColor->_shading->_isExtendedBegin) { 986 continue; 987 } 988 scale = 0; 989 } else if (scale > 1.0f) { 990 if (!_info._fillColor->_shading->_isExtendedEnd) { 991 continue; 992 } 993 scale = 1.0f; 994 } 995 int32_t index = (int32_t)(scale * (FX_SHADING_Steps - 1)); 996 dib_buf[column] = _info._fillColor->_shading->_argbArray[index]; 997 } 998 } 999 result = TRUE; 1000 break; 1001 } 1002 case FX_SHADING_Radial: { 1003 FX_FLOAT start_r = _info._fillColor->_shading->_beginRadius; 1004 FX_FLOAT end_r = _info._fillColor->_shading->_endRadius; 1005 FX_FLOAT a = FXSYS_Mul(start_x - end_x, start_x - end_x) + 1006 FXSYS_Mul(start_y - end_y, start_y - end_y) - 1007 FXSYS_Mul(start_r - end_r, start_r - end_r); 1008 for (int32_t row = 0; row < height; row++) { 1009 FX_DWORD* dib_buf = (FX_DWORD*)(bmp.GetBuffer() + row * pitch); 1010 for (int32_t column = 0; column < width; column++) { 1011 FX_FLOAT x = (FX_FLOAT)(column); 1012 FX_FLOAT y = (FX_FLOAT)(row); 1013 FX_FLOAT b = -2 * (FXSYS_Mul(x - start_x, end_x - start_x) + 1014 FXSYS_Mul(y - start_y, end_y - start_y) + 1015 FXSYS_Mul(start_r, end_r - start_r)); 1016 FX_FLOAT c = FXSYS_Mul(x - start_x, x - start_x) + 1017 FXSYS_Mul(y - start_y, y - start_y) - 1018 FXSYS_Mul(start_r, start_r); 1019 FX_FLOAT s; 1020 if (a == 0) { 1021 s = (FXSYS_Div(-c, b)); 1022 } else { 1023 FX_FLOAT b2_4ac = FXSYS_Mul(b, b) - 4 * FXSYS_Mul(a, c); 1024 if (b2_4ac < 0) { 1025 continue; 1026 } 1027 FX_FLOAT root = (FXSYS_sqrt(b2_4ac)); 1028 FX_FLOAT s1, s2; 1029 if (a > 0) { 1030 s1 = FXSYS_Div(-b - root, 2 * a); 1031 s2 = FXSYS_Div(-b + root, 2 * a); 1032 } else { 1033 s2 = FXSYS_Div(-b - root, 2 * a); 1034 s1 = FXSYS_Div(-b + root, 2 * a); 1035 } 1036 if (s2 <= 1.0f || _info._fillColor->_shading->_isExtendedEnd) { 1037 s = (s2); 1038 } else { 1039 s = (s1); 1040 } 1041 if ((start_r) + s * (end_r - start_r) < 0) { 1042 continue; 1043 } 1044 } 1045 if (s < 0) { 1046 if (!_info._fillColor->_shading->_isExtendedBegin) { 1047 continue; 1048 } 1049 s = 0; 1050 } 1051 if (s > 1.0f) { 1052 if (!_info._fillColor->_shading->_isExtendedEnd) { 1053 continue; 1054 } 1055 s = 1.0f; 1056 } 1057 int index = (int32_t)(s * (FX_SHADING_Steps - 1)); 1058 dib_buf[column] = _info._fillColor->_shading->_argbArray[index]; 1059 } 1060 } 1061 result = TRUE; 1062 break; 1063 } 1064 default: { result = FALSE; } 1065 } 1066 if (result) { 1067 _renderDevice->SaveState(); 1068 _renderDevice->SetClip_PathFill(path->GetPathData(), (CFX_Matrix*)matrix, 1069 fillMode); 1070 SetDIBitsWithMatrix(&bmp, matrix); 1071 _renderDevice->RestoreState(); 1072 } 1073 return result; 1074 } 1075 FX_ERR CFX_Graphics::SetDIBitsWithMatrix(CFX_DIBSource* source, 1076 CFX_Matrix* matrix) { 1077 if (matrix->IsIdentity()) { 1078 _renderDevice->SetDIBits(source, 0, 0); 1079 } else { 1080 CFX_Matrix m; 1081 m.Set((FX_FLOAT)source->GetWidth(), 0, 0, (FX_FLOAT)source->GetHeight(), 0, 1082 0); 1083 m.Concat(*matrix); 1084 int32_t left, top; 1085 CFX_DIBitmap* bmp1 = source->FlipImage(FALSE, TRUE); 1086 CFX_DIBitmap* bmp2 = bmp1->TransformTo((CFX_Matrix*)&m, left, top); 1087 _renderDevice->SetDIBits(bmp2, left, top); 1088 if (bmp2) { 1089 delete bmp2; 1090 bmp2 = NULL; 1091 } 1092 if (bmp1) { 1093 delete bmp1; 1094 bmp1 = NULL; 1095 } 1096 } 1097 return FX_ERR_Succeeded; 1098 } 1099 FX_ERR CFX_Graphics::CalcTextInfo(const CFX_WideString& text, 1100 FX_DWORD* charCodes, 1101 FXTEXT_CHARPOS* charPos, 1102 CFX_RectF& rect) { 1103 std::unique_ptr<CFX_UnicodeEncoding> encoding( 1104 new CFX_UnicodeEncoding(_info._font)); 1105 int32_t length = text.GetLength(); 1106 FX_FLOAT penX = (FX_FLOAT)rect.left; 1107 FX_FLOAT penY = (FX_FLOAT)rect.top; 1108 FX_FLOAT left = (FX_FLOAT)(0); 1109 FX_FLOAT top = (FX_FLOAT)(0); 1110 charCodes[0] = text.GetAt(0); 1111 charPos[0].m_OriginX = penX + left; 1112 charPos[0].m_OriginY = penY + top; 1113 charPos[0].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[0]); 1114 charPos[0].m_FontCharWidth = FXSYS_round( 1115 _info._font->GetGlyphWidth(charPos[0].m_GlyphIndex) * _info._fontHScale); 1116 charPos[0].m_bGlyphAdjust = TRUE; 1117 charPos[0].m_AdjustMatrix[0] = -1; 1118 charPos[0].m_AdjustMatrix[1] = 0; 1119 charPos[0].m_AdjustMatrix[2] = 0; 1120 charPos[0].m_AdjustMatrix[3] = 1; 1121 penX += (FX_FLOAT)(charPos[0].m_FontCharWidth) * _info._fontSize / 1000 + 1122 _info._fontSpacing; 1123 for (int32_t i = 1; i < length; i++) { 1124 charCodes[i] = text.GetAt(i); 1125 charPos[i].m_OriginX = penX + left; 1126 charPos[i].m_OriginY = penY + top; 1127 charPos[i].m_GlyphIndex = encoding->GlyphFromCharCode(charCodes[i]); 1128 charPos[i].m_FontCharWidth = 1129 FXSYS_round(_info._font->GetGlyphWidth(charPos[i].m_GlyphIndex) * 1130 _info._fontHScale); 1131 charPos[i].m_bGlyphAdjust = TRUE; 1132 charPos[i].m_AdjustMatrix[0] = -1; 1133 charPos[i].m_AdjustMatrix[1] = 0; 1134 charPos[i].m_AdjustMatrix[2] = 0; 1135 charPos[i].m_AdjustMatrix[3] = 1; 1136 penX += (FX_FLOAT)(charPos[i].m_FontCharWidth) * _info._fontSize / 1000 + 1137 _info._fontSpacing; 1138 } 1139 rect.width = (FX_FLOAT)penX - rect.left; 1140 rect.height = rect.top + _info._fontSize * _info._fontHScale - rect.top; 1141 return FX_ERR_Succeeded; 1142 } 1143 CAGG_Graphics::CAGG_Graphics() { 1144 _owner = NULL; 1145 } 1146 FX_ERR CAGG_Graphics::Create(CFX_Graphics* owner, 1147 int32_t width, 1148 int32_t height, 1149 FXDIB_Format format) { 1150 if (owner->_renderDevice) { 1151 return FX_ERR_Parameter_Invalid; 1152 } 1153 if (_owner) { 1154 return FX_ERR_Property_Invalid; 1155 } 1156 CFX_FxgeDevice* device = new CFX_FxgeDevice; 1157 device->Create(width, height, format); 1158 _owner = owner; 1159 _owner->_renderDevice = device; 1160 _owner->_renderDevice->GetBitmap()->Clear(0xFFFFFFFF); 1161 return FX_ERR_Succeeded; 1162 } 1163 CAGG_Graphics::~CAGG_Graphics() { 1164 if (_owner->_renderDevice) { 1165 delete (CFX_FxgeDevice*)_owner->_renderDevice; 1166 } 1167 _owner = NULL; 1168 } 1169 CFX_Path::CFX_Path() { 1170 _generator = NULL; 1171 } 1172 FX_ERR CFX_Path::Create() { 1173 if (_generator) { 1174 return FX_ERR_Property_Invalid; 1175 } 1176 _generator = new CFX_PathGenerator; 1177 _generator->Create(); 1178 return FX_ERR_Succeeded; 1179 } 1180 CFX_Path::~CFX_Path() { 1181 if (_generator) { 1182 delete _generator; 1183 _generator = NULL; 1184 } 1185 } 1186 FX_ERR CFX_Path::MoveTo(FX_FLOAT x, FX_FLOAT y) { 1187 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1188 _generator->MoveTo(x, y); 1189 return FX_ERR_Succeeded; 1190 } 1191 FX_ERR CFX_Path::LineTo(FX_FLOAT x, FX_FLOAT y) { 1192 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1193 _generator->LineTo(x, y); 1194 return FX_ERR_Succeeded; 1195 } 1196 FX_ERR CFX_Path::BezierTo(FX_FLOAT ctrlX1, 1197 FX_FLOAT ctrlY1, 1198 FX_FLOAT ctrlX2, 1199 FX_FLOAT ctrlY2, 1200 FX_FLOAT toX, 1201 FX_FLOAT toY) { 1202 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1203 _generator->BezierTo(ctrlX1, ctrlY1, ctrlX2, ctrlY2, toX, toY); 1204 return FX_ERR_Succeeded; 1205 } 1206 FX_ERR CFX_Path::ArcTo(FX_FLOAT left, 1207 FX_FLOAT top, 1208 FX_FLOAT width, 1209 FX_FLOAT height, 1210 FX_FLOAT startAngle, 1211 FX_FLOAT sweepAngle) { 1212 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1213 _generator->ArcTo(left + width / 2, top + height / 2, width / 2, height / 2, 1214 startAngle, sweepAngle); 1215 return FX_ERR_Succeeded; 1216 } 1217 FX_ERR CFX_Path::Close() { 1218 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1219 _generator->Close(); 1220 return FX_ERR_Succeeded; 1221 } 1222 FX_ERR CFX_Path::AddLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2) { 1223 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1224 _generator->AddLine(x1, y1, x2, y2); 1225 return FX_ERR_Succeeded; 1226 } 1227 FX_ERR CFX_Path::AddBezier(FX_FLOAT startX, 1228 FX_FLOAT startY, 1229 FX_FLOAT ctrlX1, 1230 FX_FLOAT ctrlY1, 1231 FX_FLOAT ctrlX2, 1232 FX_FLOAT ctrlY2, 1233 FX_FLOAT endX, 1234 FX_FLOAT endY) { 1235 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1236 _generator->AddBezier(startX, startY, ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, 1237 endY); 1238 return FX_ERR_Succeeded; 1239 } 1240 FX_ERR CFX_Path::AddRectangle(FX_FLOAT left, 1241 FX_FLOAT top, 1242 FX_FLOAT width, 1243 FX_FLOAT height) { 1244 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1245 _generator->AddRectangle(left, top, left + width, top + height); 1246 return FX_ERR_Succeeded; 1247 } 1248 FX_ERR CFX_Path::AddEllipse(FX_FLOAT left, 1249 FX_FLOAT top, 1250 FX_FLOAT width, 1251 FX_FLOAT height) { 1252 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1253 _generator->AddEllipse(left + width / 2, top + height / 2, width / 2, 1254 height / 2); 1255 return FX_ERR_Succeeded; 1256 } 1257 FX_ERR CFX_Path::AddEllipse(const CFX_RectF& rect) { 1258 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1259 _generator->AddEllipse(rect.left + rect.Width() / 2, 1260 rect.top + rect.Height() / 2, rect.Width() / 2, 1261 rect.Height() / 2); 1262 return FX_ERR_Succeeded; 1263 } 1264 FX_ERR CFX_Path::AddArc(FX_FLOAT left, 1265 FX_FLOAT top, 1266 FX_FLOAT width, 1267 FX_FLOAT height, 1268 FX_FLOAT startAngle, 1269 FX_FLOAT sweepAngle) { 1270 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1271 _generator->AddArc(left + width / 2, top + height / 2, width / 2, height / 2, 1272 startAngle, sweepAngle); 1273 return FX_ERR_Succeeded; 1274 } 1275 FX_ERR CFX_Path::AddPie(FX_FLOAT left, 1276 FX_FLOAT top, 1277 FX_FLOAT width, 1278 FX_FLOAT height, 1279 FX_FLOAT startAngle, 1280 FX_FLOAT sweepAngle) { 1281 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1282 _generator->AddPie(left + width / 2, top + height / 2, width / 2, height / 2, 1283 startAngle, sweepAngle); 1284 return FX_ERR_Succeeded; 1285 } 1286 FX_ERR CFX_Path::AddSubpath(CFX_Path* path) { 1287 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1288 _generator->AddPathData(path->GetPathData()); 1289 return FX_ERR_Succeeded; 1290 } 1291 FX_ERR CFX_Path::Clear() { 1292 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1293 _generator->GetPathData()->SetPointCount(0); 1294 return FX_ERR_Succeeded; 1295 } 1296 FX_BOOL CFX_Path::IsEmpty() { 1297 _FX_RETURN_VALUE_IF_FAIL(_generator, FX_ERR_Property_Invalid); 1298 if (_generator->GetPathData()->GetPointCount() == 0) { 1299 return TRUE; 1300 } 1301 return FALSE; 1302 } 1303 CFX_PathData* CFX_Path::GetPathData() { 1304 _FX_RETURN_VALUE_IF_FAIL(_generator, NULL); 1305 return _generator->GetPathData(); 1306 } 1307 CFX_Color::CFX_Color() { 1308 _type = FX_COLOR_None; 1309 } 1310 CFX_Color::CFX_Color(const FX_ARGB argb) { 1311 _type = FX_COLOR_None; 1312 Set(argb); 1313 } 1314 CFX_Color::CFX_Color(CFX_Pattern* pattern, const FX_ARGB argb) { 1315 _type = FX_COLOR_None; 1316 Set(pattern, argb); 1317 } 1318 CFX_Color::CFX_Color(CFX_Shading* shading) { 1319 _type = FX_COLOR_None; 1320 Set(shading); 1321 } 1322 CFX_Color::~CFX_Color() { 1323 _type = FX_COLOR_None; 1324 } 1325 FX_ERR CFX_Color::Set(const FX_ARGB argb) { 1326 _type = FX_COLOR_Solid; 1327 _argb = argb; 1328 _pattern = NULL; 1329 return FX_ERR_Succeeded; 1330 } 1331 FX_ERR CFX_Color::Set(CFX_Pattern* pattern, const FX_ARGB argb) { 1332 _FX_RETURN_VALUE_IF_FAIL(pattern, FX_ERR_Parameter_Invalid); 1333 _type = FX_COLOR_Pattern; 1334 _argb = argb; 1335 _pattern = pattern; 1336 return FX_ERR_Succeeded; 1337 } 1338 FX_ERR CFX_Color::Set(CFX_Shading* shading) { 1339 _FX_RETURN_VALUE_IF_FAIL(shading, FX_ERR_Parameter_Invalid); 1340 _type = FX_COLOR_Shading; 1341 _shading = shading; 1342 return FX_ERR_Succeeded; 1343 } 1344 CFX_Pattern::CFX_Pattern() { 1345 _type = FX_PATTERN_None; 1346 _matrix.SetIdentity(); 1347 } 1348 FX_ERR CFX_Pattern::Create(CFX_DIBitmap* bitmap, 1349 const FX_FLOAT xStep, 1350 const FX_FLOAT yStep, 1351 CFX_Matrix* matrix) { 1352 _FX_RETURN_VALUE_IF_FAIL(bitmap, FX_ERR_Parameter_Invalid); 1353 if (_type != FX_PATTERN_None) { 1354 return FX_ERR_Property_Invalid; 1355 } 1356 _type = FX_PATTERN_Bitmap; 1357 _bitmap = bitmap; 1358 _x1Step = xStep; 1359 _y1Step = yStep; 1360 if (matrix) { 1361 _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, 1362 matrix->f); 1363 } 1364 return FX_ERR_Succeeded; 1365 } 1366 FX_ERR CFX_Pattern::Create(FX_HatchStyle hatchStyle, 1367 const FX_ARGB foreArgb, 1368 const FX_ARGB backArgb, 1369 CFX_Matrix* matrix) { 1370 if (hatchStyle < FX_HATCHSTYLE_Horizontal || 1371 hatchStyle > FX_HATCHSTYLE_SolidDiamond) { 1372 return FX_ERR_Parameter_Invalid; 1373 } 1374 if (_type != FX_PATTERN_None) { 1375 return FX_ERR_Property_Invalid; 1376 } 1377 _type = FX_PATTERN_Hatch; 1378 _hatchStyle = hatchStyle; 1379 _foreArgb = foreArgb; 1380 _backArgb = backArgb; 1381 if (matrix) { 1382 _matrix.Set(matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, 1383 matrix->f); 1384 } 1385 return FX_ERR_Succeeded; 1386 } 1387 CFX_Pattern::~CFX_Pattern() { 1388 _type = FX_PATTERN_None; 1389 } 1390 CFX_Shading::CFX_Shading() { 1391 _type = FX_SHADING_None; 1392 } 1393 FX_ERR CFX_Shading::CreateAxial(const CFX_PointF& beginPoint, 1394 const CFX_PointF& endPoint, 1395 FX_BOOL isExtendedBegin, 1396 FX_BOOL isExtendedEnd, 1397 const FX_ARGB beginArgb, 1398 const FX_ARGB endArgb) { 1399 if (_type != FX_SHADING_None) { 1400 return FX_ERR_Property_Invalid; 1401 } 1402 _type = FX_SHADING_Axial; 1403 _beginPoint = beginPoint; 1404 _endPoint = endPoint; 1405 _isExtendedBegin = isExtendedBegin; 1406 _isExtendedEnd = isExtendedEnd; 1407 _beginArgb = beginArgb; 1408 _endArgb = endArgb; 1409 return InitArgbArray(); 1410 } 1411 FX_ERR CFX_Shading::CreateRadial(const CFX_PointF& beginPoint, 1412 const CFX_PointF& endPoint, 1413 const FX_FLOAT beginRadius, 1414 const FX_FLOAT endRadius, 1415 FX_BOOL isExtendedBegin, 1416 FX_BOOL isExtendedEnd, 1417 const FX_ARGB beginArgb, 1418 const FX_ARGB endArgb) { 1419 if (_type != FX_SHADING_None) { 1420 return FX_ERR_Property_Invalid; 1421 } 1422 _type = FX_SHADING_Radial; 1423 _beginPoint = beginPoint; 1424 _endPoint = endPoint; 1425 _beginRadius = beginRadius; 1426 _endRadius = endRadius; 1427 _isExtendedBegin = isExtendedBegin; 1428 _isExtendedEnd = isExtendedEnd; 1429 _beginArgb = beginArgb; 1430 _endArgb = endArgb; 1431 return InitArgbArray(); 1432 } 1433 CFX_Shading::~CFX_Shading() { 1434 _type = FX_SHADING_None; 1435 } 1436 FX_ERR CFX_Shading::InitArgbArray() { 1437 int32_t a1, r1, g1, b1; 1438 ArgbDecode(_beginArgb, a1, r1, g1, b1); 1439 int32_t a2, r2, g2, b2; 1440 ArgbDecode(_endArgb, a2, r2, g2, b2); 1441 FX_FLOAT f = (FX_FLOAT)(FX_SHADING_Steps - 1); 1442 FX_FLOAT aScale = (FX_FLOAT)(1.0 * (a2 - a1) / f); 1443 FX_FLOAT rScale = (FX_FLOAT)(1.0 * (r2 - r1) / f); 1444 FX_FLOAT gScale = (FX_FLOAT)(1.0 * (g2 - g1) / f); 1445 FX_FLOAT bScale = (FX_FLOAT)(1.0 * (b2 - b1) / f); 1446 int32_t a3, r3, g3, b3; 1447 for (int32_t i = 0; i < FX_SHADING_Steps; i++) { 1448 a3 = (int32_t)(i * aScale); 1449 r3 = (int32_t)(i * rScale); 1450 g3 = (int32_t)(i * gScale); 1451 b3 = (int32_t)(i * bScale); 1452 _argbArray[i] = 1453 FXARGB_TODIB(FXARGB_MAKE((a1 + a3), (r1 + r3), (g1 + g3), (b1 + b3))); 1454 } 1455 return FX_ERR_Succeeded; 1456 } 1457 class CFX_Pause : public IFX_Pause { 1458 public: 1459 virtual FX_BOOL NeedToPauseNow() { return TRUE; } 1460 }; 1461