00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #include "camtypes.h"
00104 #include "cdrfiltr.h"
00105 #include "nodepath.h"
00106 #include "cdrbitm.h"
00107
00108 #include "nodebmp.h"
00109 #include "nodetxts.h"
00110
00111 DECLARE_SOURCE("$Revision: 751 $");
00112
00113 #define new CAM_DEBUG_NEW
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 BOOL CDRFilter::SetFillAttr(cdrfOffsetHeader *Object)
00129 {
00130 if(Version == CDRVERSION_3)
00131 {
00132 return SetFillAttr3(Object);
00133 }
00134
00135
00136 DWORD *pReference = (DWORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_FILL);
00137
00138
00139
00140 if(pReference == 0)
00141 {
00142
00143 WORD *pStyleReference = (WORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_STYLE);
00144
00145 if(pStyleReference != 0)
00146 {
00147
00148 cdrfStyle *pStyle;
00149 INT32 StyleSize;
00150
00151 if((pStyle = (cdrfStyle *)Styles.Find(*pStyleReference, &StyleSize)) != 0)
00152 {
00153
00154 pReference = (DWORD *)FindDataInObject(&pStyle->Header, cdrfSTYLEOFFSETTYPE_FILL);
00155 }
00156 }
00157 }
00158
00159
00160 if(pReference == 0 || ObjFilled == FALSE)
00161 {
00162
00163 return NoFill();
00164 }
00165
00166 cdrfFillHeader *Fill;
00167 INT32 FillSize;
00168
00169
00170 if(!SetPathFilled(TRUE))
00171 return FALSE;
00172
00173
00174 if((Fill = (cdrfFillHeader *)Fills.Find(*pReference, &FillSize)) == 0)
00175 return SetUKFill();
00176
00177
00178 if(FillSize < sizeof(cdrfFillHeader))
00179 {
00180
00181 return SetUKFill();
00182 }
00183
00184
00185 switch(CDRDATA_WORD(Fill->FillType))
00186 {
00187 case cdrfFILLTYPE_NONE:
00188
00189 return NoFill();
00190 break;
00191
00192 case cdrfFILLTYPE_FLAT:
00193 return SetFillAttrFlat(Fill, FillSize);
00194 break;
00195
00196 case cdrfFILLTYPE_GRADUATED:
00197 return SetFillAttrGrad(Fill, FillSize);
00198 break;
00199
00200 case cdrfFILLTYPE_PATTERN:
00201 {
00202 CDRTiledFillInfo i;
00203 cdrfFillPattern *PFill = (cdrfFillPattern *)Fill;
00204
00205
00206 if(FillSize < sizeof(cdrfFillPattern))
00207 return SetUKFill();
00208
00209
00210 i.SizeX = CDRDATA_SWORD(PFill->SizeX);
00211 i.SizeY = CDRDATA_SWORD(PFill->SizeY);
00212 i.OffsetX = CDRDATA_SWORD(PFill->OffsetX);
00213 i.OffsetY = CDRDATA_SWORD(PFill->OffsetY);
00214 i.Reference = CDRDATA_DWORD(PFill->Reference);
00215
00216
00217 DocColour Colour1;
00218 DocColour Colour2;
00219 ConvertColour(&PFill->Colour1, &Colour1);
00220 ConvertColour(&PFill->Colour2, &Colour2);
00221
00222 return SetFillAttrPattern(&i, &Colour1, &Colour2);
00223 }
00224 break;
00225
00226 case cdrfFILLTYPE_VECTOR:
00227 {
00228 CDRTiledFillInfo i;
00229 cdrfFillVector *VFill = (cdrfFillVector *)Fill;
00230
00231
00232 if(FillSize < sizeof(cdrfFillVector))
00233 return SetUKFill();
00234
00235
00236 i.SizeX = CDRDATA_SWORD(VFill->SizeX);
00237 i.SizeY = CDRDATA_SWORD(VFill->SizeY);
00238 i.OffsetX = CDRDATA_SWORD(VFill->OffsetX);
00239 i.OffsetY = CDRDATA_SWORD(VFill->OffsetY);
00240 i.Reference = CDRDATA_DWORD(VFill->VectorReference);
00241
00242 return SetFillAttrVector(&i);
00243 }
00244 break;
00245
00246 case cdrfFILLTYPE_TEXTURE:
00247 return SetFillAttrTexture(Fill, FillSize);
00248 break;
00249
00250 default:
00251 return SetUKFill();
00252 break;
00253 }
00254
00255 return TRUE;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 BOOL CDRFilter::NoFill(void)
00273 {
00274 if(pMadeNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
00275 {
00276 NodePath *pPath = (NodePath *)pMadeNode;
00277
00278 pPath->InkPath.IsFilled = FALSE;
00279 }
00280
00281 ObjFilled = FALSE;
00282 SetFillColour(DocColour(COLOUR_TRANS));
00283 return SetPathFilled(FALSE);
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 BOOL CDRFilter::SetFillAttr3(cdrfOffsetHeader *Object)
00300 {
00301 cdrfFillV3 *Fill = (cdrfFillV3 *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_FILL);
00302
00303 if(Fill == 0)
00304 {
00305
00306 return NoFill();
00307 }
00308
00309
00310 CDRFillInfo fi;
00311
00312
00313 DocRect BBox;
00314 if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
00315 return FALSE;
00316
00317
00318 DocColour Col1;
00319 DocColour Col2;
00320
00321 if(Fill->Type == cdrfFILLTYPEV3_FLAT)
00322 {
00323 if(!ConvertColour((cdrfColour *)&Fill->Data.Flat.Colour, &Col1))
00324 return FALSE;
00325 }
00326 else if(Fill->Type == cdrfFILLTYPEV3_LINEAR || Fill->Type == cdrfFILLTYPEV3_RADIAL)
00327 {
00328 fi.Angle = CDRDATA_SWORD(Fill->Data.Grad.Angle);
00329 fi.Pad = CDRDATA_SWORD(Fill->Data.Grad.Pad);
00330 fi.HorizontalCentreOffset = CDRDATA_SWORD(Fill->Data.Grad.HorizontalCentreOffset);
00331 fi.VerticalCentreOffset = CDRDATA_SWORD(Fill->Data.Grad.VerticalCentreOffset);
00332
00333 if(!ConvertColour((cdrfColour *)&Fill->Data.Grad.Colour1, &Col1))
00334 return FALSE;
00335 if(!ConvertColour((cdrfColour *)&Fill->Data.Grad.Colour2, &Col2))
00336 return FALSE;
00337 }
00338
00339
00340 if(!SetPathFilled(TRUE))
00341 return FALSE;
00342
00343
00344 switch(Fill->Type)
00345 {
00346 case cdrfFILLTYPEV3_NONE:
00347 return NoFill();
00348 break;
00349
00350 case cdrfFILLTYPEV3_FLAT:
00351 if(!SetFillColour(Col1))
00352 return FALSE;
00353 break;
00354
00355 case cdrfFILLTYPEV3_LINEAR:
00356 if(!SetLinearGrad(&fi, BBox, &Col1, &Col2))
00357 return SetUKFill();
00358 break;
00359
00360 case cdrfFILLTYPEV3_RADIAL:
00361 if(!SetRadialGrad(&fi, BBox, &Col1, &Col2))
00362 return SetUKFill();
00363 break;
00364
00365
00366 case cdrfFILLTYPEV3_PATTERN:
00367 {
00368 CDRTiledFillInfo i;
00369
00370
00371 i.SizeX = CDRDATA_SWORD(Fill->Data.Pattern.SizeX);
00372 i.SizeY = CDRDATA_SWORD(Fill->Data.Pattern.SizeY);
00373 i.OffsetX = CDRDATA_SWORD(Fill->Data.Pattern.OffsetX);
00374 i.OffsetY = CDRDATA_SWORD(Fill->Data.Pattern.OffsetY);
00375 i.Reference = CDRDATA_DWORD(Fill->Data.Pattern.Reference);
00376
00377
00378 ConvertColour((cdrfColour *)&Fill->Data.Pattern.Colour1, &Col1);
00379 ConvertColour((cdrfColour *)&Fill->Data.Pattern.Colour2, &Col2);
00380
00381 return SetFillAttrPattern(&i, &Col1, &Col2);
00382 }
00383 break;
00384
00385 case cdrfFILLTYPEV3_VECTOR:
00386 {
00387 CDRTiledFillInfo i;
00388
00389
00390 i.SizeX = CDRDATA_SWORD(Fill->Data.Vector.SizeX);
00391 i.SizeY = CDRDATA_SWORD(Fill->Data.Vector.SizeY);
00392 i.OffsetX = CDRDATA_SWORD(Fill->Data.Vector.OffsetX);
00393 i.OffsetY = CDRDATA_SWORD(Fill->Data.Vector.OffsetY);
00394 i.Reference = CDRDATA_DWORD(Fill->Data.Vector.Reference);
00395
00396 return SetFillAttrVector(&i);
00397 }
00398 break;
00399
00400 default:
00401 return SetUKFill();
00402 break;
00403 }
00404
00405 return TRUE;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 BOOL CDRFilter::SetFillAttrFlat(cdrfFillHeader *Fill, INT32 Size)
00423 {
00424 cdrfFillFlat *FFill = (cdrfFillFlat *)Fill;
00425
00426
00427 if(Size < sizeof(cdrfFillFlat))
00428 return SetUKFill();
00429
00430
00431 DocColour Col;
00432 ConvertColour(&FFill->Colour, &Col);
00433
00434 if(!SetFillColour(Col))
00435 return FALSE;
00436
00437 return TRUE;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 BOOL CDRFilter::SetFillAttrGrad(cdrfFillHeader *Fill, INT32 Size)
00455 {
00456
00457 if(Size < (sizeof(cdrfFillGraduated) + sizeof(cdrfFillGradColour)))
00458 {
00459 TRACEUSER( "Ben", _T("fill too small, size = %d\n"), Size);
00460 return SetUKFill();
00461 }
00462
00463
00464 cdrfFillGraduated *GFill = (cdrfFillGraduated *)Fill;
00465
00466
00467 if(CDRDATA_WORD(GFill->NColours) < 1)
00468 return SetUKFill();
00469
00470
00471 DocRect BBox;
00472 if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
00473 return FALSE;
00474
00475
00476
00477 cdrfFillGradColour *Cols = (cdrfFillGradColour *)(GFill + 1);
00478
00479 UINT32 min = CDRDATA_WORD(Cols[0].Percentage);
00480 UINT32 max = min;
00481 UINT32 minO = 0;
00482 UINT32 maxO = 0;
00483 UINT32 l;
00484
00485 for(l = 1; l < CDRDATA_WORD(GFill->NColours); l++)
00486 {
00487 UINT32 p = CDRDATA_WORD(Cols[l].Percentage);
00488
00489 if(p < min)
00490 {
00491 min = p;
00492 minO = l;
00493 }
00494 if(p > max)
00495 {
00496 max = p;
00497 maxO = l;
00498 }
00499 }
00500
00501
00502
00503 DocColour StartColour;
00504 DocColour EndColour;
00505
00506 ConvertColour(&Cols[minO].Colour, &StartColour);
00507 ConvertColour(&Cols[maxO].Colour, &EndColour);
00508
00509
00510 UINT32 FadeType = CDRDATA_WORD(GFill->ColourType);
00511
00512
00513
00514 BOOL NormalRainbow = TRUE;
00515 if(FadeType == cdrfGRADFILLCOLOURTYPE_RAINBOW_CLOCKWISE ||
00516 FadeType == cdrfGRADFILLCOLOURTYPE_RAINBOW_ANTICLOCKWISE)
00517 {
00518
00519 ColourContext *Conv = ColourContext::GetGlobalDefault(COLOURMODEL_HSVT);
00520
00521 ColourHSVT StartC;
00522 ColourHSVT EndC;
00523
00524 Conv->ConvertColour(&StartColour, (ColourGeneric *)&StartC);
00525 Conv->ConvertColour(&EndColour, (ColourGeneric *)&EndC);
00526
00527
00528 ColourValue Difference;
00529
00530 if(EndC.Hue > StartC.Hue)
00531 {
00532 Difference = EndC.Hue - StartC.Hue;
00533 } else {
00534 Difference = 1.0 - (StartC.Hue - EndC.Hue);
00535 }
00536
00537
00538 if(Difference > fixed24(0.5))
00539 NormalRainbow = FALSE;
00540 }
00541
00542
00543 switch(FadeType)
00544 {
00545 case cdrfGRADFILLCOLOURTYPE_DIRECT:
00546 case cdrfGRADFILLCOLOURTYPE_CUSTOM:
00547 default:
00548 SetFadeFillEffect();
00549 break;
00550
00551 case cdrfGRADFILLCOLOURTYPE_RAINBOW_ANTICLOCKWISE:
00552 if(NormalRainbow)
00553 SetRainbowFillEffect();
00554 else
00555 SetAltRainbowFillEffect();
00556 break;
00557
00558 case cdrfGRADFILLCOLOURTYPE_RAINBOW_CLOCKWISE:
00559 if(NormalRainbow)
00560 SetAltRainbowFillEffect();
00561 else
00562 SetRainbowFillEffect();
00563 break;
00564 }
00565
00566
00567 CDRFillInfo fi;
00568
00569 fi.Angle = CDRDATA_SWORD(GFill->Angle);
00570 fi.Pad = CDRDATA_SWORD(GFill->Pad);
00571 fi.HorizontalCentreOffset = CDRDATA_SWORD(GFill->HorizontalCentreOffset);
00572 fi.VerticalCentreOffset = CDRDATA_SWORD(GFill->VerticalCentreOffset);
00573
00574
00575 DocCoord StartPoint;
00576 DocCoord EndPoint;
00577 switch(CDRDATA_WORD(GFill->GradFillType))
00578 {
00579 case cdrfGRADFILLTYPE_LINEAR:
00580 if(!SetLinearGrad(&fi, BBox, &StartColour, &EndColour))
00581 return SetUKFill();
00582 break;
00583
00584 case cdrfGRADFILLTYPE_RADIAL:
00585 case cdrfGRADFILLTYPE_SQUARE:
00586 if(!SetRadialGrad(&fi, BBox, &StartColour, &EndColour))
00587 return SetUKFill();
00588 break;
00589
00590 case cdrfGRADFILLTYPE_CONICAL:
00591 if(!SetConicalGrad(&fi, BBox, &StartColour, &EndColour))
00592 return SetUKFill();
00593 break;
00594
00595 default:
00596 return SetUKFill();
00597 break;
00598 }
00599
00600 return TRUE;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 BOOL CDRFilter::SetUKFill(void)
00618 {
00619 PColourCMYK cmyk;
00620 cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0;
00621 cmyk.Key = 255;
00622
00623 DocColour Col;
00624 Col.SetCMYKValue(&cmyk);
00625
00626 return SetFillColour(Col);
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 BOOL CDRFilter::GetObjCorelBBox(NodeRenderableBounded *pNode, DocRect *BBox)
00644 {
00645 if(IS_A(pNode, TextStory) && TextBBoxes.Find(pNode, BBox) == TRUE)
00646 return TRUE;
00647
00648 return GetCorelBBox(pNode, BBox);
00649 }
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 BOOL CDRFilter::GetCorelBBox(NodeRenderableBounded *pNode, DocRect *BBox)
00665 {
00666 if(pNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
00667 {
00668
00669
00670
00671
00672 NodePath *pNodePath = (NodePath *)pNode;
00673
00674
00675 INT32 NCoords = pNodePath->InkPath.GetNumCoords();
00676 DocCoord *Coords = pNodePath->InkPath.GetCoordArray();
00677
00678 ERROR3IF(NCoords < 1, "Awooga! Trying to find a corel bbox of a path with less than one coord.");
00679
00680 INT32 c;
00681
00682 INT32 x0, y0, x1, y1;
00683
00684
00685 x0 = x1 = Coords[0].x;
00686 y0 = y1 = Coords[0].y;
00687
00688 for(c = 1; c < NCoords; c++)
00689 {
00690
00691 if(Coords[c].x < x0) x0 = Coords[c].x;
00692 if(Coords[c].y < y0) y0 = Coords[c].y;
00693 if(Coords[c].x > x1) x1 = Coords[c].x;
00694 if(Coords[c].y > y1) y1 = Coords[c].y;
00695 }
00696
00697
00698 BBox->lo.x = x0;
00699 BBox->lo.y = y0;
00700 BBox->hi.x = x1;
00701 BBox->hi.y = y1;
00702 } else {
00703
00704
00705 *BBox = pNode->GetBoundingRect();
00706 }
00707
00708 return TRUE;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 BOOL CDRFilter::SetLinearGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00727 {
00728
00729
00730
00731
00732
00733 DocCoord Start, End;
00734
00735
00736 MILLIPOINT Width = BBox.Width();
00737 MILLIPOINT Height = BBox.Height();
00738
00739
00740 if(Width < 16)
00741 Width = 16;
00742
00743 if(Height < 16)
00744 Height = 16;
00745
00746
00747 DocCoord Centre;
00748 Centre.x = BBox.lo.x + (Width / 2);
00749 Centre.y = BBox.lo.y + (Height / 2);
00750
00751
00752 double TotalArea = (double) Width * (double) Height;
00753
00754
00755 BOOL Mirror = FALSE;
00756 INT32 Angle = GFill->Angle;
00757
00758 if (Angle >= 1800)
00759 {
00760 Angle -= 1800;
00761 Mirror = TRUE;
00762 }
00763 else if (Angle < 00)
00764 {
00765 Angle += 1800;
00766 Mirror = TRUE;
00767 }
00768
00769 Angle += 900;
00770
00771 if (Angle >= 1800)
00772 {
00773 Angle -= 1800;
00774 }
00775
00776
00777 INT32 EdgePad = GFill->Pad;
00778
00779
00780 double Radians = (((double) Angle) / 1800.0) * PI;
00781 double TanTheta;
00782 if (Angle == 900)
00783 {
00784
00785
00786
00787 Start.x = BBox.lo.x;
00788 Start.y = Centre.y;
00789 End.x = BBox.hi.x;
00790 End.y = Centre.y;
00791
00792
00793 INT32 Padding = (Width * EdgePad) / 100;
00794 Start.x += Padding;
00795 End.x -= Padding;
00796 }
00797 else if (Angle == 0)
00798 {
00799
00800
00801
00802 Start.x = Centre.x;
00803 Start.y = BBox.lo.y;
00804 End.x = Centre.x;
00805 End.y = BBox.hi.y;
00806
00807
00808 INT32 Padding = (Height * EdgePad) / 100;
00809 Start.y += Padding;
00810 End.y -= Padding;
00811 }
00812 else
00813 {
00814 TanTheta = tan(Radians);
00815
00816
00817
00818
00819 MILLIPOINT TriWidth = (MILLIPOINT) ((double) Height / TanTheta);
00820
00821
00822 if (TriWidth < 0)
00823 TriWidth = -TriWidth;
00824 if (TriWidth > Width)
00825 TriWidth = Width;
00826
00827
00828 MILLIPOINT TriHeight = (MILLIPOINT) ((double) Width * TanTheta);
00829
00830
00831 if (TriHeight < 0)
00832 TriHeight = -TriHeight;
00833 if (TriHeight > Height)
00834 TriHeight = Height;
00835
00836
00837 MILLIPOINT StartC, EndC;
00838
00839
00840
00841 double Percentage = (50.0 * (double) TriWidth * (double) TriHeight) / TotalArea;
00842
00843 INT32 Diff = 0;
00844
00845
00846 if (((INT32) Percentage) >= EdgePad)
00847 {
00848
00849 TriHeight = (MILLIPOINT) sqrt(ABS(((double) EdgePad * TotalArea * TanTheta) / 100.0));
00850
00851 TriWidth = (MILLIPOINT) ((double) TriHeight / TanTheta);
00852 if (TriWidth < 0)
00853 TriWidth = -TriWidth;
00854
00855 ENSURE(TriWidth < Width, "Error in Corel Grad fill decoding logic");
00856 }
00857 else
00858 {
00859
00860 Percentage = (EdgePad - Percentage) / 2;
00861
00862
00863 if (TriWidth == Width)
00864 {
00865
00866 Diff = (MILLIPOINT) ((Percentage * Height) / 100.0);
00867 }
00868 else
00869 {
00870
00871 Diff = (MILLIPOINT) ((Percentage * Width) / 100.0);
00872 Diff = (MILLIPOINT) (Diff / tan(PI - Radians));
00873 Diff = ABS(Diff);
00874 }
00875 }
00876
00877
00878
00879 if (Angle == 900)
00880 {
00881
00882 }
00883 else if (Angle < 900)
00884 {
00885 StartC = (MILLIPOINT) (BBox.lo.y - ((BBox.hi.x - TriWidth) * TanTheta));
00886 EndC = (MILLIPOINT) (BBox.hi.y - ((BBox.lo.x + TriWidth) * TanTheta));
00887 }
00888 else
00889 {
00890 StartC = (MILLIPOINT) (BBox.lo.y - ((BBox.lo.x + TriWidth) * TanTheta));
00891 EndC = (MILLIPOINT) (BBox.hi.y - ((BBox.hi.x - TriWidth) * TanTheta));
00892 }
00893
00894
00895 StartC += Diff;
00896 EndC -= Diff;
00897
00898
00899
00900
00901
00902 double FillM = -1.00 / TanTheta;
00903 MILLIPOINT FillC = (MILLIPOINT) (Centre.y - (Centre.x * FillM));
00904
00905
00906
00907 Start.x = (MILLIPOINT) ( (FillC - StartC) / (TanTheta + (1.00 / TanTheta)) );
00908 Start.y = (MILLIPOINT) ((FillM * Start.x) + FillC);
00909
00910 End.x = (MILLIPOINT) ( (FillC - EndC) / (TanTheta + (1.00 / TanTheta)) );
00911 End.y = (MILLIPOINT) ((FillM * End.x) + FillC);
00912 }
00913
00914 if (Mirror)
00915 {
00916
00917 DocCoord Tmp = Start;
00918 Start = End;
00919 End = Tmp;
00920 }
00921
00922
00923 return SetLinearFill(*StartColour, *EndColour, Start, End);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 BOOL CDRFilter::SetConicalGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00942 {
00943
00944 DocCoord Start, End;
00945
00946
00947 MILLIPOINT Width = BBox.Width();
00948 MILLIPOINT Height = BBox.Height();
00949
00950
00951
00952
00953 Start.x = BBox.lo.x + (Width / 2);
00954 Start.y = BBox.lo.y + (Height / 2);
00955 Start.x += ((GFill->HorizontalCentreOffset * Width) / 100);
00956 Start.y += ((GFill->VerticalCentreOffset * Height) / 100);
00957
00958
00959 double Radius = Width / 2;
00960
00961 double Theta = ((((double)(GFill->Angle)) / 10.0) / 360.0) * (2 * PI);
00962
00963
00964 Theta = 0 - Theta;
00965
00966
00967 Theta -= PI / 2;
00968
00969
00970 while(Theta < 0)
00971 Theta += (2 * PI);
00972
00973
00974 double dx, dy;
00975
00976 dx = Radius * sin(Theta);
00977 dy = Radius * cos(Theta);
00978
00979 End.x = Start.x + (INT32)dx;
00980 End.y = Start.y + (INT32)dy;
00981
00982
00983
00984
00985 return SetConicalFill(*EndColour, *StartColour, Start, End);
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 BOOL CDRFilter::SetRadialGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
01003 {
01004
01005 DocCoord Start, End;
01006
01007
01008 MILLIPOINT Width = BBox.Width();
01009 MILLIPOINT Height = BBox.Height();
01010
01011
01012
01013 double dWidth = Width;
01014 double dHeight = Height;
01015 INT32 Diagonal = (INT32)sqrt(dWidth*dWidth + dHeight*dHeight);
01016
01017
01018
01019 INT32 Edge = (Diagonal * (100 - (GFill->Pad * 2))) / 100;
01020
01021
01022
01023
01024 DocCoord Centre = DocCoord(BBox.lo.x + (Width / 2), BBox.lo.y + (Height / 2));
01025 INT32 OffX = (GFill->HorizontalCentreOffset * Width) / 100;
01026 INT32 OffY = (GFill->VerticalCentreOffset * Height) / 100;
01027 Start.x = Centre.x + OffX;
01028 Start.y = Centre.y + OffY;
01029
01030
01031 double Radius = Edge / 2;
01032
01033
01034 double dOffX = OffX;
01035 double dOffY = OffY;
01036 double Dist = (INT32)sqrt(dOffX*dOffX + dOffY*dOffY);
01037
01038
01039 double BodgeFactor = 1 + (Dist / (double)(Diagonal / 2));
01040 Radius *= BodgeFactor;
01041
01042
01043 End.x = Start.x + ((MILLIPOINT) Radius);
01044 End.y = Start.y;
01045
01046
01047
01048
01049 return SetRadialFill(*EndColour, *StartColour, Start, End);
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 BOOL CDRBitmapStore::AddChunkToStore(RIFFFile *RIFF, BOOL Pattern, CDRFilter *C)
01070 {
01071 CDRBitmapStoredItem *Item = new CDRBitmapStoredItem;
01072
01073 if(Item == 0)
01074 return FALSE;
01075
01076
01077 FOURCC Reference = 0;
01078
01079
01080 if(Pattern)
01081 {
01082 Item->pBitmap = CDRBitmap::ConvertPattern(RIFF, &Reference, C);
01083 }
01084 else
01085 {
01086 switch(C->Version)
01087 {
01088 case CDRVERSION_5:
01089 Item->pBitmap = CDRBitmap::ConvertBitmap5(RIFF, &Reference, C);
01090 break;
01091
01092 default:
01093 Item->pBitmap = CDRBitmap::ConvertBitmap4(RIFF, &Reference, C);
01094 break;
01095 }
01096 }
01097
01098
01099 if(Item->pBitmap == 0)
01100 return FALSE;
01101
01102
01103 String_256 Name;
01104 if(Pattern)
01105 Name.MakeMsg(_R(IDT_CDRPATTERNNAME), CDRFilter::PatternNumber++);
01106 else
01107 Name.MakeMsg(_R(IDT_CDRBITMAPNAME), CDRFilter::BitmapNumber++);
01108
01109
01110 Item->pBitmap->ActualBitmap->SetName(Name);
01111
01112
01113 Item->Reference = Reference;
01114
01115
01116 AddTail(Item);
01117
01118 return TRUE;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 KernelBitmap *CDRBitmapStore::FindBitmap(DWORD Reference)
01138 {
01139 CDRBitmapStoredItem *Item = (CDRBitmapStoredItem *)GetHead();
01140
01141
01142 while(Item != 0)
01143 {
01144 if(Item->Reference == Reference)
01145 {
01146
01147 Item->Used = TRUE;
01148
01149 return Item->pBitmap;
01150 }
01151
01152 Item = (CDRBitmapStoredItem *)GetNext(Item);
01153 }
01154
01155 return 0;
01156 }
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 CDRBitmapStoredItem::CDRBitmapStoredItem()
01173 {
01174 pBitmap = 0;
01175 Used = FALSE;
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 CDRBitmapStoredItem::~CDRBitmapStoredItem()
01193 {
01194 if(pBitmap != 0 && Used == FALSE)
01195 delete pBitmap;
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 BOOL CDRFilter::SetFillAttrPattern(CDRTiledFillInfo *Info, DocColour *Colour1, DocColour *Colour2)
01213 {
01214
01215 KernelBitmap *pBitmap = Patterns.FindBitmap(Info->Reference);
01216
01217 if(pBitmap == 0)
01218 return SetUKFill();
01219
01220
01221
01222
01223 INT32 SizeX = Info->SizeX * CDRCOORDS_TO_MILLIPOINTS;
01224 INT32 SizeY = Info->SizeY * CDRCOORDS_TO_MILLIPOINTS;
01225
01226
01227 DocRect BBox;
01228 if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01229 return FALSE;
01230
01231
01232 INT32 XPos = BBox.lo.x + ((SizeX * Info->OffsetX) / 100);
01233 INT32 YPos = BBox.hi.y - SizeY - ((SizeY * Info->OffsetY) / 100);
01234
01235
01236
01237
01238 DocCoord Start = DocCoord(XPos, YPos);
01239 DocCoord End1 = DocCoord(XPos + SizeX, YPos);
01240 DocCoord End2 = DocCoord(XPos, YPos + SizeY);
01241 if(!SetBitmapFill(pBitmap, Start, End1, End2, Colour1, Colour2))
01242 return FALSE;
01243
01244 return TRUE;
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 BOOL CDRFilter::SetFillAttrVector(CDRTiledFillInfo *Info)
01262 {
01263
01264
01265
01266
01267 CDRVectorStoredItem *Item = Vectors.Find(Info->Reference);
01268
01269 if(Item->Objects == 0)
01270 return SetUKFill();
01271
01272
01273 KernelBitmap *pBitmap = BitmapFromNodeList(Item->Objects);
01274
01275 if(pBitmap == 0)
01276 return SetUKFill();
01277
01278
01279
01280
01281 INT32 SizeX = Info->SizeX * CDRCOORDS_TO_MILLIPOINTS;
01282 INT32 SizeY = Info->SizeY * CDRCOORDS_TO_MILLIPOINTS;
01283
01284
01285 DocRect BBox;
01286 if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01287 return FALSE;
01288
01289
01290 INT32 XPos = BBox.lo.x + ((SizeX * Info->OffsetX) / 100);
01291 INT32 YPos = BBox.hi.y - SizeY - ((SizeY * Info->OffsetY) / 100);
01292
01293
01294
01295
01296 DocCoord Start = DocCoord(XPos, YPos);
01297 DocCoord End1 = DocCoord(XPos + SizeX, YPos);
01298 DocCoord End2 = DocCoord(XPos, YPos + SizeY);
01299 if(!SetBitmapFill(pBitmap, Start, End1, End2))
01300 return FALSE;
01301
01302 return TRUE;
01303 }
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319 BOOL CDRFilter::SetFillAttrTexture(cdrfFillHeader *Fill, INT32 Size)
01320 {
01321 cdrfFillTexture *TFill = (cdrfFillTexture *)Fill;
01322
01323
01324 if(Size < sizeof(cdrfFillTexture))
01325 return SetUKFill();
01326
01327
01328 DocRect fBBox;
01329 Node *FillNodes;
01330
01331 FillNodes = Vectors.Find(CDRDATA_WORD(TFill->VectorReference), &fBBox);
01332
01333
01334 if(FillNodes == 0)
01335 return SetUKFill();
01336
01337
01338 KernelBitmap *pBitmap;
01339
01340 pBitmap = BitmapFromNodeList(FillNodes);
01341
01342
01343 if(pBitmap == 0)
01344 return SetUKFill();
01345
01346
01347
01348 DocRect BBox;
01349 if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01350 return FALSE;
01351
01352
01353 DocCoord Start = DocCoord(BBox.lo.x, BBox.lo.y);
01354 DocCoord End1 = DocCoord(BBox.hi.x, BBox.lo.y);
01355 DocCoord End2 = DocCoord(BBox.lo.x, BBox.hi.y);
01356 if(!SetBitmapFill(pBitmap, Start, End1, End2))
01357 return FALSE;
01358
01359 return TRUE;
01360 }
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 CDRVectorStoredItem::CDRVectorStoredItem(void)
01377 : BBox(0, 0, 0, 0)
01378 {
01379 Objects = 0;
01380 Reference = 0;
01381 pBitmap = 0;
01382 }
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 KernelBitmap *CDRVectorStoredItem::GetBitmap(Document *pDocument)
01399 {
01400 ERROR2IF(Objects == 0, FALSE, "not objects in VectorStoredItem!");
01401
01402
01403 if(pBitmap != 0)
01404 return pBitmap;
01405
01406
01407
01408 return 0;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 CDRVectorStoredItem::~CDRVectorStoredItem(void)
01426 {
01427
01428 if(Objects != 0)
01429 CDRFilter::DeleteNodeList(Objects);
01430 }
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 BOOL CDRFilter::ProcessVectorList(ADDR Block, INT32 Size)
01456 {
01457 ERROR3IF(pLevelNodeList != 0, "ProcessVectorList called when LevelNodeList was in use");
01458
01459
01460 CCMemFile MFile;
01461
01462 MFile.open(Block, Size);
01463
01464
01465 RIFFFile RFile;
01466
01467 RFile.Init(&MFile, TRUE);
01468
01469
01470 INT32 oTranslateByX = TranslateByX;
01471 INT32 oTranslateByY = TranslateByY;
01472 RIFFFile *oRIFF = RIFF;
01473
01474 TranslateByX = 0;
01475 TranslateByY = 0;
01476 RIFF = &RFile;
01477
01478
01479
01480
01481
01482 do
01483 {
01484
01485 if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() == cdrT_grp)
01486 {
01487 if(!ProcessVectorListEntry())
01488 return FALSE;
01489 }
01490
01491 if(!RIFF->NextObject())
01492 goto Failure;
01493
01494 } while(RIFF->GetObjType() != RIFFOBJECTTYPE_FILEEND);
01495
01496
01497 MFile.close();
01498
01499 TranslateByX = oTranslateByX;
01500 TranslateByY = oTranslateByY;
01501 RIFF = oRIFF;
01502
01503 return TRUE;
01504
01505 Failure:
01506
01507 MFile.close();
01508
01509 TranslateByX = oTranslateByX;
01510 TranslateByY = oTranslateByY;
01511 RIFF = oRIFF;
01512
01513 return FALSE;
01514 }
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 BOOL CDRFilter::ProcessVectorListEntry()
01531 {
01532 UINT32 StartLevel = RIFF->GetObjLevel();
01533
01534 ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() != cdrT_grp,
01535 "ProcessVectorListEntry called without RIFF set up correctly");
01536
01537
01538 WORD Reference;
01539 DocRect BBox;
01540 BOOL GotReference = FALSE;
01541 BOOL GotBBox = FALSE;
01542
01543 do
01544 {
01545 if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK)
01546 {
01547 switch(RIFF->GetObjChunkType())
01548 {
01549 case cdrT_spnd:
01550 {
01551
01552 if(!RIFF->AquireChunkData())
01553 return FALSE;
01554
01555 WORD *Data = (WORD *)RIFF->GetAquiredData();
01556
01557 if(Data == 0)
01558 return FALSE;
01559
01560
01561 Reference = CDRDATA_WORD(*Data);
01562
01563 GotReference = TRUE;
01564 }
01565 break;
01566
01567 case cdrT_bbox:
01568 {
01569
01570 if(RIFF->GetObjSize() < sizeof(cdrfBBox))
01571 {
01572
01573 RIFF->SkipToListEnd(StartLevel);
01574 return TRUE;
01575 }
01576
01577
01578 if(!RIFF->AquireChunkData())
01579 return FALSE;
01580
01581 cdrfBBox *Data = (cdrfBBox *)RIFF->GetAquiredData();
01582
01583 if(Data == 0)
01584 return FALSE;
01585
01586
01587 BBox.lo.x = CDRDATA_SWORD(Data->x0) * CDRCOORDS_TO_MILLIPOINTS;
01588 BBox.lo.y = CDRDATA_SWORD(Data->y0) * CDRCOORDS_TO_MILLIPOINTS;
01589 BBox.hi.x = CDRDATA_SWORD(Data->x1) * CDRCOORDS_TO_MILLIPOINTS;
01590 BBox.hi.y = CDRDATA_SWORD(Data->y1) * CDRCOORDS_TO_MILLIPOINTS;
01591
01592 GotBBox = TRUE;
01593 }
01594 break;
01595
01596 default:
01597 break;
01598 }
01599 }
01600
01601 if(!RIFF->NextObject())
01602 return FALSE;
01603
01604 } while((GotReference == FALSE || GotBBox == FALSE) &&
01605 (RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel));
01606
01607
01608 if(!ProcessObjectTree(StartLevel))
01609 return FALSE;
01610
01611
01612
01613
01614 CDRVectorStoredItem *Item = new CDRVectorStoredItem;
01615
01616 if(Item == 0)
01617 return FALSE;
01618
01619
01620 Item->Objects = pLevelNodeList;
01621 Item->Reference = Reference;
01622 Item->BBox = BBox;
01623
01624
01625 pLevelNodeList = 0;
01626
01627
01628 Vectors.AddTail(Item);
01629
01630 return TRUE;
01631 }
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646 Node *CDRVectorStore::Find(DWORD Reference, DocRect *BBox)
01647 {
01648 CDRVectorStoredItem *Item = (CDRVectorStoredItem *)GetHead();
01649
01650
01651 while(Item != 0)
01652 {
01653 if(Item->Reference == Reference)
01654 {
01655
01656 if(BBox != 0)
01657 *BBox = Item->BBox;
01658
01659 return Item->Objects;
01660 }
01661
01662 Item = (CDRVectorStoredItem *)GetNext(Item);
01663 }
01664
01665 return 0;
01666 }
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 CDRVectorStoredItem *CDRVectorStore::Find(DWORD Reference)
01683 {
01684 CDRVectorStoredItem *Item = (CDRVectorStoredItem *)GetHead();
01685
01686
01687 while(Item != 0)
01688 {
01689 if(Item->Reference == Reference)
01690 {
01691
01692 return Item;
01693 }
01694
01695 Item = (CDRVectorStoredItem *)GetNext(Item);
01696 }
01697
01698 return 0;
01699 }
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716 KernelBitmap *CDRFilter::BitmapFromNodeList(Node *List)
01717 {
01718
01719 if(List == 0)
01720 return 0;
01721
01722
01723 if(List->FindNext() != 0)
01724 return 0;
01725
01726
01727 if(IS_A(List, NodeBitmap))
01728 {
01729
01730 NodeBitmap *NB = (NodeBitmap *)List;
01731
01732
01733 return NB->GetBitmap();
01734 }
01735
01736 return 0;
01737 }
01738
01739