PWL_Utils.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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 "fpdfsdk/pdfwindow/PWL_Utils.h" 8 9#include <algorithm> 10#include <memory> 11 12#include "core/fpdfdoc/cpvt_word.h" 13#include "core/fxge/cfx_graphstatedata.h" 14#include "core/fxge/cfx_pathdata.h" 15#include "core/fxge/cfx_renderdevice.h" 16#include "fpdfsdk/fxedit/fxet_edit.h" 17#include "fpdfsdk/pdfwindow/PWL_Icon.h" 18#include "fpdfsdk/pdfwindow/PWL_Wnd.h" 19 20CFX_FloatRect CPWL_Utils::OffsetRect(const CFX_FloatRect& rect, 21 FX_FLOAT x, 22 FX_FLOAT y) { 23 return CFX_FloatRect(rect.left + x, rect.bottom + y, rect.right + x, 24 rect.top + y); 25} 26 27CPVT_WordRange CPWL_Utils::OverlapWordRange(const CPVT_WordRange& wr1, 28 const CPVT_WordRange& wr2) { 29 CPVT_WordRange wrRet; 30 31 if (wr2.EndPos.WordCmp(wr1.BeginPos) < 0 || 32 wr2.BeginPos.WordCmp(wr1.EndPos) > 0) 33 return wrRet; 34 if (wr1.EndPos.WordCmp(wr2.BeginPos) < 0 || 35 wr1.BeginPos.WordCmp(wr2.EndPos) > 0) 36 return wrRet; 37 38 if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) { 39 wrRet.BeginPos = wr2.BeginPos; 40 } else { 41 wrRet.BeginPos = wr1.BeginPos; 42 } 43 44 if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) { 45 wrRet.EndPos = wr1.EndPos; 46 } else { 47 wrRet.EndPos = wr2.EndPos; 48 } 49 50 return wrRet; 51} 52 53CFX_ByteString CPWL_Utils::GetAP_Check(const CFX_FloatRect& crBBox) { 54 const FX_FLOAT fWidth = crBBox.right - crBBox.left; 55 const FX_FLOAT fHeight = crBBox.top - crBBox.bottom; 56 57 CFX_PointF pts[8][3] = {{CFX_PointF(0.28f, 0.52f), CFX_PointF(0.27f, 0.48f), 58 CFX_PointF(0.29f, 0.40f)}, 59 {CFX_PointF(0.30f, 0.33f), CFX_PointF(0.31f, 0.29f), 60 CFX_PointF(0.31f, 0.28f)}, 61 {CFX_PointF(0.39f, 0.28f), CFX_PointF(0.49f, 0.29f), 62 CFX_PointF(0.77f, 0.67f)}, 63 {CFX_PointF(0.76f, 0.68f), CFX_PointF(0.78f, 0.69f), 64 CFX_PointF(0.76f, 0.75f)}, 65 {CFX_PointF(0.76f, 0.75f), CFX_PointF(0.73f, 0.80f), 66 CFX_PointF(0.68f, 0.75f)}, 67 {CFX_PointF(0.68f, 0.74f), CFX_PointF(0.68f, 0.74f), 68 CFX_PointF(0.44f, 0.47f)}, 69 {CFX_PointF(0.43f, 0.47f), CFX_PointF(0.40f, 0.47f), 70 CFX_PointF(0.41f, 0.58f)}, 71 {CFX_PointF(0.40f, 0.60f), CFX_PointF(0.28f, 0.66f), 72 CFX_PointF(0.30f, 0.56f)}}; 73 74 for (size_t i = 0; i < FX_ArraySize(pts); ++i) { 75 for (size_t j = 0; j < FX_ArraySize(pts[0]); ++j) { 76 pts[i][j].x = pts[i][j].x * fWidth + crBBox.left; 77 pts[i][j].y *= pts[i][j].y * fHeight + crBBox.bottom; 78 } 79 } 80 81 CFX_ByteTextBuf csAP; 82 csAP << pts[0][0].x << " " << pts[0][0].y << " m\n"; 83 84 for (size_t i = 0; i < FX_ArraySize(pts); ++i) { 85 size_t nNext = i < FX_ArraySize(pts) - 1 ? i + 1 : 0; 86 87 FX_FLOAT px1 = pts[i][1].x - pts[i][0].x; 88 FX_FLOAT py1 = pts[i][1].y - pts[i][0].y; 89 FX_FLOAT px2 = pts[i][2].x - pts[nNext][0].x; 90 FX_FLOAT py2 = pts[i][2].y - pts[nNext][0].y; 91 92 csAP << pts[i][0].x + px1 * FX_BEZIER << " " 93 << pts[i][0].y + py1 * FX_BEZIER << " " 94 << pts[nNext][0].x + px2 * FX_BEZIER << " " 95 << pts[nNext][0].y + py2 * FX_BEZIER << " " << pts[nNext][0].x << " " 96 << pts[nNext][0].y << " c\n"; 97 } 98 99 return csAP.MakeString(); 100} 101 102CFX_ByteString CPWL_Utils::GetAP_Circle(const CFX_FloatRect& crBBox) { 103 CFX_ByteTextBuf csAP; 104 105 FX_FLOAT fWidth = crBBox.right - crBBox.left; 106 FX_FLOAT fHeight = crBBox.top - crBBox.bottom; 107 108 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); 109 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); 110 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); 111 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); 112 113 csAP << pt1.x << " " << pt1.y << " m\n"; 114 115 FX_FLOAT px = pt2.x - pt1.x; 116 FX_FLOAT py = pt2.y - pt1.y; 117 118 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " 119 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y 120 << " c\n"; 121 122 px = pt3.x - pt2.x; 123 py = pt2.y - pt3.y; 124 125 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " 126 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; 127 128 px = pt3.x - pt4.x; 129 py = pt3.y - pt4.y; 130 131 csAP << pt3.x << " " << pt3.y - py * FX_BEZIER << " " 132 << pt4.x + px * FX_BEZIER << " " << pt4.y << " " << pt4.x << " " << pt4.y 133 << " c\n"; 134 135 px = pt4.x - pt1.x; 136 py = pt1.y - pt4.y; 137 138 csAP << pt4.x - px * FX_BEZIER << " " << pt4.y << " " << pt1.x << " " 139 << pt1.y - py * FX_BEZIER << " " << pt1.x << " " << pt1.y << " c\n"; 140 141 return csAP.MakeString(); 142} 143 144CFX_ByteString CPWL_Utils::GetAP_Cross(const CFX_FloatRect& crBBox) { 145 CFX_ByteTextBuf csAP; 146 147 csAP << crBBox.left << " " << crBBox.top << " m\n"; 148 csAP << crBBox.right << " " << crBBox.bottom << " l\n"; 149 csAP << crBBox.left << " " << crBBox.bottom << " m\n"; 150 csAP << crBBox.right << " " << crBBox.top << " l\n"; 151 152 return csAP.MakeString(); 153} 154 155CFX_ByteString CPWL_Utils::GetAP_Diamond(const CFX_FloatRect& crBBox) { 156 CFX_ByteTextBuf csAP; 157 158 FX_FLOAT fWidth = crBBox.right - crBBox.left; 159 FX_FLOAT fHeight = crBBox.top - crBBox.bottom; 160 161 CFX_PointF pt1(crBBox.left, crBBox.bottom + fHeight / 2); 162 CFX_PointF pt2(crBBox.left + fWidth / 2, crBBox.top); 163 CFX_PointF pt3(crBBox.right, crBBox.bottom + fHeight / 2); 164 CFX_PointF pt4(crBBox.left + fWidth / 2, crBBox.bottom); 165 166 csAP << pt1.x << " " << pt1.y << " m\n"; 167 csAP << pt2.x << " " << pt2.y << " l\n"; 168 csAP << pt3.x << " " << pt3.y << " l\n"; 169 csAP << pt4.x << " " << pt4.y << " l\n"; 170 csAP << pt1.x << " " << pt1.y << " l\n"; 171 172 return csAP.MakeString(); 173} 174 175CFX_ByteString CPWL_Utils::GetAP_Square(const CFX_FloatRect& crBBox) { 176 CFX_ByteTextBuf csAP; 177 178 csAP << crBBox.left << " " << crBBox.top << " m\n"; 179 csAP << crBBox.right << " " << crBBox.top << " l\n"; 180 csAP << crBBox.right << " " << crBBox.bottom << " l\n"; 181 csAP << crBBox.left << " " << crBBox.bottom << " l\n"; 182 csAP << crBBox.left << " " << crBBox.top << " l\n"; 183 184 return csAP.MakeString(); 185} 186 187CFX_ByteString CPWL_Utils::GetAP_Star(const CFX_FloatRect& crBBox) { 188 CFX_ByteTextBuf csAP; 189 190 FX_FLOAT fRadius = 191 (crBBox.top - crBBox.bottom) / (1 + (FX_FLOAT)cos(FX_PI / 5.0f)); 192 CFX_PointF ptCenter = CFX_PointF((crBBox.left + crBBox.right) / 2.0f, 193 (crBBox.top + crBBox.bottom) / 2.0f); 194 195 FX_FLOAT px[5], py[5]; 196 197 FX_FLOAT fAngel = FX_PI / 10.0f; 198 199 for (int32_t i = 0; i < 5; i++) { 200 px[i] = ptCenter.x + fRadius * (FX_FLOAT)cos(fAngel); 201 py[i] = ptCenter.y + fRadius * (FX_FLOAT)sin(fAngel); 202 203 fAngel += FX_PI * 2 / 5.0f; 204 } 205 206 csAP << px[0] << " " << py[0] << " m\n"; 207 208 int32_t nNext = 0; 209 for (int32_t j = 0; j < 5; j++) { 210 nNext += 2; 211 if (nNext >= 5) 212 nNext -= 5; 213 csAP << px[nNext] << " " << py[nNext] << " l\n"; 214 } 215 216 return csAP.MakeString(); 217} 218 219CFX_ByteString CPWL_Utils::GetAP_HalfCircle(const CFX_FloatRect& crBBox, 220 FX_FLOAT fRotate) { 221 CFX_ByteTextBuf csAP; 222 223 FX_FLOAT fWidth = crBBox.right - crBBox.left; 224 FX_FLOAT fHeight = crBBox.top - crBBox.bottom; 225 226 CFX_PointF pt1(-fWidth / 2, 0); 227 CFX_PointF pt2(0, fHeight / 2); 228 CFX_PointF pt3(fWidth / 2, 0); 229 230 FX_FLOAT px, py; 231 232 csAP << cos(fRotate) << " " << sin(fRotate) << " " << -sin(fRotate) << " " 233 << cos(fRotate) << " " << crBBox.left + fWidth / 2 << " " 234 << crBBox.bottom + fHeight / 2 << " cm\n"; 235 236 csAP << pt1.x << " " << pt1.y << " m\n"; 237 238 px = pt2.x - pt1.x; 239 py = pt2.y - pt1.y; 240 241 csAP << pt1.x << " " << pt1.y + py * FX_BEZIER << " " 242 << pt2.x - px * FX_BEZIER << " " << pt2.y << " " << pt2.x << " " << pt2.y 243 << " c\n"; 244 245 px = pt3.x - pt2.x; 246 py = pt2.y - pt3.y; 247 248 csAP << pt2.x + px * FX_BEZIER << " " << pt2.y << " " << pt3.x << " " 249 << pt3.y + py * FX_BEZIER << " " << pt3.x << " " << pt3.y << " c\n"; 250 251 return csAP.MakeString(); 252} 253 254CFX_FloatRect CPWL_Utils::InflateRect(const CFX_FloatRect& rcRect, 255 FX_FLOAT fSize) { 256 if (rcRect.IsEmpty()) 257 return rcRect; 258 259 CFX_FloatRect rcNew(rcRect.left - fSize, rcRect.bottom - fSize, 260 rcRect.right + fSize, rcRect.top + fSize); 261 rcNew.Normalize(); 262 return rcNew; 263} 264 265CFX_FloatRect CPWL_Utils::DeflateRect(const CFX_FloatRect& rcRect, 266 FX_FLOAT fSize) { 267 if (rcRect.IsEmpty()) 268 return rcRect; 269 270 CFX_FloatRect rcNew(rcRect.left + fSize, rcRect.bottom + fSize, 271 rcRect.right - fSize, rcRect.top - fSize); 272 rcNew.Normalize(); 273 return rcNew; 274} 275 276CFX_FloatRect CPWL_Utils::ScaleRect(const CFX_FloatRect& rcRect, 277 FX_FLOAT fScale) { 278 FX_FLOAT fHalfWidth = (rcRect.right - rcRect.left) / 2.0f; 279 FX_FLOAT fHalfHeight = (rcRect.top - rcRect.bottom) / 2.0f; 280 281 CFX_PointF ptCenter = CFX_PointF((rcRect.left + rcRect.right) / 2, 282 (rcRect.top + rcRect.bottom) / 2); 283 284 return CFX_FloatRect( 285 ptCenter.x - fHalfWidth * fScale, ptCenter.y - fHalfHeight * fScale, 286 ptCenter.x + fHalfWidth * fScale, ptCenter.y + fHalfHeight * fScale); 287} 288 289CFX_ByteString CPWL_Utils::GetRectFillAppStream(const CFX_FloatRect& rect, 290 const CPWL_Color& color) { 291 CFX_ByteTextBuf sAppStream; 292 CFX_ByteString sColor = GetColorAppStream(color, true); 293 if (sColor.GetLength() > 0) { 294 sAppStream << "q\n" << sColor; 295 sAppStream << rect.left << " " << rect.bottom << " " 296 << rect.right - rect.left << " " << rect.top - rect.bottom 297 << " re f\nQ\n"; 298 } 299 300 return sAppStream.MakeString(); 301} 302 303CFX_ByteString CPWL_Utils::GetCircleFillAppStream(const CFX_FloatRect& rect, 304 const CPWL_Color& color) { 305 CFX_ByteTextBuf sAppStream; 306 CFX_ByteString sColor = GetColorAppStream(color, true); 307 if (sColor.GetLength() > 0) { 308 sAppStream << "q\n" << sColor << CPWL_Utils::GetAP_Circle(rect) << "f\nQ\n"; 309 } 310 return sAppStream.MakeString(); 311} 312 313CFX_FloatRect CPWL_Utils::GetCenterSquare(const CFX_FloatRect& rect) { 314 FX_FLOAT fWidth = rect.right - rect.left; 315 FX_FLOAT fHeight = rect.top - rect.bottom; 316 317 FX_FLOAT fCenterX = (rect.left + rect.right) / 2.0f; 318 FX_FLOAT fCenterY = (rect.top + rect.bottom) / 2.0f; 319 320 FX_FLOAT fRadius = (fWidth > fHeight) ? fHeight / 2 : fWidth / 2; 321 322 return CFX_FloatRect(fCenterX - fRadius, fCenterY - fRadius, 323 fCenterX + fRadius, fCenterY + fRadius); 324} 325 326CFX_ByteString CPWL_Utils::GetEditAppStream(CFX_Edit* pEdit, 327 const CFX_PointF& ptOffset, 328 const CPVT_WordRange* pRange, 329 bool bContinuous, 330 uint16_t SubWord) { 331 return CFX_Edit::GetEditAppearanceStream(pEdit, ptOffset, pRange, bContinuous, 332 SubWord); 333} 334 335CFX_ByteString CPWL_Utils::GetEditSelAppStream(CFX_Edit* pEdit, 336 const CFX_PointF& ptOffset, 337 const CPVT_WordRange* pRange) { 338 return CFX_Edit::GetSelectAppearanceStream(pEdit, ptOffset, pRange); 339} 340 341CFX_ByteString CPWL_Utils::GetPushButtonAppStream(const CFX_FloatRect& rcBBox, 342 IPVT_FontMap* pFontMap, 343 CPDF_Stream* pIconStream, 344 CPDF_IconFit& IconFit, 345 const CFX_WideString& sLabel, 346 const CPWL_Color& crText, 347 FX_FLOAT fFontSize, 348 int32_t nLayOut) { 349 const FX_FLOAT fAutoFontScale = 1.0f / 3.0f; 350 351 std::unique_ptr<CFX_Edit> pEdit(new CFX_Edit); 352 pEdit->SetFontMap(pFontMap); 353 pEdit->SetAlignmentH(1, true); 354 pEdit->SetAlignmentV(1, true); 355 pEdit->SetMultiLine(false, true); 356 pEdit->SetAutoReturn(false, true); 357 if (IsFloatZero(fFontSize)) 358 pEdit->SetAutoFontSize(true, true); 359 else 360 pEdit->SetFontSize(fFontSize); 361 362 pEdit->Initialize(); 363 pEdit->SetText(sLabel); 364 365 CFX_FloatRect rcLabelContent = pEdit->GetContentRect(); 366 CPWL_Icon Icon; 367 PWL_CREATEPARAM cp; 368 cp.dwFlags = PWS_VISIBLE; 369 Icon.Create(cp); 370 Icon.SetIconFit(&IconFit); 371 Icon.SetPDFStream(pIconStream); 372 373 CFX_FloatRect rcLabel = CFX_FloatRect(0, 0, 0, 0); 374 CFX_FloatRect rcIcon = CFX_FloatRect(0, 0, 0, 0); 375 FX_FLOAT fWidth = 0.0f; 376 FX_FLOAT fHeight = 0.0f; 377 378 switch (nLayOut) { 379 case PPBL_LABEL: 380 rcLabel = rcBBox; 381 rcIcon = CFX_FloatRect(0, 0, 0, 0); 382 break; 383 case PPBL_ICON: 384 rcIcon = rcBBox; 385 rcLabel = CFX_FloatRect(0, 0, 0, 0); 386 break; 387 case PPBL_ICONTOPLABELBOTTOM: 388 389 if (pIconStream) { 390 if (IsFloatZero(fFontSize)) { 391 fHeight = rcBBox.top - rcBBox.bottom; 392 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, 393 rcBBox.bottom + fHeight * fAutoFontScale); 394 rcIcon = 395 CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, rcBBox.top); 396 } else { 397 fHeight = rcLabelContent.Height(); 398 399 if (rcBBox.bottom + fHeight > rcBBox.top) { 400 rcIcon = CFX_FloatRect(0, 0, 0, 0); 401 rcLabel = rcBBox; 402 } else { 403 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, 404 rcBBox.bottom + fHeight); 405 rcIcon = CFX_FloatRect(rcBBox.left, rcLabel.top, rcBBox.right, 406 rcBBox.top); 407 } 408 } 409 } else { 410 rcLabel = rcBBox; 411 rcIcon = CFX_FloatRect(0, 0, 0, 0); 412 } 413 414 break; 415 case PPBL_LABELTOPICONBOTTOM: 416 417 if (pIconStream) { 418 if (IsFloatZero(fFontSize)) { 419 fHeight = rcBBox.top - rcBBox.bottom; 420 rcLabel = 421 CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight * fAutoFontScale, 422 rcBBox.right, rcBBox.top); 423 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, 424 rcLabel.bottom); 425 } else { 426 fHeight = rcLabelContent.Height(); 427 428 if (rcBBox.bottom + fHeight > rcBBox.top) { 429 rcIcon = CFX_FloatRect(0, 0, 0, 0); 430 rcLabel = rcBBox; 431 } else { 432 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.top - fHeight, 433 rcBBox.right, rcBBox.top); 434 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcBBox.right, 435 rcLabel.bottom); 436 } 437 } 438 } else { 439 rcLabel = rcBBox; 440 rcIcon = CFX_FloatRect(0, 0, 0, 0); 441 } 442 443 break; 444 case PPBL_ICONLEFTLABELRIGHT: 445 446 if (pIconStream) { 447 if (IsFloatZero(fFontSize)) { 448 fWidth = rcBBox.right - rcBBox.left; 449 rcLabel = CFX_FloatRect(rcBBox.right - fWidth * fAutoFontScale, 450 rcBBox.bottom, rcBBox.right, rcBBox.top); 451 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, 452 rcBBox.top); 453 454 if (rcLabelContent.Width() < fWidth * fAutoFontScale) { 455 } else { 456 if (rcLabelContent.Width() < fWidth) { 457 rcLabel = CFX_FloatRect(rcBBox.right - rcLabelContent.Width(), 458 rcBBox.bottom, rcBBox.right, rcBBox.top); 459 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, 460 rcBBox.top); 461 } else { 462 rcLabel = rcBBox; 463 rcIcon = CFX_FloatRect(0, 0, 0, 0); 464 } 465 } 466 } else { 467 fWidth = rcLabelContent.Width(); 468 469 if (rcBBox.left + fWidth > rcBBox.right) { 470 rcLabel = rcBBox; 471 rcIcon = CFX_FloatRect(0, 0, 0, 0); 472 } else { 473 rcLabel = CFX_FloatRect(rcBBox.right - fWidth, rcBBox.bottom, 474 rcBBox.right, rcBBox.top); 475 rcIcon = CFX_FloatRect(rcBBox.left, rcBBox.bottom, rcLabel.left, 476 rcBBox.top); 477 } 478 } 479 } else { 480 rcLabel = rcBBox; 481 rcIcon = CFX_FloatRect(0, 0, 0, 0); 482 } 483 484 break; 485 case PPBL_LABELLEFTICONRIGHT: 486 487 if (pIconStream) { 488 if (IsFloatZero(fFontSize)) { 489 fWidth = rcBBox.right - rcBBox.left; 490 rcLabel = 491 CFX_FloatRect(rcBBox.left, rcBBox.bottom, 492 rcBBox.left + fWidth * fAutoFontScale, rcBBox.top); 493 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, 494 rcBBox.top); 495 496 if (rcLabelContent.Width() < fWidth * fAutoFontScale) { 497 } else { 498 if (rcLabelContent.Width() < fWidth) { 499 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, 500 rcBBox.left + rcLabelContent.Width(), 501 rcBBox.top); 502 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, 503 rcBBox.top); 504 } else { 505 rcLabel = rcBBox; 506 rcIcon = CFX_FloatRect(0, 0, 0, 0); 507 } 508 } 509 } else { 510 fWidth = rcLabelContent.Width(); 511 512 if (rcBBox.left + fWidth > rcBBox.right) { 513 rcLabel = rcBBox; 514 rcIcon = CFX_FloatRect(0, 0, 0, 0); 515 } else { 516 rcLabel = CFX_FloatRect(rcBBox.left, rcBBox.bottom, 517 rcBBox.left + fWidth, rcBBox.top); 518 rcIcon = CFX_FloatRect(rcLabel.right, rcBBox.bottom, rcBBox.right, 519 rcBBox.top); 520 } 521 } 522 } else { 523 rcLabel = rcBBox; 524 rcIcon = CFX_FloatRect(0, 0, 0, 0); 525 } 526 527 break; 528 case PPBL_LABELOVERICON: 529 rcLabel = rcBBox; 530 rcIcon = rcBBox; 531 break; 532 } 533 534 CFX_ByteTextBuf sAppStream, sTemp; 535 536 if (!rcIcon.IsEmpty()) { 537 Icon.Move(rcIcon, false, false); 538 sTemp << Icon.GetImageAppStream(); 539 } 540 541 Icon.Destroy(); 542 543 if (!rcLabel.IsEmpty()) { 544 pEdit->SetPlateRect(rcLabel); 545 CFX_ByteString sEdit = 546 CPWL_Utils::GetEditAppStream(pEdit.get(), CFX_PointF(0.0f, 0.0f)); 547 if (sEdit.GetLength() > 0) { 548 sTemp << "BT\n" 549 << CPWL_Utils::GetColorAppStream(crText) << sEdit << "ET\n"; 550 } 551 } 552 553 if (sTemp.GetSize() > 0) { 554 sAppStream << "q\n" 555 << rcBBox.left << " " << rcBBox.bottom << " " 556 << rcBBox.right - rcBBox.left << " " 557 << rcBBox.top - rcBBox.bottom << " re W n\n"; 558 sAppStream << sTemp << "Q\n"; 559 } 560 return sAppStream.MakeString(); 561} 562 563CFX_ByteString CPWL_Utils::GetColorAppStream(const CPWL_Color& color, 564 const bool& bFillOrStroke) { 565 CFX_ByteTextBuf sColorStream; 566 567 switch (color.nColorType) { 568 case COLORTYPE_RGB: 569 sColorStream << color.fColor1 << " " << color.fColor2 << " " 570 << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG") 571 << "\n"; 572 break; 573 case COLORTYPE_GRAY: 574 sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") 575 << "\n"; 576 break; 577 case COLORTYPE_CMYK: 578 sColorStream << color.fColor1 << " " << color.fColor2 << " " 579 << color.fColor3 << " " << color.fColor4 << " " 580 << (bFillOrStroke ? "k" : "K") << "\n"; 581 break; 582 } 583 584 return sColorStream.MakeString(); 585} 586 587CFX_ByteString CPWL_Utils::GetBorderAppStream(const CFX_FloatRect& rect, 588 FX_FLOAT fWidth, 589 const CPWL_Color& color, 590 const CPWL_Color& crLeftTop, 591 const CPWL_Color& crRightBottom, 592 BorderStyle nStyle, 593 const CPWL_Dash& dash) { 594 CFX_ByteTextBuf sAppStream; 595 CFX_ByteString sColor; 596 597 FX_FLOAT fLeft = rect.left; 598 FX_FLOAT fRight = rect.right; 599 FX_FLOAT fTop = rect.top; 600 FX_FLOAT fBottom = rect.bottom; 601 602 if (fWidth > 0.0f) { 603 FX_FLOAT fHalfWidth = fWidth / 2.0f; 604 605 sAppStream << "q\n"; 606 607 switch (nStyle) { 608 default: 609 case BorderStyle::SOLID: 610 sColor = CPWL_Utils::GetColorAppStream(color, true); 611 if (sColor.GetLength() > 0) { 612 sAppStream << sColor; 613 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " 614 << fTop - fBottom << " re\n"; 615 sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " 616 << fRight - fLeft - fWidth * 2 << " " 617 << fTop - fBottom - fWidth * 2 << " re\n"; 618 sAppStream << "f*\n"; 619 } 620 break; 621 case BorderStyle::DASH: 622 sColor = CPWL_Utils::GetColorAppStream(color, false); 623 if (sColor.GetLength() > 0) { 624 sAppStream << sColor; 625 sAppStream << fWidth << " w" 626 << " [" << dash.nDash << " " << dash.nGap << "] " 627 << dash.nPhase << " d\n"; 628 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 629 << " m\n"; 630 sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 631 << " l\n"; 632 sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 633 << " l\n"; 634 sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 635 << " l\n"; 636 sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 637 << " l S\n"; 638 } 639 break; 640 case BorderStyle::BEVELED: 641 case BorderStyle::INSET: 642 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, true); 643 if (sColor.GetLength() > 0) { 644 sAppStream << sColor; 645 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth 646 << " m\n"; 647 sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth 648 << " l\n"; 649 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth 650 << " l\n"; 651 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 652 << " l\n"; 653 sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 654 << " l\n"; 655 sAppStream << fLeft + fHalfWidth * 2 << " " 656 << fBottom + fHalfWidth * 2 << " l f\n"; 657 } 658 659 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, true); 660 if (sColor.GetLength() > 0) { 661 sAppStream << sColor; 662 sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth 663 << " m\n"; 664 sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth 665 << " l\n"; 666 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth 667 << " l\n"; 668 sAppStream << fLeft + fHalfWidth * 2 << " " 669 << fBottom + fHalfWidth * 2 << " l\n"; 670 sAppStream << fRight - fHalfWidth * 2 << " " 671 << fBottom + fHalfWidth * 2 << " l\n"; 672 sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 673 << " l f\n"; 674 } 675 676 sColor = CPWL_Utils::GetColorAppStream(color, true); 677 if (sColor.GetLength() > 0) { 678 sAppStream << sColor; 679 sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " 680 << fTop - fBottom << " re\n"; 681 sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " 682 << fRight - fLeft - fHalfWidth * 2 << " " 683 << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; 684 } 685 break; 686 case BorderStyle::UNDERLINE: 687 sColor = CPWL_Utils::GetColorAppStream(color, false); 688 if (sColor.GetLength() > 0) { 689 sAppStream << sColor; 690 sAppStream << fWidth << " w\n"; 691 sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; 692 sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; 693 } 694 break; 695 } 696 697 sAppStream << "Q\n"; 698 } 699 700 return sAppStream.MakeString(); 701} 702 703CFX_ByteString CPWL_Utils::GetCircleBorderAppStream( 704 const CFX_FloatRect& rect, 705 FX_FLOAT fWidth, 706 const CPWL_Color& color, 707 const CPWL_Color& crLeftTop, 708 const CPWL_Color& crRightBottom, 709 BorderStyle nStyle, 710 const CPWL_Dash& dash) { 711 CFX_ByteTextBuf sAppStream; 712 CFX_ByteString sColor; 713 714 if (fWidth > 0.0f) { 715 sAppStream << "q\n"; 716 717 switch (nStyle) { 718 default: 719 case BorderStyle::SOLID: 720 case BorderStyle::UNDERLINE: { 721 sColor = CPWL_Utils::GetColorAppStream(color, false); 722 if (sColor.GetLength() > 0) { 723 sAppStream << "q\n" << fWidth << " w\n" << sColor 724 << CPWL_Utils::GetAP_Circle( 725 CPWL_Utils::DeflateRect(rect, fWidth / 2.0f)) 726 << " S\nQ\n"; 727 } 728 } break; 729 case BorderStyle::DASH: { 730 sColor = CPWL_Utils::GetColorAppStream(color, false); 731 if (sColor.GetLength() > 0) { 732 sAppStream << "q\n" << fWidth << " w\n" 733 << "[" << dash.nDash << " " << dash.nGap << "] " 734 << dash.nPhase << " d\n" << sColor 735 << CPWL_Utils::GetAP_Circle( 736 CPWL_Utils::DeflateRect(rect, fWidth / 2.0f)) 737 << " S\nQ\n"; 738 } 739 } break; 740 case BorderStyle::BEVELED: { 741 FX_FLOAT fHalfWidth = fWidth / 2.0f; 742 743 sColor = CPWL_Utils::GetColorAppStream(color, false); 744 if (sColor.GetLength() > 0) { 745 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 746 << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; 747 } 748 749 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); 750 if (sColor.GetLength() > 0) { 751 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 752 << CPWL_Utils::GetAP_HalfCircle( 753 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), 754 FX_PI / 4.0f) 755 << " S\nQ\n"; 756 } 757 758 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); 759 if (sColor.GetLength() > 0) { 760 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 761 << CPWL_Utils::GetAP_HalfCircle( 762 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), 763 FX_PI * 5 / 4.0f) 764 << " S\nQ\n"; 765 } 766 } break; 767 case BorderStyle::INSET: { 768 FX_FLOAT fHalfWidth = fWidth / 2.0f; 769 770 sColor = CPWL_Utils::GetColorAppStream(color, false); 771 if (sColor.GetLength() > 0) { 772 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 773 << CPWL_Utils::GetAP_Circle(rect) << " S\nQ\n"; 774 } 775 776 sColor = CPWL_Utils::GetColorAppStream(crLeftTop, false); 777 if (sColor.GetLength() > 0) { 778 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 779 << CPWL_Utils::GetAP_HalfCircle( 780 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), 781 FX_PI / 4.0f) 782 << " S\nQ\n"; 783 } 784 785 sColor = CPWL_Utils::GetColorAppStream(crRightBottom, false); 786 if (sColor.GetLength() > 0) { 787 sAppStream << "q\n" << fHalfWidth << " w\n" << sColor 788 << CPWL_Utils::GetAP_HalfCircle( 789 CPWL_Utils::DeflateRect(rect, fHalfWidth * 0.75f), 790 FX_PI * 5 / 4.0f) 791 << " S\nQ\n"; 792 } 793 } break; 794 } 795 796 sAppStream << "Q\n"; 797 } 798 799 return sAppStream.MakeString(); 800} 801 802CFX_ByteString CPWL_Utils::GetAppStream_Check(const CFX_FloatRect& rcBBox, 803 const CPWL_Color& crText) { 804 CFX_ByteTextBuf sAP; 805 sAP << "q\n" 806 << CPWL_Utils::GetColorAppStream(crText, true) 807 << CPWL_Utils::GetAP_Check(rcBBox) << "f\nQ\n"; 808 return sAP.MakeString(); 809} 810 811CFX_ByteString CPWL_Utils::GetAppStream_Circle(const CFX_FloatRect& rcBBox, 812 const CPWL_Color& crText) { 813 CFX_ByteTextBuf sAP; 814 sAP << "q\n" 815 << CPWL_Utils::GetColorAppStream(crText, true) 816 << CPWL_Utils::GetAP_Circle(rcBBox) << "f\nQ\n"; 817 return sAP.MakeString(); 818} 819 820CFX_ByteString CPWL_Utils::GetAppStream_Cross(const CFX_FloatRect& rcBBox, 821 const CPWL_Color& crText) { 822 CFX_ByteTextBuf sAP; 823 sAP << "q\n" 824 << CPWL_Utils::GetColorAppStream(crText, false) 825 << CPWL_Utils::GetAP_Cross(rcBBox) << "S\nQ\n"; 826 return sAP.MakeString(); 827} 828 829CFX_ByteString CPWL_Utils::GetAppStream_Diamond(const CFX_FloatRect& rcBBox, 830 const CPWL_Color& crText) { 831 CFX_ByteTextBuf sAP; 832 sAP << "q\n1 w\n" 833 << CPWL_Utils::GetColorAppStream(crText, true) 834 << CPWL_Utils::GetAP_Diamond(rcBBox) << "f\nQ\n"; 835 return sAP.MakeString(); 836} 837 838CFX_ByteString CPWL_Utils::GetAppStream_Square(const CFX_FloatRect& rcBBox, 839 const CPWL_Color& crText) { 840 CFX_ByteTextBuf sAP; 841 sAP << "q\n" 842 << CPWL_Utils::GetColorAppStream(crText, true) 843 << CPWL_Utils::GetAP_Square(rcBBox) << "f\nQ\n"; 844 return sAP.MakeString(); 845} 846 847CFX_ByteString CPWL_Utils::GetAppStream_Star(const CFX_FloatRect& rcBBox, 848 const CPWL_Color& crText) { 849 CFX_ByteTextBuf sAP; 850 sAP << "q\n" 851 << CPWL_Utils::GetColorAppStream(crText, true) 852 << CPWL_Utils::GetAP_Star(rcBBox) << "f\nQ\n"; 853 return sAP.MakeString(); 854} 855 856CFX_ByteString CPWL_Utils::GetCheckBoxAppStream(const CFX_FloatRect& rcBBox, 857 int32_t nStyle, 858 const CPWL_Color& crText) { 859 CFX_FloatRect rcCenter = GetCenterSquare(rcBBox); 860 switch (nStyle) { 861 default: 862 case PCS_CHECK: 863 return GetAppStream_Check(rcCenter, crText); 864 case PCS_CIRCLE: 865 return GetAppStream_Circle(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 866 case PCS_CROSS: 867 return GetAppStream_Cross(rcCenter, crText); 868 case PCS_DIAMOND: 869 return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 870 case PCS_SQUARE: 871 return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 872 case PCS_STAR: 873 return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 874 } 875} 876 877CFX_ByteString CPWL_Utils::GetRadioButtonAppStream(const CFX_FloatRect& rcBBox, 878 int32_t nStyle, 879 const CPWL_Color& crText) { 880 CFX_FloatRect rcCenter = GetCenterSquare(rcBBox); 881 switch (nStyle) { 882 default: 883 case PCS_CHECK: 884 return GetAppStream_Check(rcCenter, crText); 885 case PCS_CIRCLE: 886 return GetAppStream_Circle(ScaleRect(rcCenter, 1.0f / 2.0f), crText); 887 case PCS_CROSS: 888 return GetAppStream_Cross(rcCenter, crText); 889 case PCS_DIAMOND: 890 return GetAppStream_Diamond(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 891 case PCS_SQUARE: 892 return GetAppStream_Square(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 893 case PCS_STAR: 894 return GetAppStream_Star(ScaleRect(rcCenter, 2.0f / 3.0f), crText); 895 } 896} 897 898CFX_ByteString CPWL_Utils::GetDropButtonAppStream(const CFX_FloatRect& rcBBox) { 899 CFX_ByteTextBuf sAppStream; 900 901 if (!rcBBox.IsEmpty()) { 902 sAppStream << "q\n" 903 << CPWL_Utils::GetColorAppStream( 904 CPWL_Color(COLORTYPE_RGB, 220.0f / 255.0f, 905 220.0f / 255.0f, 220.0f / 255.0f), 906 true); 907 sAppStream << rcBBox.left << " " << rcBBox.bottom << " " 908 << rcBBox.right - rcBBox.left << " " 909 << rcBBox.top - rcBBox.bottom << " re f\n"; 910 sAppStream << "Q\n"; 911 912 sAppStream << "q\n" 913 << CPWL_Utils::GetBorderAppStream( 914 rcBBox, 2, CPWL_Color(COLORTYPE_GRAY, 0), 915 CPWL_Color(COLORTYPE_GRAY, 1), 916 CPWL_Color(COLORTYPE_GRAY, 0.5), BorderStyle::BEVELED, 917 CPWL_Dash(3, 0, 0)) 918 << "Q\n"; 919 920 CFX_PointF ptCenter = CFX_PointF((rcBBox.left + rcBBox.right) / 2, 921 (rcBBox.top + rcBBox.bottom) / 2); 922 if (IsFloatBigger(rcBBox.right - rcBBox.left, 6) && 923 IsFloatBigger(rcBBox.top - rcBBox.bottom, 6)) { 924 sAppStream << "q\n" 925 << " 0 g\n"; 926 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; 927 sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; 928 sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; 929 sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; 930 sAppStream << "Q\n"; 931 } 932 } 933 934 return sAppStream.MakeString(); 935} 936 937void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice, 938 CFX_Matrix* pUser2Device, 939 const CFX_FloatRect& rect, 940 const FX_COLORREF& color) { 941 CFX_PathData path; 942 CFX_FloatRect rcTemp(rect); 943 path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); 944 pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_WINDING); 945} 946 947void CPWL_Utils::DrawFillArea(CFX_RenderDevice* pDevice, 948 CFX_Matrix* pUser2Device, 949 const CFX_PointF* pPts, 950 int32_t nCount, 951 const FX_COLORREF& color) { 952 CFX_PathData path; 953 path.AppendPoint(pPts[0], FXPT_TYPE::MoveTo, false); 954 for (int32_t i = 1; i < nCount; i++) 955 path.AppendPoint(pPts[i], FXPT_TYPE::LineTo, false); 956 957 pDevice->DrawPath(&path, pUser2Device, nullptr, color, 0, FXFILL_ALTERNATE); 958} 959 960void CPWL_Utils::DrawStrokeRect(CFX_RenderDevice* pDevice, 961 CFX_Matrix* pUser2Device, 962 const CFX_FloatRect& rect, 963 const FX_COLORREF& color, 964 FX_FLOAT fWidth) { 965 CFX_PathData path; 966 CFX_FloatRect rcTemp(rect); 967 path.AppendRect(rcTemp.left, rcTemp.bottom, rcTemp.right, rcTemp.top); 968 969 CFX_GraphStateData gsd; 970 gsd.m_LineWidth = fWidth; 971 972 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); 973} 974 975void CPWL_Utils::DrawStrokeLine(CFX_RenderDevice* pDevice, 976 CFX_Matrix* pUser2Device, 977 const CFX_PointF& ptMoveTo, 978 const CFX_PointF& ptLineTo, 979 const FX_COLORREF& color, 980 FX_FLOAT fWidth) { 981 CFX_PathData path; 982 path.AppendPoint(ptMoveTo, FXPT_TYPE::MoveTo, false); 983 path.AppendPoint(ptLineTo, FXPT_TYPE::LineTo, false); 984 985 CFX_GraphStateData gsd; 986 gsd.m_LineWidth = fWidth; 987 988 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, color, FXFILL_ALTERNATE); 989} 990 991void CPWL_Utils::DrawFillRect(CFX_RenderDevice* pDevice, 992 CFX_Matrix* pUser2Device, 993 const CFX_FloatRect& rect, 994 const CPWL_Color& color, 995 int32_t nTransparency) { 996 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rect, 997 color.ToFXColor(nTransparency)); 998} 999 1000void CPWL_Utils::DrawShadow(CFX_RenderDevice* pDevice, 1001 CFX_Matrix* pUser2Device, 1002 bool bVertical, 1003 bool bHorizontal, 1004 CFX_FloatRect rect, 1005 int32_t nTransparency, 1006 int32_t nStartGray, 1007 int32_t nEndGray) { 1008 FX_FLOAT fStepGray = 1.0f; 1009 1010 if (bVertical) { 1011 fStepGray = (nEndGray - nStartGray) / rect.Height(); 1012 1013 for (FX_FLOAT fy = rect.bottom + 0.5f; fy <= rect.top - 0.5f; fy += 1.0f) { 1014 int32_t nGray = nStartGray + (int32_t)(fStepGray * (fy - rect.bottom)); 1015 CPWL_Utils::DrawStrokeLine( 1016 pDevice, pUser2Device, CFX_PointF(rect.left, fy), 1017 CFX_PointF(rect.right, fy), 1018 ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); 1019 } 1020 } 1021 1022 if (bHorizontal) { 1023 fStepGray = (nEndGray - nStartGray) / rect.Width(); 1024 1025 for (FX_FLOAT fx = rect.left + 0.5f; fx <= rect.right - 0.5f; fx += 1.0f) { 1026 int32_t nGray = nStartGray + (int32_t)(fStepGray * (fx - rect.left)); 1027 CPWL_Utils::DrawStrokeLine( 1028 pDevice, pUser2Device, CFX_PointF(fx, rect.bottom), 1029 CFX_PointF(fx, rect.top), 1030 ArgbEncode(nTransparency, nGray, nGray, nGray), 1.5f); 1031 } 1032 } 1033} 1034 1035void CPWL_Utils::DrawBorder(CFX_RenderDevice* pDevice, 1036 CFX_Matrix* pUser2Device, 1037 const CFX_FloatRect& rect, 1038 FX_FLOAT fWidth, 1039 const CPWL_Color& color, 1040 const CPWL_Color& crLeftTop, 1041 const CPWL_Color& crRightBottom, 1042 BorderStyle nStyle, 1043 int32_t nTransparency) { 1044 FX_FLOAT fLeft = rect.left; 1045 FX_FLOAT fRight = rect.right; 1046 FX_FLOAT fTop = rect.top; 1047 FX_FLOAT fBottom = rect.bottom; 1048 1049 if (fWidth > 0.0f) { 1050 FX_FLOAT fHalfWidth = fWidth / 2.0f; 1051 1052 switch (nStyle) { 1053 default: 1054 case BorderStyle::SOLID: { 1055 CFX_PathData path; 1056 path.AppendRect(fLeft, fBottom, fRight, fTop); 1057 path.AppendRect(fLeft + fWidth, fBottom + fWidth, fRight - fWidth, 1058 fTop - fWidth); 1059 pDevice->DrawPath(&path, pUser2Device, nullptr, 1060 color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); 1061 break; 1062 } 1063 case BorderStyle::DASH: { 1064 CFX_PathData path; 1065 path.AppendPoint( 1066 CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), 1067 FXPT_TYPE::MoveTo, false); 1068 path.AppendPoint( 1069 CFX_PointF(fLeft + fWidth / 2.0f, fTop - fWidth / 2.0f), 1070 FXPT_TYPE::LineTo, false); 1071 path.AppendPoint( 1072 CFX_PointF(fRight - fWidth / 2.0f, fTop - fWidth / 2.0f), 1073 FXPT_TYPE::LineTo, false); 1074 path.AppendPoint( 1075 CFX_PointF(fRight - fWidth / 2.0f, fBottom + fWidth / 2.0f), 1076 FXPT_TYPE::LineTo, false); 1077 path.AppendPoint( 1078 CFX_PointF(fLeft + fWidth / 2.0f, fBottom + fWidth / 2.0f), 1079 FXPT_TYPE::LineTo, false); 1080 1081 CFX_GraphStateData gsd; 1082 gsd.SetDashCount(2); 1083 gsd.m_DashArray[0] = 3.0f; 1084 gsd.m_DashArray[1] = 3.0f; 1085 gsd.m_DashPhase = 0; 1086 1087 gsd.m_LineWidth = fWidth; 1088 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, 1089 color.ToFXColor(nTransparency), FXFILL_WINDING); 1090 break; 1091 } 1092 case BorderStyle::BEVELED: 1093 case BorderStyle::INSET: { 1094 CFX_GraphStateData gsd; 1095 gsd.m_LineWidth = fHalfWidth; 1096 1097 CFX_PathData pathLT; 1098 1099 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), 1100 FXPT_TYPE::MoveTo, false); 1101 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fTop - fHalfWidth), 1102 FXPT_TYPE::LineTo, false); 1103 pathLT.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), 1104 FXPT_TYPE::LineTo, false); 1105 pathLT.AppendPoint( 1106 CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), 1107 FXPT_TYPE::LineTo, false); 1108 pathLT.AppendPoint( 1109 CFX_PointF(fLeft + fHalfWidth * 2, fTop - fHalfWidth * 2), 1110 FXPT_TYPE::LineTo, false); 1111 pathLT.AppendPoint( 1112 CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), 1113 FXPT_TYPE::LineTo, false); 1114 pathLT.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), 1115 FXPT_TYPE::LineTo, false); 1116 1117 pDevice->DrawPath(&pathLT, pUser2Device, &gsd, 1118 crLeftTop.ToFXColor(nTransparency), 0, 1119 FXFILL_ALTERNATE); 1120 1121 CFX_PathData pathRB; 1122 pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), 1123 FXPT_TYPE::MoveTo, false); 1124 pathRB.AppendPoint( 1125 CFX_PointF(fRight - fHalfWidth, fBottom + fHalfWidth), 1126 FXPT_TYPE::LineTo, false); 1127 pathRB.AppendPoint(CFX_PointF(fLeft + fHalfWidth, fBottom + fHalfWidth), 1128 FXPT_TYPE::LineTo, false); 1129 pathRB.AppendPoint( 1130 CFX_PointF(fLeft + fHalfWidth * 2, fBottom + fHalfWidth * 2), 1131 FXPT_TYPE::LineTo, false); 1132 pathRB.AppendPoint( 1133 CFX_PointF(fRight - fHalfWidth * 2, fBottom + fHalfWidth * 2), 1134 FXPT_TYPE::LineTo, false); 1135 pathRB.AppendPoint( 1136 CFX_PointF(fRight - fHalfWidth * 2, fTop - fHalfWidth * 2), 1137 FXPT_TYPE::LineTo, false); 1138 pathRB.AppendPoint(CFX_PointF(fRight - fHalfWidth, fTop - fHalfWidth), 1139 FXPT_TYPE::LineTo, false); 1140 1141 pDevice->DrawPath(&pathRB, pUser2Device, &gsd, 1142 crRightBottom.ToFXColor(nTransparency), 0, 1143 FXFILL_ALTERNATE); 1144 1145 CFX_PathData path; 1146 1147 path.AppendRect(fLeft, fBottom, fRight, fTop); 1148 path.AppendRect(fLeft + fHalfWidth, fBottom + fHalfWidth, 1149 fRight - fHalfWidth, fTop - fHalfWidth); 1150 1151 pDevice->DrawPath(&path, pUser2Device, &gsd, 1152 color.ToFXColor(nTransparency), 0, FXFILL_ALTERNATE); 1153 break; 1154 } 1155 case BorderStyle::UNDERLINE: { 1156 CFX_PathData path; 1157 path.AppendPoint(CFX_PointF(fLeft, fBottom + fWidth / 2), 1158 FXPT_TYPE::MoveTo, false); 1159 path.AppendPoint(CFX_PointF(fRight, fBottom + fWidth / 2), 1160 FXPT_TYPE::LineTo, false); 1161 1162 CFX_GraphStateData gsd; 1163 gsd.m_LineWidth = fWidth; 1164 1165 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, 1166 color.ToFXColor(nTransparency), FXFILL_ALTERNATE); 1167 break; 1168 } 1169 } 1170 } 1171} 1172 1173