Changeset 317 for GraphicTest/BGRABitmap/bgrabitmaptypes.pas
- Timestamp:
- Feb 1, 2012, 3:02:33 PM (13 years ago)
- Location:
- GraphicTest/BGRABitmap
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/BGRABitmap
-
Property svn:ignore
set to
lib
-
Property svn:ignore
set to
-
GraphicTest/BGRABitmap/bgrabitmaptypes.pas
r210 r317 30 30 31 31 uses 32 Classes, Graphics;32 Classes, Types, Graphics, FPImage, FPImgCanv, GraphType; 33 33 34 34 type 35 //pointer for direct pixel access 35 36 PBGRAPixel = ^TBGRAPixel; 36 37 38 //pixel structure 37 39 TBGRAPixel = packed record 38 40 blue, green, red, alpha: byte; 39 41 end; 40 42 43 //gamma expanded values 41 44 TExpandedPixel = packed record 42 45 red, green, blue, alpha: word; 43 46 end; 44 47 48 //pixel color defined in HSL colorspace 45 49 THSLAPixel = packed record 46 50 hue, saturation, lightness, alpha: word; 47 51 end; 48 52 49 TDrawMode = (dmSet, dmSetExceptTransparent, dmLinearBlend, dmDrawWithTransparency); 50 TFloodfillMode = (fmSet, fmDrawWithTransparency, fmProgressive); 51 TResampleMode = (rmSimpleStretch, rmFineResample); 53 //general purpose color variable with floating point values 54 TColorF = array[1..4] of single; 55 56 { These types are used as parameters } 57 58 TDrawMode = (dmSet, //replace pixels 59 dmSetExceptTransparent, //draw pixels with alpha=255 60 dmLinearBlend, //blend without gamma correction 61 dmDrawWithTransparency, //normal blending with gamma correction 62 dmXor); //bitwise xor for all channels 63 TChannel = (cRed, cGreen, cBlue, cAlpha); 64 TChannels = set of TChannel; 65 66 //floodfill option 67 TFloodfillMode = (fmSet, //set pixels 68 fmDrawWithTransparency, //draw fill color with transparency 69 fmProgressive); //draw fill color with transparency according to similarity with start color 70 71 TResampleMode = (rmSimpleStretch, //low quality resample 72 rmFineResample); //use resample filters 73 TResampleFilter = (rfLinear, //linear interpolation 74 rfHalfCosine, //mix of rfLinear and rfCosine 75 rfCosine, //cosine-like interpolation 76 rfBicubic, //simple bi-cubic filter (blur) 77 rfMitchell, //downsizing interpolation 78 rfSpline, //upsizing interpolation 79 rfBestQuality); //mix of rfMitchell and rfSpline 80 81 TBGRAFontQuality = (fqSystem, fqSystemClearType, fqFineAntialiasing, fqFineClearTypeRGB, fqFineClearTypeBGR); 82 52 83 TMedianOption = (moNone, moLowSmooth, moMediumSmooth, moHighSmooth); 84 TRadialBlurType = (rbNormal, rbDisk, rbCorona, rbPrecise, rbFast); 85 TSplineStyle = (ssInside, ssInsideWithEnds, ssCrossing, ssCrossingWithEnds, ssOutside, ssRoundOutside, ssVertexToSide); 86 87 //Advanced blending modes 88 //see : http://www.brighthub.com/multimedia/photography/articles/18301.aspx 89 //and : http://www.pegtop.net/delphi/articles/blendmodes/ 90 TBlendOperation = (boLinearBlend, boTransparent, //blending 91 boLighten, boScreen, boAdditive, boLinearAdd, boColorDodge, boNiceGlow, //lighting 92 boGlow, boReflect, boOverlay, boDarkOverlay, boDarken, boMultiply, boColorBurn, //masking 93 boDifference, boLinearDifference, boNegation, boLinearNegation, boXor); //negative 94 95 const 96 boGlowMask = boGlow; 97 boLinearMultiply = boMultiply; 98 99 const 100 BlendOperationStr : array[TBlendOperation] of string = 101 ('LinearBlend', 'Transparent', 102 'Lighten', 'Screen', 'Additive', 'LinearAdd', 'ColorDodge', 'NiceGlow', 103 'Glow', 'Reflect', 'Overlay', 'DarkOverlay', 'Darken', 'Multiply', 'ColorBurn', 104 'Difference', 'LinearDifference', 'Negation', 'LinearNegation', 'Xor'); 105 106 function StrToBlendOperation(str: string): TBlendOperation; 107 108 type 53 109 TGradientType = (gtLinear, gtReflected, gtDiamond, gtRadial); 54 55 110 const 56 111 GradientTypeStr : array[TGradientType] of string = 57 112 ('Linear','Reflected','Diamond','Radial'); 58 113 function StrToGradientType(str: string): TGradientType; 114 59 115 type 60 TRadialBlurType = (rbNormal, rbDisk, rbCorona, rbPrecise); 61 TChannel = (cRed, cGreen, cBlue, cAlpha); 62 TBlendOperation = (boLinearBlend, boTransparent, boMultiply, 63 boLinearMultiply, boAdditive, boLinearAdd, boColorBurn, boColorDodge, boReflect, 64 boGlow, boOverlay, boDifference, boLinearDifference, boNegation, 65 boLinearNegation, boLighten, boDarken, boScreen, boXor); 66 116 { A pen style is defined as a list of floating number. The first number is the length of the first dash, 117 the second number is the length of the first gap, the third number is the length of the second dash... 118 It must have an even number of values. } 119 TBGRAPenStyle = Array Of Single; 120 TRoundRectangleOption = (rrTopLeftSquare,rrTopRightSquare,rrBottomRightSquare,rrBottomLeftSquare, 121 rrTopLeftBevel,rrTopRightBevel,rrBottomRightBevel,rrBottomLeftBevel,rrDefault); 122 TRoundRectangleOptions = set of TRoundRectangleOption; 123 TPolygonOrder = (poNone, poFirstOnTop, poLastOnTop); //see TBGRAMultiShapeFiller in BGRAPolygon 124 125 function BGRAPenStyle(dash1, space1: single; dash2: single=0; space2: single = 0; dash3: single=0; space3: single = 0; dash4 : single = 0; space4 : single = 0): TBGRAPenStyle; 126 127 { Point, polygon and curve structures } 128 type 129 PPointF = ^TPointF; 67 130 TPointF = record 68 131 x, y: single; 69 132 end; 70 133 ArrayOfTPointF = array of TPointF; 71 134 TArcOption = (aoClosePath, aoPie, aoFillPath); 135 TArcOptions = set of TArcOption; 136 137 TCubicBezierCurve = record 138 p1,c1,c2,p2: TPointF; 139 end; 140 TQuadraticBezierCurve = record 141 p1,c,p2: TPointF; 142 end; 143 144 TPoint3D = record 145 x,y,z: single; 146 end; 147 148 function ConcatPointsF(const APolylines: array of ArrayOfTPointF): ArrayOfTPointF; 149 150 function Point3D(x,y,z: single): TPoint3D; 151 operator = (const v1,v2: TPoint3D): boolean; inline; 152 operator * (const v1,v2: TPoint3D): single; inline; 153 operator * (const v1: TPoint3D; const factor: single): TPoint3D; inline; 154 operator - (const v1,v2: TPoint3D): TPoint3D; inline; 155 operator - (const v: TPoint3D): TPoint3D; inline; 156 operator + (const v1,v2: TPoint3D): TPoint3D; inline; 157 procedure VectProduct3D(u,v: TPoint3D; out w: TPoint3D); 158 procedure Normalize3D(var v: TPoint3D); inline; 159 160 function BezierCurve(origin, control1, control2, destination: TPointF) : TCubicBezierCurve; overload; 161 function BezierCurve(origin, control, destination: TPointF) : TQuadraticBezierCurve; overload; 162 163 { Useful constants } 72 164 const 73 165 dmFastBlend = dmLinearBlend; 74 75 const 76 EmptySingle: single = -3.402823e38; 77 78 const 79 EmptyPointF: TPointF = (x: -3.402823e38; y: -3.402823e38); 80 81 const 166 EmptySingle: single = -3.402823e38; //used as a separator in floating point lists 167 EmptyPointF: TPointF = (x: -3.402823e38; y: -3.402823e38); //used as a separator in TPointF lists 82 168 BGRAPixelTransparent: TBGRAPixel = (blue: 0; green: 0; red: 0; alpha: 0); 83 84 const85 169 BGRAWhite: TBGRAPixel = (blue: 255; green: 255; red: 255; alpha: 255); 86 87 const88 170 BGRABlack: TBGRAPixel = (blue: 0; green: 0; red: 0; alpha: 255); 89 171 90 const 172 //Red colors 173 CSSIndianRed: TBGRAPixel = (blue: 92; green: 92; red: 205; alpha: 255); 174 CSSLightCoral: TBGRAPixel = (blue: 128; green: 128; red: 240; alpha: 255); 175 CSSSalmon: TBGRAPixel = (blue: 114; green: 128; red: 250; alpha: 255); 176 CSSDarkSalmon: TBGRAPixel = (blue: 122; green: 150; red: 233; alpha: 255); 177 CSSRed: TBGRAPixel = (blue: 0; green: 0; red: 255; alpha: 255); 178 CSSCrimson: TBGRAPixel = (blue: 60; green: 20; red: 220; alpha: 255); 179 CSSFireBrick: TBGRAPixel = (blue: 34; green: 34; red: 178; alpha: 255); 180 CSSDarkRed: TBGRAPixel = (blue: 0; green: 0; red: 139; alpha: 255); 181 182 //Pink colors 183 CSSPink: TBGRAPixel = (blue: 203; green: 192; red: 255; alpha: 255); 184 CSSLightPink: TBGRAPixel = (blue: 193; green: 182; red: 255; alpha: 255); 185 CSSHotPink: TBGRAPixel = (blue: 180; green: 105; red: 255; alpha: 255); 186 CSSDeepPink: TBGRAPixel = (blue: 147; green: 20; red: 255; alpha: 255); 187 CSSMediumVioletRed: TBGRAPixel = (blue: 133; green: 21; red: 199; alpha: 255); 188 CSSPaleVioletRed: TBGRAPixel = (blue: 147; green: 112; red: 219; alpha: 255); 189 190 //Orange colors 191 CSSLightSalmon: TBGRAPixel = (blue: 122; green: 160; red: 255; alpha: 255); 192 CSSCoral: TBGRAPixel = (blue: 80; green: 127; red: 255; alpha: 255); 193 CSSTomato: TBGRAPixel = (blue: 71; green: 99; red: 255; alpha: 255); 194 CSSOrangeRed: TBGRAPixel = (blue: 0; green: 69; red: 255; alpha: 255); 195 CSSDarkOrange: TBGRAPixel = (blue: 0; green: 140; red: 255; alpha: 255); 196 CSSOrange: TBGRAPixel = (blue: 0; green: 165; red: 255; alpha: 255); 197 198 //Yellow colors 199 CSSGold: TBGRAPixel = (blue: 0; green: 215; red: 255; alpha: 255); 200 CSSYellow: TBGRAPixel = (blue: 0; green: 255; red: 255; alpha: 255); 201 CSSLightYellow: TBGRAPixel = (blue: 224; green: 255; red: 255; alpha: 255); 202 CSSLemonChiffon: TBGRAPixel = (blue: 205; green: 250; red: 255; alpha: 255); 203 CSSLightGoldenrodYellow: TBGRAPixel = (blue: 210; green: 250; red: 250; alpha: 255); 204 CSSPapayaWhip: TBGRAPixel = (blue: 213; green: 239; red: 255; alpha: 255); 205 CSSMoccasin: TBGRAPixel = (blue: 181; green: 228; red: 255; alpha: 255); 206 CSSPeachPuff: TBGRAPixel = (blue: 185; green: 218; red: 255; alpha: 255); 207 CSSPaleGoldenrod: TBGRAPixel = (blue: 170; green: 232; red: 238; alpha: 255); 208 CSSKhaki: TBGRAPixel = (blue: 140; green: 230; red: 240; alpha: 255); 209 CSSDarkKhaki: TBGRAPixel = (blue: 107; green: 183; red: 189; alpha: 255); 210 211 //Purple colors 212 CSSLavender: TBGRAPixel = (blue: 250; green: 230; red: 230; alpha: 255); 213 CSSThistle: TBGRAPixel = (blue: 216; green: 191; red: 216; alpha: 255); 214 CSSPlum: TBGRAPixel = (blue: 221; green: 160; red: 221; alpha: 255); 215 CSSViolet: TBGRAPixel = (blue: 238; green: 130; red: 238; alpha: 255); 216 CSSOrchid: TBGRAPixel = (blue: 214; green: 112; red: 218; alpha: 255); 217 CSSFuchsia: TBGRAPixel = (blue: 255; green: 0; red: 255; alpha: 255); 218 CSSMagenta: TBGRAPixel = (blue: 255; green: 0; red: 255; alpha: 255); 219 CSSMediumOrchid: TBGRAPixel = (blue: 211; green: 85; red: 186; alpha: 255); 220 CSSMediumPurple: TBGRAPixel = (blue: 219; green: 112; red: 147; alpha: 255); 221 CSSBlueViolet: TBGRAPixel = (blue: 226; green: 43; red: 138; alpha: 255); 222 CSSDarkViolet: TBGRAPixel = (blue: 211; green: 0; red: 148; alpha: 255); 223 CSSDarkOrchid: TBGRAPixel = (blue: 204; green: 50; red: 153; alpha: 255); 224 CSSDarkMagenta: TBGRAPixel = (blue: 139; green: 0; red: 139; alpha: 255); 225 CSSPurple: TBGRAPixel = (blue: 128; green: 0; red: 128; alpha: 255); 226 CSSIndigo: TBGRAPixel = (blue: 130; green: 0; red: 75; alpha: 255); 227 CSSDarkSlateBlue: TBGRAPixel = (blue: 139; green: 61; red: 72; alpha: 255); 228 CSSSlateBlue: TBGRAPixel = (blue: 205; green: 90; red: 106; alpha: 255); 229 CSSMediumSlateBlue: TBGRAPixel = (blue: 238; green: 104; red: 123; alpha: 255); 230 231 //Green colors 232 CSSGreenYellow: TBGRAPixel = (blue: 47; green: 255; red: 173; alpha: 255); 233 CSSChartreuse: TBGRAPixel = (blue: 0; green: 255; red: 127; alpha: 255); 234 CSSLawnGreen: TBGRAPixel = (blue: 0; green: 252; red: 124; alpha: 255); 235 CSSLime: TBGRAPixel = (blue: 0; green: 255; red: 0; alpha: 255); 236 CSSLimeGreen: TBGRAPixel = (blue: 50; green: 205; red: 50; alpha: 255); 237 CSSPaleGreen: TBGRAPixel = (blue: 152; green: 251; red: 152; alpha: 255); 238 CSSLightGreen: TBGRAPixel = (blue: 144; green: 238; red: 144; alpha: 255); 239 CSSMediumSpringGreen: TBGRAPixel = (blue: 154; green: 250; red: 0; alpha: 255); 240 CSSSpringGreen: TBGRAPixel = (blue: 127; green: 255; red: 0; alpha: 255); 241 CSSMediumSeaGreen: TBGRAPixel = (blue: 113; green: 179; red: 60; alpha: 255); 242 CSSSeaGreen: TBGRAPixel = (blue: 87; green: 139; red: 46; alpha: 255); 243 CSSForestGreen: TBGRAPixel = (blue: 34; green: 139; red: 34; alpha: 255); 244 CSSGreen: TBGRAPixel = (blue: 0; green: 128; red: 0; alpha: 255); 245 CSSDarkGreen: TBGRAPixel = (blue: 0; green: 100; red: 0; alpha: 255); 246 CSSYellowGreen: TBGRAPixel = (blue: 50; green: 205; red: 154; alpha: 255); 247 CSSOliveDrab: TBGRAPixel = (blue: 35; green: 142; red: 107; alpha: 255); 248 CSSOlive: TBGRAPixel = (blue: 0; green: 128; red: 128; alpha: 255); 249 CSSDarkOliveGreen: TBGRAPixel = (blue: 47; green: 107; red: 85; alpha: 255); 250 CSSMediumAquamarine: TBGRAPixel = (blue: 170; green: 205; red: 102; alpha: 255); 251 CSSDarkSeaGreen: TBGRAPixel = (blue: 143; green: 188; red: 143; alpha: 255); 252 CSSLightSeaGreen: TBGRAPixel = (blue: 170; green: 178; red: 32; alpha: 255); 253 CSSDarkCyan: TBGRAPixel = (blue: 139; green: 139; red: 0; alpha: 255); 254 CSSTeal: TBGRAPixel = (blue: 128; green: 128; red: 0; alpha: 255); 255 256 //Blue/Cyan colors 257 CSSAqua: TBGRAPixel = (blue: 255; green: 255; red: 0; alpha: 255); 258 CSSCyan: TBGRAPixel = (blue: 255; green: 255; red: 0; alpha: 255); 259 CSSLightCyan: TBGRAPixel = (blue: 255; green: 255; red: 224; alpha: 255); 260 CSSPaleTurquoise: TBGRAPixel = (blue: 238; green: 238; red: 175; alpha: 255); 261 CSSAquamarine: TBGRAPixel = (blue: 212; green: 255; red: 127; alpha: 255); 262 CSSTurquoise: TBGRAPixel = (blue: 208; green: 224; red: 64; alpha: 255); 263 CSSMediumTurquoise: TBGRAPixel = (blue: 204; green: 209; red: 72; alpha: 255); 264 CSSDarkTurquoise: TBGRAPixel = (blue: 209; green: 206; red: 0; alpha: 255); 265 CSSCadetBlue: TBGRAPixel = (blue: 160; green: 158; red: 95; alpha: 255); 266 CSSSteelBlue: TBGRAPixel = (blue: 180; green: 130; red: 70; alpha: 255); 267 CSSLightSteelBlue: TBGRAPixel = (blue: 222; green: 196; red: 176; alpha: 255); 268 CSSPowderBlue: TBGRAPixel = (blue: 230; green: 224; red: 176; alpha: 255); 269 CSSLightBlue: TBGRAPixel = (blue: 230; green: 216; red: 173; alpha: 255); 270 CSSSkyBlue: TBGRAPixel = (blue: 235; green: 206; red: 135; alpha: 255); 271 CSSLightSkyBlue: TBGRAPixel = (blue: 250; green: 206; red: 135; alpha: 255); 272 CSSDeepSkyBlue: TBGRAPixel = (blue: 255; green: 191; red: 0; alpha: 255); 273 CSSDodgerBlue: TBGRAPixel = (blue: 255; green: 144; red: 30; alpha: 255); 274 CSSCornflowerBlue: TBGRAPixel = (blue: 237; green: 149; red: 100; alpha: 255); 275 CSSRoyalBlue: TBGRAPixel = (blue: 255; green: 105; red: 65; alpha: 255); 276 CSSBlue: TBGRAPixel = (blue: 255; green: 0; red: 0; alpha: 255); 277 CSSMediumBlue: TBGRAPixel = (blue: 205; green: 0; red: 0; alpha: 255); 278 CSSDarkBlue: TBGRAPixel = (blue: 139; green: 0; red: 0; alpha: 255); 279 CSSNavy: TBGRAPixel = (blue: 128; green: 0; red: 0; alpha: 255); 280 CSSMidnightBlue: TBGRAPixel = (blue: 112; green: 25; red: 25; alpha: 255); 281 282 //Brown colors 283 CSSCornsilk: TBGRAPixel = (blue: 220; green: 248; red: 255; alpha: 255); 284 CSSBlanchedAlmond: TBGRAPixel = (blue: 205; green: 235; red: 255; alpha: 255); 285 CSSBisque: TBGRAPixel = (blue: 196; green: 228; red: 255; alpha: 255); 286 CSSNavajoWhite: TBGRAPixel = (blue: 173; green: 222; red: 255; alpha: 255); 287 CSSWheat: TBGRAPixel = (blue: 179; green: 222; red: 245; alpha: 255); 288 CSSBurlyWood: TBGRAPixel = (blue: 135; green: 184; red: 222; alpha: 255); 289 CSSTan: TBGRAPixel = (blue: 140; green: 180; red: 210; alpha: 255); 290 CSSRosyBrown: TBGRAPixel = (blue: 143; green: 143; red: 188; alpha: 255); 291 CSSSandyBrown: TBGRAPixel = (blue: 96; green: 164; red: 244; alpha: 255); 292 CSSGoldenrod: TBGRAPixel = (blue: 32; green: 165; red: 218; alpha: 255); 293 CSSDarkGoldenrod: TBGRAPixel = (blue: 11; green: 134; red: 184; alpha: 255); 294 CSSPeru: TBGRAPixel = (blue: 63; green: 133; red: 205; alpha: 255); 295 CSSChocolate: TBGRAPixel = (blue: 30; green: 105; red: 210; alpha: 255); 296 CSSSaddleBrown: TBGRAPixel = (blue: 19; green: 69; red: 139; alpha: 255); 297 CSSSienna: TBGRAPixel = (blue: 45; green: 82; red: 160; alpha: 255); 298 CSSBrown: TBGRAPixel = (blue: 42; green: 42; red: 165; alpha: 255); 299 CSSMaroon: TBGRAPixel = (blue: 0; green: 0; red: 128; alpha: 255); 300 301 //White colors 302 CSSWhite: TBGRAPixel = (blue: 255; green: 255; red: 255; alpha: 255); 303 CSSSnow: TBGRAPixel = (blue: 250; green: 250; red: 255; alpha: 255); 304 CSSHoneydew: TBGRAPixel = (blue: 240; green: 255; red: 250; alpha: 255); 305 CSSMintCream: TBGRAPixel = (blue: 250; green: 255; red: 245; alpha: 255); 306 CSSAzure: TBGRAPixel = (blue: 255; green: 255; red: 240; alpha: 255); 307 CSSAliceBlue: TBGRAPixel = (blue: 255; green: 248; red: 240; alpha: 255); 308 CSSGhostWhite: TBGRAPixel = (blue: 255; green: 248; red: 248; alpha: 255); 309 CSSWhiteSmoke: TBGRAPixel = (blue: 245; green: 245; red: 245; alpha: 255); 310 CSSSeashell: TBGRAPixel = (blue: 255; green: 245; red: 238; alpha: 255); 311 CSSBeige: TBGRAPixel = (blue: 220; green: 245; red: 245; alpha: 255); 312 CSSOldLace: TBGRAPixel = (blue: 230; green: 245; red: 253; alpha: 255); 313 CSSFloralWhite: TBGRAPixel = (blue: 240; green: 250; red: 255; alpha: 255); 314 CSSIvory: TBGRAPixel = (blue: 240; green: 255; red: 255; alpha: 255); 315 CSSAntiqueWhite: TBGRAPixel = (blue: 215; green: 235; red: 250; alpha: 255); 316 CSSLinen: TBGRAPixel = (blue: 230; green: 240; red: 250; alpha: 255); 317 CSSLavenderBlush: TBGRAPixel = (blue: 245; green: 240; red: 255; alpha: 255); 318 CSSMistyRose: TBGRAPixel = (blue: 255; green: 228; red: 255; alpha: 255); 319 320 //Gray colors 321 CSSGainsboro: TBGRAPixel = (blue: 220; green: 220; red: 220; alpha: 255); 322 CSSLightGray: TBGRAPixel = (blue: 211; green: 211; red: 211; alpha: 255); 323 CSSSilver: TBGRAPixel = (blue: 192; green: 192; red: 192; alpha: 255); 324 CSSDarkGray: TBGRAPixel = (blue: 169; green: 169; red: 169; alpha: 255); 325 CSSGray: TBGRAPixel = (blue: 128; green: 128; red: 128; alpha: 255); 326 CSSDimGray: TBGRAPixel = (blue: 105; green: 105; red: 105; alpha: 255); 327 CSSLightSlateGray: TBGRAPixel = (blue: 153; green: 136; red: 119; alpha: 255); 328 CSSSlateGray: TBGRAPixel = (blue: 144; green: 128; red: 112; alpha: 255); 329 CSSDarkSlateGray: TBGRAPixel = (blue: 79; green: 79; red: 47; alpha: 255); 330 CSSBlack: TBGRAPixel = (blue: 0; green: 0; red: 0; alpha: 255); 331 332 { This color is needed for drawing black shapes on the standard TCanvas, because 333 when drawing with pure black, there is no way to know if something has been 334 drawn or if it is transparent } 91 335 clBlackOpaque = TColor($010000); 92 336 337 type 338 TBGRAColorDefinition = record 339 Name: string; 340 Color: TBGRAPixel; 341 end; 342 343 { TBGRAColorList } 344 345 TBGRAColorList = class 346 protected 347 FFinished: boolean; 348 FNbColors: integer; 349 FColors: array of TBGRAColorDefinition; 350 function GetByIndex(Index: integer): TBGRAPixel; 351 function GetByName(Name: string): TBGRAPixel; 352 function GetName(Index: integer): string; 353 public 354 constructor Create; 355 procedure Add(Name: string; Color: TBGRAPixel); 356 procedure Finished; 357 function IndexOf(Name: string): integer; 358 359 property ByName[Name: string]: TBGRAPixel read GetByName; 360 property ByIndex[Index: integer]: TBGRAPixel read GetByIndex; default; 361 property Name[Index: integer]: string read GetName; 362 property Count: integer read FNbColors; 363 end; 364 365 var 366 CSSColors: TBGRAColorList; 367 93 368 function isEmptyPointF(pt: TPointF): boolean; 94 369 370 type 371 TFontPixelMetric = record 372 Defined: boolean; 373 Baseline, xLine, CapLine, DescentLine, Lineheight: integer; 374 end; 375 376 { A scanner is like an image, but its content has no limit and can be calculated on the fly. 377 It must not implement reference counting. } 378 IBGRAScanner = interface 379 procedure ScanMoveTo(X,Y: Integer); 380 function ScanNextPixel: TBGRAPixel; 381 function ScanAt(X,Y: Single): TBGRAPixel; 382 procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); 383 function IsScanPutPixelsDefined: boolean; 384 end; 385 386 TScanAtFunction = function (X,Y: Single): TBGRAPixel of object; 387 TScanNextPixelFunction = function: TBGRAPixel of object; 388 TBGRACustomGradient = class; 389 390 { TBGRACustomBitmap } 391 392 TBGRACustomBitmap = class(TFPCustomImage,IBGRAScanner) // a bitmap can be used as a scanner 393 private 394 function GetFontAntialias: Boolean; 395 procedure SetFontAntialias(const AValue: Boolean); 396 protected 397 { accessors to properies } 398 function GetHeight: integer; virtual; abstract; 399 function GetWidth: integer; virtual; abstract; 400 function GetDataPtr: PBGRAPixel; virtual; abstract; 401 function GetNbPixels: integer; virtual; abstract; 402 function CheckEmpty: boolean; virtual; abstract; 403 function GetHasTransparentPixels: boolean; virtual; abstract; 404 function GetAverageColor: TColor; virtual; abstract; 405 function GetAveragePixel: TBGRAPixel; virtual; abstract; 406 procedure SetCanvasOpacity(AValue: byte); virtual; abstract; 407 function GetScanLine(y: integer): PBGRAPixel; virtual; abstract; 408 function GetRefCount: integer; virtual; abstract; 409 function GetBitmap: TBitmap; virtual; abstract; 410 function GetLineOrder: TRawImageLineOrder; virtual; abstract; 411 function GetCanvasFP: TFPImageCanvas; virtual; abstract; 412 function GetCanvasDrawModeFP: TDrawMode; virtual; abstract; 413 procedure SetCanvasDrawModeFP(const AValue: TDrawMode); virtual; abstract; 414 function GetCanvas: TCanvas; virtual; abstract; 415 function GetCanvasOpacity: byte; virtual; abstract; 416 function GetCanvasAlphaCorrection: boolean; virtual; abstract; 417 procedure SetCanvasAlphaCorrection(const AValue: boolean); virtual; abstract; 418 function GetFontHeight: integer; virtual; abstract; 419 procedure SetFontHeight(AHeight: integer); virtual; abstract; 420 function GetFontFullHeight: integer; virtual; abstract; 421 procedure SetFontFullHeight(AHeight: integer); virtual; abstract; 422 function GetPenStyle: TPenStyle; virtual; abstract; 423 procedure SetPenStyle(const AValue: TPenStyle); virtual; abstract; 424 function GetCustomPenStyle: TBGRAPenStyle; virtual; abstract; 425 procedure SetCustomPenStyle(const AValue: TBGRAPenStyle); virtual; abstract; 426 function GetClipRect: TRect; virtual; abstract; 427 procedure SetClipRect(const AValue: TRect); virtual; abstract; 428 function GetFontPixelMetric: TFontPixelMetric; virtual; abstract; 429 function LoadAsBmp32(Str: TStream): boolean; virtual; abstract; 430 431 public 432 Caption: string; //user defined caption 433 434 //font style 435 FontName: string; 436 FontStyle: TFontStyles; 437 FontQuality : TBGRAFontQuality; 438 FontOrientation: integer; 439 440 //line style 441 LineCap: TPenEndCap; 442 JoinStyle: TPenJoinStyle; 443 JoinMiterLimit: single; 444 445 FillMode: TFillMode; //winding or alternate 446 447 { The resample filter is used when resizing the bitmap, and 448 scan interpolation filter is used when the bitmap is used 449 as a scanner (IBGRAScanner) } 450 ResampleFilter, 451 ScanInterpolationFilter: TResampleFilter; 452 ScanOffset: TPoint; 453 454 constructor Create; virtual; abstract; overload; 455 constructor Create(ABitmap: TBitmap); virtual; abstract; overload; 456 constructor Create(AWidth, AHeight: integer; Color: TColor); virtual; abstract; overload; 457 constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); virtual; abstract; overload; 458 constructor Create(AFilename: string); virtual; abstract; overload; 459 constructor Create(AStream: TStream); virtual; abstract; overload; 460 461 function NewBitmap(AWidth, AHeight: integer): TBGRACustomBitmap; virtual; abstract; overload; 462 function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; virtual; abstract; overload; 463 function NewBitmap(Filename: string): TBGRACustomBitmap; virtual; abstract; overload; 464 465 procedure LoadFromFile(const filename: string); virtual; 466 procedure LoadFromStream(Str: TStream); virtual; 467 procedure LoadFromStream(Str: TStream; Handler: TFPCustomImageReader); virtual; 468 procedure SaveToFile(const filename: string); virtual; 469 procedure SaveToFile(const filename: string; Handler:TFPCustomImageWriter); virtual; 470 procedure SaveToStreamAsPng(Str: TStream); virtual; abstract; 471 procedure Assign(ABitmap: TBitmap); virtual; abstract; overload; 472 procedure Assign(MemBitmap: TBGRACustomBitmap); virtual; abstract; overload; 473 procedure Serialize(AStream: TStream); virtual; abstract; 474 procedure Deserialize(AStream: TStream); virtual; abstract; 475 476 {Pixel functions} 477 procedure SetPixel(x, y: integer; c: TColor); virtual; abstract; overload; 478 procedure XorPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 479 procedure SetPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 480 procedure DrawPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 481 procedure DrawPixel(x, y: integer; ec: TExpandedPixel); virtual; abstract; overload; 482 procedure FastBlendPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; 483 procedure ErasePixel(x, y: integer; alpha: byte); virtual; abstract; 484 procedure AlphaPixel(x, y: integer; alpha: byte); virtual; abstract; 485 function GetPixel(x, y: integer): TBGRAPixel; virtual; abstract; 486 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload; 487 function GetPixelCycle(x, y: integer): TBGRAPixel; virtual; 488 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload; 489 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; virtual; abstract; overload; 490 491 {Line primitives} 492 procedure SetHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 493 procedure XorHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 494 procedure DrawHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; overload; 495 procedure DrawHorizLine(x, y, x2: integer; ec: TExpandedPixel); virtual; abstract; overload; 496 procedure DrawHorizLine(x, y, x2: integer; texture: IBGRAScanner); virtual; abstract; overload; 497 procedure FastBlendHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 498 procedure AlphaHorizLine(x, y, x2: integer; alpha: byte); virtual; abstract; 499 procedure SetVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 500 procedure XorVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 501 procedure DrawVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 502 procedure AlphaVertLine(x, y, y2: integer; alpha: byte); virtual; abstract; 503 procedure FastBlendVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 504 procedure DrawHorizLineDiff(x, y, x2: integer; c, compare: TBGRAPixel; 505 maxDiff: byte); virtual; abstract; 506 507 {Shapes} 508 procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); virtual; abstract; 509 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); virtual; abstract; overload; 510 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); virtual; abstract; overload; 511 procedure DrawLineAntialias(x1, y1, x2, y2: single; c: TBGRAPixel; w: single); virtual; abstract; overload; 512 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single); virtual; abstract; overload; 513 procedure DrawLineAntialias(x1, y1, x2, y2: single; c: TBGRAPixel; w: single; Closed: boolean); virtual; abstract; overload; 514 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single; Closed: boolean); virtual; abstract; overload; 515 516 procedure DrawPolyLineAntialias(const points: array of TPoint; c: TBGRAPixel; DrawLastPixel: boolean); virtual; overload; 517 procedure DrawPolyLineAntialias(const points: array of TPoint; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); virtual; overload; 518 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); virtual; abstract; overload; 519 procedure DrawPolyLineAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); virtual; abstract; overload; 520 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; Closed: boolean); virtual; abstract; overload; 521 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); virtual; abstract; overload; 522 procedure DrawPolygonAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); virtual; abstract; overload; 523 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single); virtual; abstract; overload; 524 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single; Closed: boolean); virtual; abstract; overload; 525 procedure ErasePolyLineAntialias(const points: array of TPointF; alpha: byte; w: single); virtual; abstract; overload; 526 527 procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); virtual; abstract; overload; 528 procedure FillTriangleLinearColorAntialias(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); virtual; abstract; overload; 529 procedure FillTriangleLinearMapping(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; TextureInterpolation: Boolean= True); virtual; abstract; overload; 530 procedure FillTriangleLinearMappingLightness(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF; light1,light2,light3: word; TextureInterpolation: Boolean= True); virtual; abstract; overload; 531 procedure FillTriangleLinearMappingAntialias(pt1,pt2,pt3: TPointF; texture: IBGRAScanner; tex1, tex2, tex3: TPointF); virtual; abstract; overload; 532 533 procedure FillQuadLinearColor(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); virtual; abstract; overload; 534 procedure FillQuadLinearColorAntialias(pt1,pt2,pt3,pt4: TPointF; c1,c2,c3,c4: TBGRAPixel); virtual; abstract; overload; 535 procedure FillQuadLinearMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; TextureInterpolation: Boolean= True); virtual; abstract; overload; 536 procedure FillQuadLinearMappingLightness(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; light1,light2,light3,light4: word; TextureInterpolation: Boolean= True); virtual; abstract; overload; 537 procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 538 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 539 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 540 541 procedure FillPolyLinearColor(const points: array of TPointF; AColors: array of TBGRAPixel); virtual; abstract; overload; 542 procedure FillPolyLinearMapping(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); virtual; abstract; overload; 543 procedure FillPolyLinearMappingLightness(const points: array of TPointF; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean); virtual; abstract; overload; 544 procedure FillPolyPerspectiveMapping(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; TextureInterpolation: Boolean); virtual; abstract; overload; 545 procedure FillPolyPerspectiveMappingLightness(const points: array of TPointF; const pointsZ: array of single; texture: IBGRAScanner; texCoords: array of TPointF; lightnesses: array of word; TextureInterpolation: Boolean); virtual; abstract; overload; 546 547 procedure FillPoly(const points: array of TPointF; c: TBGRAPixel; drawmode: TDrawMode); virtual; abstract; 548 procedure FillPoly(const points: array of TPointF; texture: IBGRAScanner; drawmode: TDrawMode); virtual; abstract; 549 procedure FillPolyAntialias(const points: array of TPointF; c: TBGRAPixel); virtual; abstract; 550 procedure FillPolyAntialias(const points: array of TPointF; texture: IBGRAScanner); virtual; abstract; 551 procedure ErasePoly(const points: array of TPointF; alpha: byte); virtual; abstract; 552 procedure ErasePolyAntialias(const points: array of TPointF; alpha: byte); virtual; abstract; 553 554 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single); virtual; abstract; 555 procedure EllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner; w: single); virtual; abstract; 556 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single; back: TBGRAPixel); virtual; abstract; 557 procedure FillEllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel); virtual; abstract; 558 procedure FillEllipseAntialias(x, y, rx, ry: single; texture: IBGRAScanner); virtual; abstract; 559 procedure FillEllipseLinearColorAntialias(x, y, rx, ry: single; outercolor, innercolor: TBGRAPixel); virtual; abstract; 560 procedure EraseEllipseAntialias(x, y, rx, ry: single; alpha: byte); virtual; abstract; 561 562 procedure Rectangle(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); virtual; abstract; overload; 563 procedure Rectangle(x, y, x2, y2: integer; BorderColor, FillColor: TBGRAPixel; mode: TDrawMode); virtual; abstract; overload; 564 procedure Rectangle(x, y, x2, y2: integer; c: TColor); virtual; overload; 565 procedure Rectangle(r: TRect; c: TBGRAPixel; mode: TDrawMode); virtual; overload; 566 procedure Rectangle(r: TRect; BorderColor, FillColor: TBGRAPixel; mode: TDrawMode); virtual;overload; 567 procedure Rectangle(r: TRect; c: TColor); virtual; overload; 568 procedure RectangleAntialias(x, y, x2, y2: single; c: TBGRAPixel; w: single); virtual; overload; 569 procedure RectangleAntialias(x, y, x2, y2: single; c: TBGRAPixel; w: single; back: TBGRAPixel); virtual; abstract; overload; 570 procedure RectangleAntialias(x, y, x2, y2: single; texture: IBGRAScanner; w: single); virtual; abstract; overload; 571 572 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor, FillColor: TBGRAPixel); virtual; abstract; 573 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; w: single; options: TRoundRectangleOptions = []); virtual; abstract; 574 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; pencolor: TBGRAPixel; w: single; fillcolor: TBGRAPixel; options: TRoundRectangleOptions = []); virtual; abstract; 575 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); virtual; abstract; 576 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; w: single; options: TRoundRectangleOptions = []); virtual; abstract; 577 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; options: TRoundRectangleOptions = []); virtual; abstract; 578 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions = []); virtual; abstract; 579 procedure EraseRoundRectAntialias(x,y,x2,y2,rx,ry: single; alpha: byte; options: TRoundRectangleOptions = []); virtual; abstract; 580 581 procedure FillRect(r: TRect; c: TColor); virtual; overload; 582 procedure FillRect(r: TRect; c: TBGRAPixel; mode: TDrawMode); virtual; overload; 583 procedure FillRect(x, y, x2, y2: integer; c: TColor); virtual; overload; 584 procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); virtual; abstract; overload; 585 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); virtual; abstract; 586 procedure FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel); virtual; abstract; 587 procedure FillRectAntialias(x, y, x2, y2: single; texture: IBGRAScanner); virtual; abstract; 588 procedure EraseRectAntialias(x, y, x2, y2: single; alpha: byte); virtual; abstract; 589 procedure AlphaFillRect(x, y, x2, y2: integer; alpha: byte); virtual; abstract; 590 591 procedure TextOut(x, y: integer; s: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; overload; 592 procedure TextOut(x, y: integer; s: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; overload; 593 procedure TextOutAngle(x, y, orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; 594 procedure TextOutAngle(x, y, orientation: integer; s: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; 595 procedure TextOut(x, y: integer; s: string; c: TBGRAPixel); virtual; overload; 596 procedure TextOut(x, y: integer; s: string; c: TColor); virtual; overload; 597 procedure TextOut(x, y: integer; s: string; texture: IBGRAScanner); virtual; overload; 598 procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); virtual; abstract; overload; 599 procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); virtual; abstract; overload; 600 procedure TextRect(ARect: TRect; s: string; halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); virtual; overload; 601 procedure TextRect(ARect: TRect; s: string; halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); virtual; overload; 602 function TextSize(s: string): TSize; virtual; abstract; 603 604 {Spline} 605 function ComputeClosedSpline(const APoints: array of TPointF; AStyle: TSplineStyle): ArrayOfTPointF; virtual; abstract; 606 function ComputeOpenedSpline(const APoints: array of TPointF; AStyle: TSplineStyle): ArrayOfTPointF; virtual; abstract; 607 function ComputeBezierCurve(const curve: TCubicBezierCurve): ArrayOfTPointF; virtual; abstract; 608 function ComputeBezierCurve(const curve: TQuadraticBezierCurve): ArrayOfTPointF; virtual; abstract; 609 function ComputeBezierSpline(const spline: array of TCubicBezierCurve): ArrayOfTPointF; virtual; abstract; 610 function ComputeBezierSpline(const spline: array of TQuadraticBezierCurve): ArrayOfTPointF; virtual; abstract; 611 612 function ComputeWidePolyline(const points: array of TPointF; w: single): ArrayOfTPointF; virtual; abstract; 613 function ComputeWidePolyline(const points: array of TPointF; w: single; Closed: boolean): ArrayOfTPointF; virtual; abstract; 614 function ComputeWidePolygon(const points: array of TPointF; w: single): ArrayOfTPointF; virtual; abstract; 615 616 function ComputeEllipse(x,y,rx,ry: single): ArrayOfTPointF; virtual; abstract; 617 function ComputeEllipse(x,y,rx,ry,w: single): ArrayOfTPointF; virtual; abstract; 618 function ComputeArc65536(x,y,rx,ry: single; start65536,end65536: word): ArrayOfTPointF; virtual; abstract; 619 function ComputeArcRad(x,y,rx,ry: single; startRad,endRad: single): ArrayOfTPointF; virtual; abstract; 620 function ComputeRoundRect(x1,y1,x2,y2,rx,ry: single): ArrayOfTPointF; virtual; abstract; 621 function ComputeRoundRect(x1,y1,x2,y2,rx,ry: single; options: TRoundRectangleOptions): ArrayOfTPointF; virtual; abstract; 622 function ComputePie65536(x,y,rx,ry: single; start65536,end65536: word): ArrayOfTPointF; virtual; abstract; 623 function ComputePieRad(x,y,rx,ry: single; startRad,endRad: single): ArrayOfTPointF; virtual; abstract; 624 625 {Filling} 626 procedure FillTransparent; virtual; 627 procedure NoClip; virtual; abstract; 628 procedure ApplyGlobalOpacity(alpha: byte); virtual; abstract; 629 procedure Fill(c: TColor); virtual; overload; 630 procedure Fill(c: TBGRAPixel); virtual; overload; 631 procedure Fill(texture: IBGRAScanner; mode: TDrawMode); virtual; abstract; overload; 632 procedure Fill(texture: IBGRAScanner); virtual; abstract; overload; 633 procedure Fill(c: TBGRAPixel; start, Count: integer); virtual; abstract; overload; 634 procedure DrawPixels(c: TBGRAPixel; start, Count: integer); virtual; abstract; 635 procedure AlphaFill(alpha: byte); virtual; overload; 636 procedure AlphaFill(alpha: byte; start, Count: integer); virtual; abstract; overload; 637 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel); virtual; abstract; overload; 638 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner); virtual; abstract; overload; 639 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ARGBOrder: boolean = true); virtual; abstract; overload; 640 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ARGBOrder: boolean = true); virtual; abstract; overload; 641 procedure ReplaceColor(before, after: TColor); virtual; abstract; overload; 642 procedure ReplaceColor(before, after: TBGRAPixel); virtual; abstract; overload; 643 procedure ReplaceTransparent(after: TBGRAPixel); virtual; abstract; overload; 644 procedure FloodFill(X, Y: integer; Color: TBGRAPixel; 645 mode: TFloodfillMode; Tolerance: byte = 0); virtual; 646 procedure ParallelFloodFill(X, Y: integer; Dest: TBGRACustomBitmap; Color: TBGRAPixel; 647 mode: TFloodfillMode; Tolerance: byte = 0); virtual; abstract; 648 procedure GradientFill(x, y, x2, y2: integer; c1, c2: TBGRAPixel; 649 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 650 gammaColorCorrection: boolean = True; Sinus: Boolean=False); virtual; abstract; 651 procedure GradientFill(x, y, x2, y2: integer; gradient: TBGRACustomGradient; 652 gtype: TGradientType; o1, o2: TPointF; mode: TDrawMode; 653 Sinus: Boolean=False); virtual; abstract; 654 function CreateBrushTexture(ABrushStyle: TBrushStyle; APatternColor, ABackgroundColor: TBGRAPixel; 655 AWidth: integer = 8; AHeight: integer = 8; APenWidth: single = 1): TBGRACustomBitmap; virtual; abstract; 656 657 {Canvas drawing functions} 658 procedure DataDrawTransparent(ACanvas: TCanvas; Rect: TRect; 659 AData: Pointer; ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); virtual; abstract; 660 procedure DataDrawOpaque(ACanvas: TCanvas; Rect: TRect; AData: Pointer; 661 ALineOrder: TRawImageLineOrder; AWidth, AHeight: integer); virtual; abstract; 662 procedure GetImageFromCanvas(CanvasSource: TCanvas; x, y: integer); virtual; abstract; 663 procedure Draw(ACanvas: TCanvas; x, y: integer; Opaque: boolean = True); virtual; abstract; 664 procedure Draw(ACanvas: TCanvas; Rect: TRect; Opaque: boolean = True); virtual; abstract; 665 procedure DrawPart(ARect: TRect; Canvas: TCanvas; x, y: integer; Opaque: boolean); virtual; 666 function GetPart(ARect: TRect): TBGRACustomBitmap; virtual; abstract; 667 function GetPtrBitmap(Top,Bottom: Integer): TBGRACustomBitmap; virtual; abstract; 668 procedure InvalidateBitmap; virtual; abstract; //call if you modify with Scanline 669 procedure LoadFromBitmapIfNeeded; virtual; abstract; //call to ensure that bitmap data is up to date 670 671 {BGRA bitmap functions} 672 procedure PutImage(x, y: integer; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); virtual; abstract; 673 procedure PutImageSubpixel(x, y: single; Source: TBGRACustomBitmap); 674 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte=255); virtual; abstract; 675 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255); virtual; abstract; 676 procedure BlendImage(x, y: integer; Source: TBGRACustomBitmap; 677 operation: TBlendOperation); virtual; abstract; 678 function Duplicate(DuplicateProperties: Boolean = False): TBGRACustomBitmap; virtual; abstract; 679 function Equals(comp: TBGRACustomBitmap): boolean; virtual; abstract; 680 function Equals(comp: TBGRAPixel): boolean; virtual; abstract; 681 function Resample(newWidth, newHeight: integer; 682 mode: TResampleMode = rmFineResample): TBGRACustomBitmap; virtual; abstract; 683 procedure VerticalFlip; virtual; abstract; 684 procedure HorizontalFlip; virtual; abstract; 685 function RotateCW: TBGRACustomBitmap; virtual; abstract; 686 function RotateCCW: TBGRACustomBitmap; virtual; abstract; 687 procedure Negative; virtual; abstract; 688 procedure LinearNegative; virtual; abstract; 689 procedure SwapRedBlue; virtual; abstract; 690 procedure GrayscaleToAlpha; virtual; abstract; 691 procedure AlphaToGrayscale; virtual; abstract; 692 procedure ApplyMask(mask: TBGRACustomBitmap); virtual; abstract; 693 function GetImageBounds(Channel: TChannel = cAlpha): TRect; virtual; abstract; 694 function GetImageBounds(Channels: TChannels): TRect; virtual; abstract; 695 function MakeBitmapCopy(BackgroundColor: TColor): TBitmap; virtual; abstract; 696 697 {Filters} 698 function FilterSmartZoom3(Option: TMedianOption): TBGRACustomBitmap; virtual; abstract; 699 function FilterMedian(Option: TMedianOption): TBGRACustomBitmap; virtual; abstract; 700 function FilterSmooth: TBGRACustomBitmap; virtual; abstract; 701 function FilterSharpen: TBGRACustomBitmap; virtual; abstract; 702 function FilterContour: TBGRACustomBitmap; virtual; abstract; 703 function FilterBlurRadial(radius: integer; 704 blurType: TRadialBlurType): TBGRACustomBitmap; virtual; abstract; 705 function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; virtual; abstract; 706 function FilterBlurMotion(distance: integer; angle: single; 707 oriented: boolean): TBGRACustomBitmap; virtual; abstract; 708 function FilterCustomBlur(mask: TBGRACustomBitmap): TBGRACustomBitmap; virtual; abstract; 709 function FilterEmboss(angle: single): TBGRACustomBitmap; virtual; abstract; 710 function FilterEmbossHighlight(FillSelection: boolean): TBGRACustomBitmap; virtual; abstract; 711 function FilterGrayscale: TBGRACustomBitmap; virtual; abstract; 712 function FilterNormalize(eachChannel: boolean = True): TBGRACustomBitmap; virtual; abstract; 713 function FilterRotate(origin: TPointF; angle: single): TBGRACustomBitmap; virtual; abstract; 714 function FilterSphere: TBGRACustomBitmap; virtual; abstract; 715 function FilterTwirl(ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; virtual; abstract; 716 function FilterCylinder: TBGRACustomBitmap; virtual; abstract; 717 function FilterPlane: TBGRACustomBitmap; virtual; abstract; 718 719 property Data: PBGRAPixel Read GetDataPtr; 720 property Width: integer Read GetWidth; 721 property Height: integer Read GetHeight; 722 property NbPixels: integer Read GetNbPixels; 723 property Empty: boolean Read CheckEmpty; 724 725 property ScanLine[y: integer]: PBGRAPixel Read GetScanLine; 726 property RefCount: integer Read GetRefCount; 727 property Bitmap: TBitmap Read GetBitmap; //don't forget to call InvalidateBitmap before if you changed something with Scanline 728 property HasTransparentPixels: boolean Read GetHasTransparentPixels; 729 property AverageColor: TColor Read GetAverageColor; 730 property AveragePixel: TBGRAPixel Read GetAveragePixel; 731 property LineOrder: TRawImageLineOrder Read GetLineOrder; 732 property CanvasFP: TFPImageCanvas read GetCanvasFP; 733 property CanvasDrawModeFP: TDrawMode read GetCanvasDrawModeFP write SetCanvasDrawModeFP; 734 property Canvas: TCanvas Read GetCanvas; 735 property CanvasOpacity: byte Read GetCanvasOpacity Write SetCanvasOpacity; 736 property CanvasAlphaCorrection: boolean 737 Read GetCanvasAlphaCorrection Write SetCanvasAlphaCorrection; 738 739 property FontHeight: integer Read GetFontHeight Write SetFontHeight; 740 property PenStyle: TPenStyle read GetPenStyle Write SetPenStyle; 741 property CustomPenStyle: TBGRAPenStyle read GetCustomPenStyle write SetCustomPenStyle; 742 property ClipRect: TRect read GetClipRect write SetClipRect; 743 property FontAntialias: Boolean read GetFontAntialias write SetFontAntialias; //antialiasing (it's different from TFont antialiasing mode) 744 property FontFullHeight: integer read GetFontFullHeight write SetFontFullHeight; 745 property FontPixelMetric: TFontPixelMetric read GetFontPixelMetric; 746 747 //interface 748 function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 749 function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 750 function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 751 752 //IBGRAScanner 753 procedure ScanMoveTo(X,Y: Integer); virtual; abstract; 754 function ScanNextPixel: TBGRAPixel; virtual; abstract; 755 function ScanAt(X,Y: Single): TBGRAPixel; virtual; abstract; 756 procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); virtual; 757 function IsScanPutPixelsDefined: boolean; virtual; 758 end; 759 760 { TBGRACustomScanner } 761 762 TBGRACustomScanner = class(IBGRAScanner) 763 private 764 FCurX,FCurY: integer; 765 public 766 procedure ScanMoveTo(X,Y: Integer); virtual; 767 function ScanNextPixel: TBGRAPixel; virtual; 768 function ScanAt(X,Y: Single): TBGRAPixel; virtual; abstract; 769 procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); virtual; 770 function IsScanPutPixelsDefined: boolean; virtual; 771 function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 772 function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 773 function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 774 end; 775 776 TBGRACustomGradient = class 777 public 778 function GetColorAt(position: integer): TBGRAPixel; virtual; abstract; 779 function GetAverageColor: TBGRAPixel; virtual; abstract; 780 function GetMonochrome: boolean; virtual; abstract; 781 property Monochrome: boolean read GetMonochrome; 782 end; 783 784 type 785 TBGRABitmapAny = class of TBGRACustomBitmap; //used to create instances of the same type (see NewBitmap) 786 787 var 788 BGRABitmapFactory : TBGRABitmapAny; 789 790 { Color functions } 95 791 function GetIntensity(c: TExpandedPixel): word; inline; 96 792 function SetIntensity(c: TExpandedPixel; intensity: word): TExpandedPixel; 97 793 function GetLightness(c: TExpandedPixel): word; inline; 98 794 function SetLightness(c: TExpandedPixel; lightness: word): TExpandedPixel; 795 function ApplyLightnessFast(color: TBGRAPixel; lightness: word): TBGRAPixel; inline; 99 796 function BGRAToHSLA(c: TBGRAPixel): THSLAPixel; 797 function HSLAToExpanded(c: THSLAPixel): TExpandedPixel; 100 798 function HSLAToBGRA(c: THSLAPixel): TBGRAPixel; 799 function GtoH(ghue: word): word; 800 function HtoG(hue: word): word; 801 function HueDiff(h1, h2: word): word; 802 function GetHue(ec: TExpandedPixel): word; 803 function ColorImportance(ec: TExpandedPixel): word; 804 function GSBAToBGRA(c: THSLAPixel): TBGRAPixel; 805 function GSBAToHSLA(c: THSLAPixel): THSLAPixel; 101 806 function GammaExpansion(c: TBGRAPixel): TExpandedPixel; inline; 102 807 function GammaCompression(ec: TExpandedPixel): TBGRAPixel; inline; 808 function GammaCompression(red,green,blue,alpha: word): TBGRAPixel; inline; 103 809 function BGRAToGrayscale(c: TBGRAPixel): TBGRAPixel; 104 function MergeBGRA(c1, c2: TBGRAPixel): TBGRAPixel; 810 function GrayscaleToBGRA(lightness: word): TBGRAPixel; 811 function MergeBGRA(c1, c2: TBGRAPixel): TBGRAPixel; overload; 812 function MergeBGRA(c1: TBGRAPixel; weight1: integer; c2: TBGRAPixel; weight2: integer): TBGRAPixel; overload; 813 function MergeBGRA(ec1, ec2: TExpandedPixel): TExpandedPixel; overload; 105 814 function BGRA(red, green, blue, alpha: byte): TBGRAPixel; overload; inline; 106 815 function BGRA(red, green, blue: byte): TBGRAPixel; overload; inline; 107 816 function ColorToBGRA(color: TColor): TBGRAPixel; overload; 108 817 function ColorToBGRA(color: TColor; opacity: byte): TBGRAPixel; overload; 818 function BGRAToFPColor(AValue: TBGRAPixel): TFPColor; inline; 819 function FPColorToBGRA(AValue: TFPColor): TBGRAPixel; 109 820 function BGRAToColor(c: TBGRAPixel): TColor; 110 821 operator = (const c1, c2: TBGRAPixel): boolean; inline; 111 822 function ExpandedDiff(ec1, ec2: TExpandedPixel): word; 823 function BGRAWordDiff(c1, c2: TBGRAPixel): word; 112 824 function BGRADiff(c1, c2: TBGRAPixel): byte; 113 function PointF(x, y: single): TPointF;114 115 function PtInRect(pt: TPoint; r: TRect): boolean;116 117 function StrToGradientType(str: string): TGradientType;825 operator - (const c1, c2: TColorF): TColorF; inline; 826 operator + (const c1, c2: TColorF): TColorF; inline; 827 operator * (const c1, c2: TColorF): TColorF; inline; 828 operator * (const c1: TColorF; factor: single): TColorF; inline; 829 function ColorF(red,green,blue,alpha: single): TColorF; 118 830 function BGRAToStr(c: TBGRAPixel): string; 119 831 function StrToBGRA(str: string): TBGRAPixel; 120 832 833 { Get height [0..1] stored in a TBGRAPixel } 834 function MapHeight(Color: TBGRAPixel): Single; 835 836 { Get TBGRAPixel to store height [0..1] } 837 function MapHeightToBGRA(Height: Single; Alpha: Byte): TBGRAPixel; 838 839 840 { Gamma conversion arrays. Should be used as readonly } 121 841 var 842 // TBGRAPixel -> TExpandedPixel 122 843 GammaExpansionTab: packed array[0..255] of word; 844 845 // TExpandedPixel -> TBGRAPixel 123 846 GammaCompressionTab: packed array[0..65535] of byte; 124 847 848 { Point functions } 849 function PointF(x, y: single): TPointF; 850 function PointsF(const pts: array of TPointF): ArrayOfTPointF; 851 operator = (const pt1, pt2: TPointF): boolean; inline; 852 operator - (const pt1, pt2: TPointF): TPointF; inline; 853 operator - (const pt2: TPointF): TPointF; inline; 854 operator + (const pt1, pt2: TPointF): TPointF; inline; 855 operator * (const pt1, pt2: TPointF): single; inline; //scalar product 856 operator * (const pt1: TPointF; factor: single): TPointF; inline; 857 operator * (factor: single; const pt1: TPointF): TPointF; inline; 858 function PtInRect(pt: TPoint; r: TRect): boolean; 859 function VectLen(dx,dy: single): single; overload; 860 function VectLen(v: TPointF): single; overload; 861 862 { Line and polygon functions } 863 type 864 TLineDef = record 865 origin, dir: TPointF; 866 end; 867 868 function IntersectLine(line1, line2: TLineDef): TPointF; 869 function IntersectLine(line1, line2: TLineDef; out parallel: boolean): TPointF; 870 function IsConvex(const pts: array of TPointF; IgnoreAlign: boolean = true): boolean; 871 function DoesQuadIntersect(pt1,pt2,pt3,pt4: TPointF): boolean; 872 function DoesSegmentIntersect(pt1,pt2,pt3,pt4: TPointF): boolean; 873 874 { Cyclic functions } 875 function PositiveMod(value, cycle: integer): integer; inline; 876 877 { Sin65536 and Cos65536 are fast routines to compute sine and cosine as integer values. 878 They use a table to store already computed values. The return value is an integer 879 ranging from 0 to 65536, so the mean value is 32768 and the half amplitude is 880 32768 instead of 1. The input has a period of 65536, so you can supply any integer 881 without applying a modulo. } 882 procedure PrecalcSin65536; // compute all values now 883 function Sin65536(value: word): integer; inline; 884 function Cos65536(value: word): integer; inline; 885 125 886 implementation 126 887 127 888 uses Math, SysUtils; 128 889 890 function StrToBlendOperation(str: string): TBlendOperation; 891 var op: TBlendOperation; 892 begin 893 result := boTransparent; 894 str := LowerCase(str); 895 for op := low(TBlendOperation) to high(TBlendOperation) do 896 if str = LowerCase(BlendOperationStr[op]) then 897 begin 898 result := op; 899 exit; 900 end; 901 end; 902 903 function StrToGradientType(str: string): TGradientType; 904 var gt: TGradientType; 905 begin 906 result := gtLinear; 907 str := LowerCase(str); 908 for gt := low(TGradientType) to high(TGradientType) do 909 if str = LowerCase(GradientTypeStr[gt]) then 910 begin 911 result := gt; 912 exit; 913 end; 914 end; 915 916 { Make a pen style. Need an even number of values. See TBGRAPenStyle } 917 function BGRAPenStyle(dash1, space1: single; dash2: single; space2: single; 918 dash3: single; space3: single; dash4: single; space4: single): TBGRAPenStyle; 919 var 920 i: Integer; 921 begin 922 if dash4 <> 0 then 923 begin 924 setlength(result,8); 925 result[6] := dash4; 926 result[7] := space4; 927 result[4] := dash3; 928 result[5] := space3; 929 result[2] := dash2; 930 result[3] := space2; 931 end else 932 if dash3 <> 0 then 933 begin 934 setlength(result,6); 935 result[4] := dash3; 936 result[5] := space3; 937 result[2] := dash2; 938 result[3] := space2; 939 end else 940 if dash2 <> 0 then 941 begin 942 setlength(result,4); 943 result[2] := dash2; 944 result[3] := space2; 945 end else 946 begin 947 setlength(result,2); 948 end; 949 result[0] := dash1; 950 result[1] := space1; 951 for i := 0 to high(result) do 952 if result[i]=0 then 953 raise exception.Create('Zero is not a valid value'); 954 end; 955 956 { Bézier curves definitions. See : http://en.wikipedia.org/wiki/B%C3%A9zier_curve } 957 958 function ConcatPointsF(const APolylines: array of ArrayOfTPointF 959 ): ArrayOfTPointF; 960 var 961 i,pos,count:integer; 962 j: Integer; 963 begin 964 count := 0; 965 for i := 0 to high(APolylines) do 966 inc(count,length(APolylines[i])); 967 setlength(result,count); 968 pos := 0; 969 for i := 0 to high(APolylines) do 970 for j := 0 to high(APolylines[i]) do 971 begin 972 result[pos] := APolylines[i][j]; 973 inc(pos); 974 end; 975 end; 976 977 operator-(const v: TPoint3D): TPoint3D; 978 begin 979 result.x := -v.x; 980 result.y := -v.y; 981 result.z := -v.z; 982 end; 983 984 operator + (const v1,v2: TPoint3D): TPoint3D; inline; 985 begin 986 result.x := v1.x+v2.x; 987 result.y := v1.y+v2.y; 988 result.z := v1.z+v2.z; 989 end; 990 991 operator - (const v1,v2: TPoint3D): TPoint3D; inline; 992 begin 993 result.x := v1.x-v2.x; 994 result.y := v1.y-v2.y; 995 result.z := v1.z-v2.z; 996 end; 997 998 operator * (const v1: TPoint3D; const factor: single): TPoint3D; inline; 999 begin 1000 result.x := v1.x*factor; 1001 result.y := v1.y*factor; 1002 result.z := v1.z*factor; 1003 end; 1004 1005 function Point3D(x, y, z: single): TPoint3D; 1006 begin 1007 result.x := x; 1008 result.y := y; 1009 result.z := z; 1010 end; 1011 1012 operator=(const v1, v2: TPoint3D): boolean; 1013 begin 1014 result := (v1.x=v2.x) and (v1.y=v2.y) and (v1.z=v2.z); 1015 end; 1016 1017 operator * (const v1,v2: TPoint3D): single; inline; 1018 begin 1019 result := v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; 1020 end; 1021 1022 procedure Normalize3D(var v: TPoint3D); inline; 1023 var len: double; 1024 begin 1025 len := v*v; 1026 if len = 0 then exit; 1027 len := sqrt(len); 1028 v.x /= len; 1029 v.y /= len; 1030 v.z /= len; 1031 end; 1032 1033 procedure VectProduct3D(u,v: TPoint3D; out w: TPoint3D); 1034 begin 1035 w.x := u.y*v.z-u.z*v.y; 1036 w.y := u.z*v.x-u.x*v.z; 1037 w.z := u.x*v.Y-u.y*v.x; 1038 end; 1039 1040 // Define a Bézier curve with two control points. 1041 function BezierCurve(origin, control1, control2, destination: TPointF): TCubicBezierCurve; 1042 begin 1043 result.p1 := origin; 1044 result.c1 := control1; 1045 result.c2 := control2; 1046 result.p2 := destination; 1047 end; 1048 1049 // Define a Bézier curve with one control point. 1050 function BezierCurve(origin, control, destination: TPointF 1051 ): TQuadraticBezierCurve; 1052 begin 1053 result.p1 := origin; 1054 result.c := control; 1055 result.p2 := destination; 1056 end; 1057 1058 { Check if a PointF structure is empty or should be treated as a list separator } 129 1059 function isEmptyPointF(pt: TPointF): boolean; 130 1060 begin … … 132 1062 end; 133 1063 1064 { TBGRAColorList } 1065 1066 function TBGRAColorList.GetByIndex(Index: integer): TBGRAPixel; 1067 begin 1068 if (Index < 0) or (Index >= FNbColors) then 1069 result := BGRAPixelTransparent 1070 else 1071 result := FColors[Index].Color; 1072 end; 1073 1074 function TBGRAColorList.GetByName(Name: string): TBGRAPixel; 1075 var i: integer; 1076 begin 1077 i := IndexOf(Name); 1078 if i = -1 then 1079 result := BGRAPixelTransparent 1080 else 1081 result := FColors[i].Color; 1082 end; 1083 1084 function TBGRAColorList.GetName(Index: integer): string; 1085 begin 1086 if (Index < 0) or (Index >= FNbColors) then 1087 result := '' 1088 else 1089 result := FColors[Index].Name; 1090 end; 1091 1092 constructor TBGRAColorList.Create; 1093 begin 1094 FNbColors:= 0; 1095 FColors := nil; 1096 FFinished:= false; 1097 end; 1098 1099 procedure TBGRAColorList.Add(Name: string; Color: TBGRAPixel); 1100 begin 1101 if FFinished then 1102 raise Exception.Create('This list is already finished'); 1103 if length(FColors) = FNbColors then 1104 SetLength(FColors, FNbColors*2+1); 1105 FColors[FNbColors].Name := Name; 1106 FColors[FNbColors].Color := Color; 1107 inc(FNbColors); 1108 end; 1109 1110 procedure TBGRAColorList.Finished; 1111 begin 1112 if FFinished then exit; 1113 FFinished := true; 1114 SetLength(FColors, FNbColors); 1115 end; 1116 1117 function TBGRAColorList.IndexOf(Name: string): integer; 1118 var i: integer; 1119 begin 1120 for i := 0 to FNbColors-1 do 1121 if CompareText(Name, FColors[i].Name) = 0 then 1122 begin 1123 result := i; 1124 exit; 1125 end; 1126 result := -1; 1127 end; 1128 1129 { TBGRACustomBitmap } 1130 1131 function TBGRACustomBitmap.GetFontAntialias: Boolean; 1132 begin 1133 result := FontQuality <> fqSystem; 1134 end; 1135 1136 procedure TBGRACustomBitmap.SetFontAntialias(const AValue: Boolean); 1137 begin 1138 if AValue and not FontAntialias then 1139 FontQuality := fqFineAntialiasing 1140 else if not AValue and (FontQuality <> fqSystem) then 1141 FontQuality := fqSystem; 1142 end; 1143 1144 { These declaration make sure that these methods are virtual } 1145 procedure TBGRACustomBitmap.LoadFromFile(const filename: string); 1146 begin 1147 inherited LoadFromFile(filename); 1148 end; 1149 1150 procedure TBGRACustomBitmap.SaveToFile(const filename: string); 1151 begin 1152 inherited SaveToFile(filename); 1153 end; 1154 1155 procedure TBGRACustomBitmap.SaveToFile(const filename: string; 1156 Handler: TFPCustomImageWriter); 1157 begin 1158 inherited SaveToFile(filename, Handler); 1159 end; 1160 1161 { LoadFromStream uses TFPCustomImage routine, which uses 1162 Colors property to access pixels. That's why the 1163 FP drawing mode is temporarily changed to load 1164 bitmaps properly } 1165 procedure TBGRACustomBitmap.LoadFromStream(Str: TStream); 1166 var 1167 OldDrawMode: TDrawMode; 1168 begin 1169 OldDrawMode := CanvasDrawModeFP; 1170 CanvasDrawModeFP := dmSet; 1171 try 1172 if not LoadAsBmp32(Str) then 1173 inherited LoadFromStream(Str); 1174 finally 1175 CanvasDrawModeFP := OldDrawMode; 1176 end; 1177 end; 1178 1179 { See above } 1180 procedure TBGRACustomBitmap.LoadFromStream(Str: TStream; 1181 Handler: TFPCustomImageReader); 1182 var 1183 OldDrawMode: TDrawMode; 1184 begin 1185 OldDrawMode := CanvasDrawModeFP; 1186 CanvasDrawModeFP := dmSet; 1187 try 1188 inherited LoadFromStream(Str, Handler); 1189 finally 1190 CanvasDrawModeFP := OldDrawMode; 1191 end; 1192 end; 1193 1194 { Look for a pixel considering the bitmap is repeated in both directions } 1195 function TBGRACustomBitmap.GetPixelCycle(x, y: integer): TBGRAPixel; 1196 begin 1197 if (Width = 0) or (Height = 0) then 1198 Result := BGRAPixelTransparent 1199 else 1200 Result := (Scanline[PositiveMod(y,Height)] + PositiveMod(x,Width))^; 1201 end; 1202 1203 { Pixel polylines are constructed by concatenation } 1204 procedure TBGRACustomBitmap.DrawPolyLineAntialias(const points: array of TPoint; 1205 c: TBGRAPixel; DrawLastPixel: boolean); 1206 var i: integer; 1207 begin 1208 if length(points) = 1 then 1209 begin 1210 if DrawLastPixel then DrawPixel(points[0].x,points[0].y,c); 1211 end 1212 else 1213 for i := 0 to high(points)-1 do 1214 DrawLineAntialias(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,c,DrawLastPixel and (i=high(points)-1)); 1215 end; 1216 1217 procedure TBGRACustomBitmap.DrawPolyLineAntialias(const points: array of TPoint; c1, 1218 c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); 1219 var i: integer; 1220 begin 1221 if length(points) = 1 then 1222 begin 1223 if DrawLastPixel then DrawPixel(points[0].x,points[0].y,c1); 1224 end 1225 else 1226 for i := 0 to high(points)-1 do 1227 DrawLineAntialias(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,c1,c2,dashLen,DrawLastPixel and (i=high(points)-1)); 1228 end; 1229 1230 { Following functions are defined for convenience } 1231 procedure TBGRACustomBitmap.Rectangle(x, y, x2, y2: integer; c: TColor); 1232 begin 1233 Rectangle(x, y, x2, y2, ColorToBGRA(c), dmSet); 1234 end; 1235 1236 procedure TBGRACustomBitmap.Rectangle(r: TRect; c: TBGRAPixel; mode: TDrawMode 1237 ); 1238 begin 1239 Rectangle(r.left, r.top, r.right, r.bottom, c, mode); 1240 end; 1241 1242 procedure TBGRACustomBitmap.Rectangle(r: TRect; BorderColor, 1243 FillColor: TBGRAPixel; mode: TDrawMode); 1244 begin 1245 Rectangle(r.left, r.top, r.right, r.bottom, BorderColor, FillColor, mode); 1246 end; 1247 1248 procedure TBGRACustomBitmap.Rectangle(r: TRect; c: TColor); 1249 begin 1250 Rectangle(r.left, r.top, r.right, r.bottom, c); 1251 end; 1252 1253 procedure TBGRACustomBitmap.RectangleAntialias(x, y, x2, y2: single; 1254 c: TBGRAPixel; w: single); 1255 begin 1256 RectangleAntialias(x, y, x2, y2, c, w, BGRAPixelTransparent); 1257 end; 1258 1259 procedure TBGRACustomBitmap.FillRect(r: TRect; c: TColor); 1260 begin 1261 FillRect(r.Left, r.top, r.right, r.bottom, c); 1262 end; 1263 1264 procedure TBGRACustomBitmap.FillRect(r: TRect; c: TBGRAPixel; mode: TDrawMode); 1265 begin 1266 FillRect(r.Left, r.top, r.right, r.bottom, c, mode); 1267 end; 1268 1269 procedure TBGRACustomBitmap.FillRect(x, y, x2, y2: integer; c: TColor); 1270 begin 1271 FillRect(x, y, x2, y2, ColorToBGRA(c), dmSet); 1272 end; 1273 1274 procedure TBGRACustomBitmap.TextOut(x, y: integer; s: string; c: TBGRAPixel); 1275 begin 1276 TextOut(x, y, s, c, taLeftJustify); 1277 end; 1278 1279 procedure TBGRACustomBitmap.TextOut(x, y: integer; s: string; c: TColor); 1280 begin 1281 TextOut(x, y, s, ColorToBGRA(c)); 1282 end; 1283 1284 procedure TBGRACustomBitmap.TextOut(x, y: integer; s: string; 1285 texture: IBGRAScanner); 1286 begin 1287 TextOut(x, y, s, texture, taLeftJustify); 1288 end; 1289 1290 procedure TBGRACustomBitmap.TextRect(ARect: TRect; s: string; 1291 halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); 1292 var 1293 style: TTextStyle; 1294 begin 1295 {$hints off} 1296 FillChar(style,sizeof(style),0); 1297 {$hints on} 1298 style.Alignment := halign; 1299 style.Layout := valign; 1300 style.Wordbreak := true; 1301 style.ShowPrefix := false; 1302 style.Clipping := false; 1303 TextRect(ARect,ARect.Left,ARect.Top,s,style,c); 1304 end; 1305 1306 procedure TBGRACustomBitmap.TextRect(ARect: TRect; s: string; 1307 halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); 1308 var 1309 style: TTextStyle; 1310 begin 1311 {$hints off} 1312 FillChar(style,sizeof(style),0); 1313 {$hints on} 1314 style.Alignment := halign; 1315 style.Layout := valign; 1316 style.Wordbreak := true; 1317 style.ShowPrefix := false; 1318 style.Clipping := false; 1319 TextRect(ARect,ARect.Left,ARect.Top,s,style,texture); 1320 end; 1321 1322 procedure TBGRACustomBitmap.FillTransparent; 1323 begin 1324 Fill(BGRAPixelTransparent); 1325 end; 1326 1327 procedure TBGRACustomBitmap.Fill(c: TColor); 1328 begin 1329 Fill(ColorToBGRA(c)); 1330 end; 1331 1332 procedure TBGRACustomBitmap.Fill(c: TBGRAPixel); 1333 begin 1334 Fill(c, 0, NbPixels); 1335 end; 1336 1337 procedure TBGRACustomBitmap.AlphaFill(alpha: byte); 1338 begin 1339 AlphaFill(alpha, 0, NbPixels); 1340 end; 1341 1342 procedure TBGRACustomBitmap.FloodFill(X, Y: integer; Color: TBGRAPixel; 1343 mode: TFloodfillMode; Tolerance: byte); 1344 begin 1345 ParallelFloodFill(X,Y,Self,Color,mode,Tolerance); 1346 end; 1347 1348 procedure TBGRACustomBitmap.DrawPart(ARect: TRect; Canvas: TCanvas; x, 1349 y: integer; Opaque: boolean); 1350 var 1351 partial: TBGRACustomBitmap; 1352 begin 1353 partial := GetPart(ARect); 1354 if partial <> nil then 1355 begin 1356 partial.Draw(Canvas, x, y, Opaque); 1357 partial.Free; 1358 end; 1359 end; 1360 1361 procedure TBGRACustomBitmap.PutImageSubpixel(x, y: single; Source: TBGRACustomBitmap); 1362 begin 1363 PutImageAngle(x,y,source,0); 1364 end; 1365 1366 { Interface gateway } 1367 function TBGRACustomBitmap.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1368 begin 1369 if GetInterface(iid, obj) then 1370 Result := S_OK 1371 else 1372 Result := longint(E_NOINTERFACE); 1373 end; 1374 1375 { There is no automatic reference counting, but it is compulsory to define these functions } 1376 function TBGRACustomBitmap._AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1377 begin 1378 result := 0; 1379 end; 1380 1381 function TBGRACustomBitmap._Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1382 begin 1383 result := 0; 1384 end; 1385 1386 {$hints off} 1387 procedure TBGRACustomBitmap.ScanPutPixels(pdest: PBGRAPixel; count: integer; 1388 mode: TDrawMode); 1389 begin 1390 //do nothing 1391 end; 1392 {$hints on} 1393 1394 function TBGRACustomBitmap.IsScanPutPixelsDefined: boolean; 1395 begin 1396 result := False; 1397 end; 1398 1399 {********************** End of TBGRACustomBitmap **************************} 1400 1401 { TBGRACustomScanner } 1402 { The abstract class record the position so that a derived class 1403 need only to redefine ScanAt } 1404 1405 procedure TBGRACustomScanner.ScanMoveTo(X, Y: Integer); 1406 begin 1407 FCurX := X; 1408 FCurY := Y; 1409 end; 1410 1411 { Call ScanAt to determine pixel value } 1412 function TBGRACustomScanner.ScanNextPixel: TBGRAPixel; 1413 begin 1414 result := ScanAt(FCurX,FCurY); 1415 Inc(FCurX); 1416 end; 1417 1418 {$hints off} 1419 procedure TBGRACustomScanner.ScanPutPixels(pdest: PBGRAPixel; count: integer; 1420 mode: TDrawMode); 1421 begin 1422 //do nothing 1423 end; 1424 {$hints on} 1425 1426 function TBGRACustomScanner.IsScanPutPixelsDefined: boolean; 1427 begin 1428 result := false; 1429 end; 1430 1431 { Interface gateway } 1432 function TBGRACustomScanner.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1433 begin 1434 if GetInterface(iid, obj) then 1435 Result := S_OK 1436 else 1437 Result := longint(E_NOINTERFACE); 1438 end; 1439 1440 { There is no automatic reference counting, but it is compulsory to define these functions } 1441 function TBGRACustomScanner._AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1442 begin 1443 result := 0; 1444 end; 1445 1446 function TBGRACustomScanner._Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 1447 begin 1448 result := 0; 1449 end; 1450 1451 {********************** End of TBGRACustomScanner **************************} 1452 1453 { The gamma correction is approximated here by a power function } 134 1454 const 135 GammaExpFactor = 1.7; 136 { redWeight = 0.299; 137 greenWeight = 0.587; 138 blueWeight = 0.114;} 139 redWeightShl10 = 306; 140 greenWeightShl10 = 601; 141 blueWeightShl10 = 117; 1455 GammaExpFactor = 1.7; //exponent 1456 redWeightShl10 = 306; // = 0.299 1457 greenWeightShl10 = 601; // = 0.587 1458 blueWeightShl10 = 117; // = 0.114 142 1459 143 1460 var … … 146 1463 procedure InitGamma; 147 1464 var 148 i: integer; {t: textfile; prevval,val: byte; } 149 begin 1465 i: integer; 1466 {$IFDEF WINCE} 1467 j,prevpos,curpos,midpos: integer; 1468 {$ENDIF} 1469 begin 1470 //the linear factor is used to normalize expanded values in the range 0..65535 150 1471 GammaLinearFactor := 65535 / power(255, GammaExpFactor); 1472 1473 {$IFDEF WINCE} 1474 curpos := 0; 1475 GammaExpansionTab[0] := 0; 1476 GammaCompressionTab[0] := 0; 1477 for i := 0 to 255 do 1478 begin 1479 prevpos := curpos; 1480 curpos := round(power(i, GammaExpFactor) * GammaLinearFactor); 1481 if i = 1 then curpos := 1; //to avoid information loss 1482 GammaExpansionTab[i] := curpos; 1483 midpos := (prevpos+1+curpos) div 2; 1484 for j := prevpos+1 to midpos-1 do 1485 GammaCompressionTab[j] := i-1; 1486 for j := midpos to curpos do 1487 GammaCompressionTab[j] := i; 1488 end; 1489 {$ELSE} 151 1490 for i := 0 to 255 do 152 1491 GammaExpansionTab[i] := round(power(i, GammaExpFactor) * GammaLinearFactor); … … 155 1494 GammaCompressionTab[i] := round(power(i / GammaLinearFactor, 1 / GammaExpFactor)); 156 1495 157 GammaExpansionTab[1] := 1; //to avoid information los t1496 GammaExpansionTab[1] := 1; //to avoid information loss 158 1497 GammaCompressionTab[1] := 1; 159 { 160 assignfile(t,'gammaout.txt'); 161 rewrite(t); 162 prevval := 255; 163 for i := 0 to 255 do 164 begin 165 val := GammaCompressionTab[i*256+128]; 166 if val <> prevval then writeln(t,val); 167 prevval := val; 168 end; 169 closefile(t);} 170 end; 171 172 {$hints off} 173 1498 {$ENDIF} 1499 end; 1500 1501 {************************** Color functions **************************} 1502 1503 { The intensity is defined here as the maximum value of any color component } 174 1504 function GetIntensity(c: TExpandedPixel): word; inline; 175 1505 begin … … 186 1516 begin 187 1517 curIntensity := GetIntensity(c); 188 if curIntensity = 0 then 1518 if curIntensity = 0 then //suppose it's gray if there is no color information 189 1519 Result := c 190 1520 else 191 1521 begin 1522 //linear interpolation to reached wanted intensity 192 1523 Result.red := (c.red * intensity + (curIntensity shr 1)) div curIntensity; 193 1524 Result.green := (c.green * intensity + (curIntensity shr 1)) div curIntensity; … … 197 1528 end; 198 1529 1530 { The lightness here is defined as the subjective sensation of luminosity, where 1531 blue is the darkest component and green the lightest } 199 1532 function GetLightness(c: TExpandedPixel): word; inline; 200 1533 begin … … 286 1619 end; 287 1620 1621 function ApplyLightnessFast(color: TBGRAPixel; lightness: word): TBGRAPixel; inline; 1622 var lightness256: byte; 1623 begin 1624 if lightness <= 32768 then 1625 begin 1626 if lightness = 32768 then 1627 result := color else 1628 begin 1629 lightness256 := GammaCompressionTab[lightness shl 1]; 1630 result := BGRA(color.red * lightness256 shr 8, color.green*lightness256 shr 8, 1631 color.blue * lightness256 shr 8, color.alpha); 1632 end; 1633 end else 1634 begin 1635 if lightness = 65535 then 1636 result := BGRAWhite else 1637 begin 1638 lightness256 := GammaCompressionTab[(lightness-32767) shl 1]; 1639 result := BGRA(color.red + (255-color.red)*lightness256 shr 8, 1640 color.green + (255-color.green)*lightness256 shr 8, 1641 color.blue + (255-color.blue)*lightness256 shr 8, 1642 color.alpha); 1643 end; 1644 end; 1645 end; 1646 1647 { Conversion from RGB value to HSL colorspace. See : http://en.wikipedia.org/wiki/HSL_color_space } 288 1648 function BGRAToHSLA(c: TBGRAPixel): THSLAPixel; 289 1649 const … … 294 1654 var 295 1655 ec: TExpandedPixel; 296 min, max, minMax: word;1656 min, max, minMax: integer; 297 1657 twiceLightness: integer; 1658 r,g,b: integer; 298 1659 begin 299 1660 ec := GammaExpansion(c); 300 min := ec.red; 301 max := ec.red; 302 if ec.green > max then 303 max := ec.green 304 else 305 if ec.green < min then 306 min := ec.green; 307 if ec.blue > max then 308 max := ec.blue 309 else 310 if ec.blue < min then 311 min := ec.blue; 1661 r := ec.red; 1662 g := ec.green; 1663 b := ec.blue; 1664 min := r; 1665 max := r; 1666 if g > max then 1667 max := g 1668 else 1669 if g < min then 1670 min := g; 1671 if b > max then 1672 max := b 1673 else 1674 if b < min then 1675 min := b; 312 1676 minMax := max - min; 313 1677 … … 315 1679 Result.hue := 0 316 1680 else 317 if max = ec.redthen318 Result.hue := ((( ec.green - ec.blue) * deg60 + (minMax shr 1)) div1681 if max = r then 1682 Result.hue := (((g - b) * deg60) div 319 1683 minMax + deg360) mod deg360 320 1684 else 321 if max = ec.greenthen322 Result.hue := (( ec.blue - ec.red) * deg60 + (minMax shr 1)) div minMax + deg120323 else 324 {max = ec.blue} Result.hue :=325 (( ec.red - ec.green) * deg60 + (minMax shr 1)) div minMax + deg240;1685 if max = g then 1686 Result.hue := ((b - r) * deg60) div minMax + deg120 1687 else 1688 {max = b} Result.hue := 1689 ((r - g) * deg60) div minMax + deg240; 326 1690 twiceLightness := max + min; 327 1691 if min = max then 328 1692 Result.saturation := 0 329 1693 else 1694 {$hints off} 330 1695 if twiceLightness < 65536 then 331 Result.saturation := (minMax shl 16) div (twiceLightness + 1) 332 else 333 Result.saturation := (minMax shl 16) div (131072 - twiceLightness); 1696 Result.saturation := (int64(minMax) shl 16) div (twiceLightness + 1) 1697 else 1698 Result.saturation := (int64(minMax) shl 16) div (131072 - twiceLightness); 1699 {$hints on} 334 1700 Result.lightness := twiceLightness shr 1; 335 1701 Result.alpha := ec.alpha; 336 Result.hue := Result.hue * 65536 div deg360; 337 end; 338 339 function HSLAToBGRA(c: THSLAPixel): TBGRAPixel; 1702 Result.hue := (Result.hue shl 16) div deg360; 1703 end; 1704 1705 function HtoG(hue: word): word; 1706 const 1707 segmentDest: array[0..5] of word = 1708 (13653, 10923, 8192, 13653, 10923, 8192); 1709 segmentSrc: array[0..5] of word = 1710 (10923, 10922, 10923, 10923, 10922, 10923); 1711 begin 1712 if hue < segmentSrc[0] then 1713 result := hue * segmentDest[0] div segmentSrc[0] 1714 else 1715 begin 1716 result := segmentDest[0]; 1717 hue -= segmentSrc[0]; 1718 if hue < segmentSrc[1] then 1719 result += hue * segmentDest[1] div segmentSrc[1] 1720 else 1721 begin 1722 result += segmentDest[1]; 1723 hue -= segmentSrc[1]; 1724 if hue < segmentSrc[2] then 1725 result += hue * segmentDest[2] div segmentSrc[2] 1726 else 1727 begin 1728 result += segmentDest[2]; 1729 hue -= segmentSrc[2]; 1730 if hue < segmentSrc[3] then 1731 result += hue * segmentDest[3] div segmentSrc[3] 1732 else 1733 begin 1734 result += segmentDest[3]; 1735 hue -= segmentSrc[3]; 1736 if hue < segmentSrc[4] then 1737 result += hue * segmentDest[4] div segmentSrc[4] 1738 else 1739 begin 1740 result += segmentDest[4]; 1741 hue -= segmentSrc[4]; 1742 result += hue * segmentDest[5] div segmentSrc[5]; 1743 end; 1744 end; 1745 end; 1746 end; 1747 end; 1748 end; 1749 1750 function GtoH(ghue: word): word; 1751 const 1752 segment: array[0..5] of word = 1753 (13653, 10923, 8192, 13653, 10923, 8192); 1754 begin 1755 if ghue < segment[0] then 1756 result := ghue * 10923 div segment[0] 1757 else 1758 begin 1759 ghue -= segment[0]; 1760 if ghue < segment[1] then 1761 result := ghue * (21845-10923) div segment[1] + 10923 1762 else 1763 begin 1764 ghue -= segment[1]; 1765 if ghue < segment[2] then 1766 result := ghue * (32768-21845) div segment[2] + 21845 1767 else 1768 begin 1769 ghue -= segment[2]; 1770 if ghue < segment[3] then 1771 result := ghue * (43691-32768) div segment[3] + 32768 1772 else 1773 begin 1774 ghue -= segment[3]; 1775 if ghue < segment[4] then 1776 result := ghue * (54613-43691) div segment[4] + 43691 1777 else 1778 begin 1779 ghue -= segment[4]; 1780 result := ghue * (65536-54613) div segment[5] + 54613; 1781 end; 1782 end; 1783 end; 1784 end; 1785 end; 1786 end; 1787 1788 function HSLAToExpanded(c: THSLAPixel): TExpandedPixel; 340 1789 const 341 1790 deg30 = 4096; … … 364 1813 var 365 1814 q, p: integer; 366 ec: TExpandedPixel;367 1815 begin 368 1816 c.hue := c.hue * deg360 shr 16; 369 1817 if c.saturation = 0 then //gray 370 1818 begin 371 ec.red := c.lightness; 372 ec.green := c.lightness; 373 ec.blue := c.lightness; 374 ec.alpha := c.alpha; 375 Result := GammaCompression(ec); 1819 result.red := c.lightness; 1820 result.green := c.lightness; 1821 result.blue := c.lightness; 1822 result.alpha := c.alpha; 376 1823 exit; 377 1824 end; 1825 {$hints off} 378 1826 if c.lightness < 32768 then 379 1827 q := (c.lightness shr 1) * ((65535 + c.saturation) shr 1) shr 14 … … 381 1829 q := c.lightness + c.saturation - ((c.lightness shr 1) * 382 1830 (c.saturation shr 1) shr 14); 1831 {$hints on} 383 1832 if q > 65535 then 384 1833 q := 65535; … … 386 1835 if p > 65535 then 387 1836 p := 65535; 388 ec.red := ComputeColor(p, q, c.hue + deg120); 389 ec.green := ComputeColor(p, q, c.hue); 390 ec.blue := ComputeColor(p, q, c.hue + deg240); 391 ec.alpha := c.alpha; 392 Result := GammaCompression(ec); 393 end; 394 1837 result.red := ComputeColor(p, q, c.hue + deg120); 1838 result.green := ComputeColor(p, q, c.hue); 1839 result.blue := ComputeColor(p, q, c.hue + deg240); 1840 result.alpha := c.alpha; 1841 end; 1842 1843 { Conversion from HSL colorspace to RGB. See : http://en.wikipedia.org/wiki/HSL_color_space } 1844 function HSLAToBGRA(c: THSLAPixel): TBGRAPixel; 1845 var ec: TExpandedPixel; 1846 begin 1847 ec := HSLAToExpanded(c); 1848 Result := GammaCompression(ec); 1849 end; 1850 1851 function HueDiff(h1, h2: word): word; 1852 begin 1853 result := abs(integer(h1)-integer(h2)); 1854 if result > 32768 then result := 65536-result; 1855 end; 1856 1857 function GetHue(ec: TExpandedPixel): word; 1858 const 1859 deg60 = 8192; 1860 deg120 = deg60 * 2; 1861 deg240 = deg60 * 4; 1862 deg360 = deg60 * 6; 1863 var 1864 min, max, minMax: integer; 1865 r,g,b: integer; 1866 begin 1867 r := ec.red; 1868 g := ec.green; 1869 b := ec.blue; 1870 min := r; 1871 max := r; 1872 if g > max then 1873 max := g 1874 else 1875 if g < min then 1876 min := g; 1877 if b > max then 1878 max := b 1879 else 1880 if b < min then 1881 min := b; 1882 minMax := max - min; 1883 1884 if minMax = 0 then 1885 Result := 0 1886 else 1887 if max = r then 1888 Result := (((g - b) * deg60) div 1889 minMax + deg360) mod deg360 1890 else 1891 if max = g then 1892 Result := ((b - r) * deg60) div minMax + deg120 1893 else 1894 {max = b} Result := 1895 ((r - g) * deg60) div minMax + deg240; 1896 1897 Result := (Result shl 16) div deg360; //normalize 1898 end; 1899 1900 function ColorImportance(ec: TExpandedPixel): word; 1901 var min,max: word; 1902 begin 1903 min := ec.red; 1904 max := ec.red; 1905 if ec.green > max then 1906 max := ec.green 1907 else 1908 if ec.green < min then 1909 min := ec.green; 1910 if ec.blue > max then 1911 max := ec.blue 1912 else 1913 if ec.blue < min then 1914 min := ec.blue; 1915 result := max - min; 1916 end; 1917 1918 function GSBAToBGRA(c: THSLAPixel): TBGRAPixel; 1919 var ec: TExpandedPixel; 1920 lightness: word; 1921 begin 1922 c.hue := GtoH(c.hue); 1923 lightness := c.lightness; 1924 c.lightness := 32768; 1925 ec := HSLAToExpanded(c); 1926 result := GammaCompression(SetLightness(ec, lightness)); 1927 end; 1928 1929 function GSBAToHSLA(c: THSLAPixel): THSLAPixel; 1930 begin 1931 result := BGRAToHSLA(GSBAToBGRA(c)); 1932 end; 1933 1934 { Apply gamma correction using conversion tables } 395 1935 function GammaExpansion(c: TBGRAPixel): TExpandedPixel; 396 1936 begin … … 398 1938 Result.green := GammaExpansionTab[c.green]; 399 1939 Result.blue := GammaExpansionTab[c.blue]; 400 Result.alpha := c.alpha shl 8 + 128; 401 end; 402 403 {$hints on} 1940 Result.alpha := c.alpha shl 8 + c.alpha; 1941 end; 404 1942 405 1943 function GammaCompression(ec: TExpandedPixel): TBGRAPixel; … … 411 1949 end; 412 1950 1951 function GammaCompression(red, green, blue, alpha: word): TBGRAPixel; 1952 begin 1953 Result.red := GammaCompressionTab[red]; 1954 Result.green := GammaCompressionTab[green]; 1955 Result.blue := GammaCompressionTab[blue]; 1956 Result.alpha := alpha shr 8; 1957 end; 1958 1959 // Conversion to grayscale by taking into account 1960 // different color weights 413 1961 function BGRAToGrayscale(c: TBGRAPixel): TBGRAPixel; 414 1962 var … … 430 1978 end; 431 1979 1980 function GrayscaleToBGRA(lightness: word): TBGRAPixel; 1981 begin 1982 result.red := GammaCompressionTab[lightness]; 1983 result.green := result.red; 1984 result.blue := result.red; 1985 result.alpha := $ff; 1986 end; 1987 1988 { Merge linearly two colors of same importance } 432 1989 function MergeBGRA(c1, c2: TBGRAPixel): TBGRAPixel; 1990 var c12: cardinal; 433 1991 begin 434 1992 if (c1.alpha = 0) then … … 439 1997 else 440 1998 begin 441 Result.red := round((c1.red * c1.alpha + c2.red * c2.alpha) / 442 (c1.alpha + c2.alpha)); 443 Result.green := round((c1.green * c1.alpha + c2.green * c2.alpha) / 444 (c1.alpha + c2.alpha)); 445 Result.blue := round((c1.blue * c1.alpha + c2.blue * c2.alpha) / 446 (c1.alpha + c2.alpha)); 447 Result.alpha := (c1.alpha + c2.alpha + 1) div 2; 1999 c12 := c1.alpha + c2.alpha; 2000 Result.red := (c1.red * c1.alpha + c2.red * c2.alpha + c12 shr 1) div c12; 2001 Result.green := (c1.green * c1.alpha + c2.green * c2.alpha + c12 shr 1) div c12; 2002 Result.blue := (c1.blue * c1.alpha + c2.blue * c2.alpha + c12 shr 1) div c12; 2003 Result.alpha := (c12 + 1) shr 1; 2004 end; 2005 end; 2006 2007 function MergeBGRA(c1: TBGRAPixel; weight1: integer; c2: TBGRAPixel; 2008 weight2: integer): TBGRAPixel; 2009 var 2010 f1,f2,f12: integer; 2011 begin 2012 f1 := c1.alpha*weight1; 2013 f2 := c2.alpha*weight2; 2014 if (f1 = 0) then 2015 begin 2016 if (f2 = 0) then 2017 result := BGRAPixelTransparent 2018 else 2019 Result := c2 2020 end 2021 else 2022 if (f2 = 0) then 2023 Result := c1 2024 else 2025 if (weight1+weight2 = 0) then 2026 Result := BGRAPixelTransparent 2027 else 2028 begin 2029 f12 := f1+f2; 2030 if f12 = 0 then 2031 result := BGRAPixelTransparent 2032 else 2033 begin 2034 Result.red := (c1.red * f1 + c2.red * f2 + f12 shr 1) div f12; 2035 Result.green := (c1.green * f1 + c2.green * f2 + f12 shr 1) div f12; 2036 Result.blue := (c1.blue * f1 + c2.blue * f2 + f12 shr 1) div f12; 2037 Result.alpha := (f12 + ((weight1+weight2) shr 1)) div (weight1+weight2); 2038 end; 2039 end; 2040 end; 2041 2042 { Merge two colors of same importance } 2043 function MergeBGRA(ec1, ec2: TExpandedPixel): TExpandedPixel; 2044 var c12: cardinal; 2045 begin 2046 if (ec1.alpha = 0) then 2047 Result := ec2 2048 else 2049 if (ec2.alpha = 0) then 2050 Result := ec1 2051 else 2052 begin 2053 c12 := ec1.alpha + ec2.alpha; 2054 Result.red := (int64(ec1.red) * ec1.alpha + int64(ec2.red) * ec2.alpha + c12 shr 1) div c12; 2055 Result.green := (int64(ec1.green) * ec1.alpha + int64(ec2.green) * ec2.alpha + c12 shr 1) div c12; 2056 Result.blue := (int64(ec1.blue) * ec1.alpha + int64(ec2.blue) * ec2.alpha + c12 shr 1) div c12; 2057 Result.alpha := (c12 + 1) shr 1; 448 2058 end; 449 2059 end; … … 465 2075 end; 466 2076 2077 { Convert a TColor value to a TBGRAPixel value. Note that 2078 you need to call ColorToRGB first if you use a system 2079 color identifier like clWindow. } 467 2080 {$PUSH}{$R-} 468 2081 function ColorToBGRA(color: TColor): TBGRAPixel; overload; … … 483 2096 {$POP} 484 2097 485 {$hints off} 2098 { Conversion from TFPColor to TBGRAPixel assuming TFPColor 2099 is already gamma compressed } 2100 function FPColorToBGRA(AValue: TFPColor): TBGRAPixel; 2101 begin 2102 with AValue do 2103 Result := BGRA(red shr 8, green shr 8, blue shr 8, alpha shr 8); 2104 end; 2105 2106 function BGRAToFPColor(AValue: TBGRAPixel): TFPColor; inline; 2107 begin 2108 result.red := AValue.red shl 8 + AValue.red; 2109 result.green := AValue.green shl 8 + AValue.green; 2110 result.blue := AValue.blue shl 8 + AValue.blue; 2111 result.alpha := AValue.alpha shl 8 + AValue.alpha; 2112 end; 2113 486 2114 function BGRAToColor(c: TBGRAPixel): TColor; 487 2115 begin 488 2116 Result := c.red + (c.green shl 8) + (c.blue shl 16); 489 2117 end; 490 491 {$hints on}492 2118 493 2119 operator = (const c1, c2: TBGRAPixel): boolean; … … 500 2126 end; 501 2127 502 function BGRADiff(c1, c2: TBGRAPixel): byte; 2128 function LessStartSlope65535(value: word): word; 2129 var factor: word; 2130 begin 2131 factor := 4096 - (not value)*3 shr 7; 2132 result := value*factor shr 12; 2133 end; 2134 2135 function ExpandedDiff(ec1, ec2: TExpandedPixel): word; 503 2136 var 504 2137 CompRedAlpha1, CompGreenAlpha1, CompBlueAlpha1, CompRedAlpha2, 505 2138 CompGreenAlpha2, CompBlueAlpha2: integer; 506 DiffAlpha: byte; 507 begin 508 {$hints off} 509 CompRedAlpha1 := c1.red * c1.alpha; 510 CompGreenAlpha1 := c1.green * c1.alpha; 511 CompBlueAlpha1 := c1.blue * c1.alpha; 512 CompRedAlpha2 := c2.red * c2.alpha; 513 CompGreenAlpha2 := c2.green * c2.alpha; 514 CompBlueAlpha2 := c2.blue * c2.alpha; 515 {$hints on} 516 Result := (Abs(CompRedAlpha2 - CompRedAlpha1) + 517 Abs(CompBlueAlpha2 - CompBlueAlpha1) + Abs(CompGreenAlpha2 - CompGreenAlpha1)) div 518 (3 * 255); 519 DiffAlpha := Abs(c2.Alpha - c1.Alpha) * 3 shr 2; 2139 DiffAlpha: word; 2140 ColorDiff: word; 2141 TempHueDiff: word; 2142 begin 2143 CompRedAlpha1 := ec1.red * ec1.alpha shr 16; //gives 0..65535 2144 CompGreenAlpha1 := ec1.green * ec1.alpha shr 16; 2145 CompBlueAlpha1 := ec1.blue * ec1.alpha shr 16; 2146 CompRedAlpha2 := ec2.red * ec2.alpha shr 16; 2147 CompGreenAlpha2 := ec2.green * ec2.alpha shr 16; 2148 CompBlueAlpha2 := ec2.blue * ec2.alpha shr 16; 2149 Result := (Abs(CompRedAlpha2 - CompRedAlpha1)*redWeightShl10 + 2150 Abs(CompBlueAlpha2 - CompBlueAlpha1)*blueWeightShl10 + 2151 Abs(CompGreenAlpha2 - CompGreenAlpha1)*greenWeightShl10) shr 10; 2152 ColorDiff := min(ColorImportance(ec1),ColorImportance(ec2)); 2153 if ColorDiff > 0 then 2154 begin 2155 TempHueDiff := HueDiff(HtoG(GetHue(ec1)),HtoG(GetHue(ec2))); 2156 if TempHueDiff < 32768 then 2157 TempHueDiff := LessStartSlope65535(TempHueDiff shl 1) shr 4 2158 else 2159 TempHueDiff := TempHueDiff shr 3; 2160 Result := ((Result shr 4)* (not ColorDiff) + TempHueDiff*ColorDiff) shr 12; 2161 end; 2162 DiffAlpha := Abs(integer(ec2.Alpha) - integer(ec1.Alpha)); 520 2163 if DiffAlpha > Result then 521 2164 Result := DiffAlpha; 522 2165 end; 523 2166 2167 function BGRAWordDiff(c1, c2: TBGRAPixel): word; 2168 begin 2169 result := ExpandedDiff(GammaExpansion(c1),GammaExpansion(c2)); 2170 end; 2171 2172 function BGRADiff(c1,c2: TBGRAPixel): byte; 2173 begin 2174 result := ExpandedDiff(GammaExpansion(c1),GammaExpansion(c2)) shr 8; 2175 end; 2176 2177 operator-(const c1, c2: TColorF): TColorF; 2178 begin 2179 result[1] := c1[1]-c2[1]; 2180 result[2] := c1[2]-c2[2]; 2181 result[3] := c1[3]-c2[3]; 2182 result[4] := c1[4]-c2[4]; 2183 end; 2184 2185 operator+(const c1, c2: TColorF): TColorF; 2186 begin 2187 result[1] := c1[1]+c2[1]; 2188 result[2] := c1[2]+c2[2]; 2189 result[3] := c1[3]+c2[3]; 2190 result[4] := c1[4]+c2[4]; 2191 end; 2192 2193 operator*(const c1, c2: TColorF): TColorF; 2194 begin 2195 result[1] := c1[1]*c2[1]; 2196 result[2] := c1[2]*c2[2]; 2197 result[3] := c1[3]*c2[3]; 2198 result[4] := c1[4]*c2[4]; 2199 end; 2200 2201 operator*(const c1: TColorF; factor: single): TColorF; 2202 begin 2203 result[1] := c1[1]*factor; 2204 result[2] := c1[2]*factor; 2205 result[3] := c1[3]*factor; 2206 result[4] := c1[4]*factor; 2207 end; 2208 2209 function ColorF(red, green, blue, alpha: single): TColorF; 2210 begin 2211 result[1] := red; 2212 result[2] := green; 2213 result[3] := blue; 2214 result[4] := alpha; 2215 end; 2216 2217 { Write a color in hexadecimal format RRGGBBAA } 2218 function BGRAToStr(c: TBGRAPixel): string; 2219 begin 2220 result := IntToHex(c.red,2)+IntToHex(c.green,2)+IntToHex(c.Blue,2)+IntToHex(c.Alpha,2); 2221 end; 2222 2223 type 2224 arrayOfString = array of string; 2225 2226 function SimpleParseFuncParam(str: string): arrayOfString; 2227 var idxOpen,start,cur: integer; 2228 begin 2229 result := nil; 2230 idxOpen := pos('(',str); 2231 if idxOpen = 0 then exit; 2232 start := idxOpen+1; 2233 cur := start; 2234 while cur <= length(str) do 2235 begin 2236 if str[cur] in[',',')'] then 2237 begin 2238 setlength(result,length(result)+1); 2239 result[high(result)] := copy(str,start,cur-start); 2240 start := cur+1; 2241 end; 2242 inc(cur); 2243 end; 2244 if start <= length(str) then 2245 begin 2246 setlength(result,length(result)+1); 2247 result[high(result)] := copy(str,start,length(str)-start+1); 2248 end; 2249 end; 2250 2251 function ParseColorValue(str: string): byte; 2252 var pourcent,unclipped,errPos: integer; 2253 begin 2254 if str = '' then result := 0 else 2255 begin 2256 if str[length(str)]='%' then 2257 begin 2258 val(copy(str,1,length(str)-1),pourcent,errPos); 2259 if pourcent < 0 then result := 0 else 2260 if pourcent > 100 then result := 255 else 2261 result := pourcent*255 div 100; 2262 end else 2263 begin 2264 val(str,unclipped,errPos); 2265 if unclipped < 0 then result := 0 else 2266 if unclipped > 255 then result := 255 else 2267 result := unclipped; 2268 end; 2269 end; 2270 end; 2271 2272 { Read a color in hexadecimal format RRGGBB(AA) or RGB(A) } 2273 function StrToBGRA(str: string): TBGRAPixel; 2274 var errPos: integer; 2275 values: array of string; 2276 alphaF: single; 2277 idx: integer; 2278 begin 2279 if str = '' then 2280 begin 2281 result := BGRAPixelTransparent; 2282 exit; 2283 end; 2284 str := lowerCase(str); 2285 2286 //VGA color names 2287 if str='black' then result := BGRA(0,0,0) else 2288 if str='silver' then result := BGRA(192,192,192) else 2289 if str='gray' then result := BGRA(128,128,128) else 2290 if str='white' then result := BGRA(255,255,255) else 2291 if str='maroon' then result := BGRA(128,0,0) else 2292 if str='red' then result := BGRA(255,0,0) else 2293 if str='purple' then result := BGRA(128,0,128) else 2294 if str='fuchsia' then result := BGRA(255,0,255) else 2295 if str='green' then result := BGRA(0,128,0) else 2296 if str='lime' then result := BGRA(0,255,0) else 2297 if str='olive' then result := BGRA(128,128,0) else 2298 if str='yellow' then result := BGRA(255,255,0) else 2299 if str='navy' then result := BGRA(0,0,128) else 2300 if str='blue' then result := BGRA(0,0,255) else 2301 if str='teal' then result := BGRA(0,128,128) else 2302 if str='aqua' then result := BGRA(0,255,255) else 2303 if str='transparent' then result := BGRAPixelTransparent else 2304 begin 2305 //check CSS color 2306 idx := CSSColors.IndexOf(str); 2307 if idx <> -1 then 2308 begin 2309 result := CSSColors[idx]; 2310 exit; 2311 end; 2312 2313 //CSS RGB notation 2314 if (copy(str,1,4)='rgb(') or (copy(str,1,5)='rgba(') then 2315 begin 2316 values := SimpleParseFuncParam(str); 2317 if (length(values)=3) or (length(values)=4) then 2318 begin 2319 result.red := ParseColorValue(values[0]); 2320 result.green := ParseColorValue(values[1]); 2321 result.blue := ParseColorValue(values[2]); 2322 if length(values)=4 then 2323 begin 2324 val(values[3],alphaF,errPos); 2325 if alphaF < 0 then 2326 result.alpha := 0 else 2327 if alphaF > 1 then 2328 result.alpha := 255 2329 else 2330 result.alpha := round(alphaF*255); 2331 end else 2332 result.alpha := 255; 2333 end else 2334 result := BGRAPixelTransparent; 2335 exit; 2336 end; 2337 2338 //remove HTML notation header 2339 if str[1]='#' then delete(str,1,1); 2340 2341 //add alpha if missing 2342 if length(str)=6 then str += 'FF'; 2343 if length(str)=3 then str += 'F'; 2344 2345 //hex notation 2346 if length(str)=8 then 2347 begin 2348 val('$'+copy(str,1,2),result.red,errPos); 2349 val('$'+copy(str,3,2),result.green,errPos); 2350 val('$'+copy(str,5,2),result.blue,errPos); 2351 val('$'+copy(str,7,2),result.alpha,errPos); 2352 end else 2353 if length(str)=4 then 2354 begin 2355 val('$'+copy(str,1,1),result.red,errPos); 2356 val('$'+copy(str,2,1),result.green,errPos); 2357 val('$'+copy(str,3,1),result.blue,errPos); 2358 val('$'+copy(str,4,1),result.alpha,errPos); 2359 result.red *= $11; 2360 result.green *= $11; 2361 result.blue *= $11; 2362 result.alpha *= $11; 2363 end else 2364 result := BGRAPixelTransparent; 2365 end; 2366 2367 end; 2368 2369 2370 function MapHeight(Color: TBGRAPixel): Single; 2371 var intval: integer; 2372 begin 2373 intval := color.Green shl 16 + color.red shl 8 + color.blue; 2374 result := intval/16777215; 2375 end; 2376 2377 function MapHeightToBGRA(Height: Single; Alpha: Byte): TBGRAPixel; 2378 var intval: integer; 2379 begin 2380 if Height >= 1 then result := BGRA(255,255,255,alpha) else 2381 if Height <= 0 then result := BGRA(0,0,0,alpha) else 2382 begin 2383 intval := round(Height*16777215); 2384 result := BGRA(intval shr 8,intval shr 16,intval,alpha); 2385 end; 2386 end; 2387 2388 {********************** Point functions **************************} 2389 524 2390 function PointF(x, y: single): TPointF; 525 2391 begin 526 2392 Result.x := x; 527 2393 Result.y := y; 2394 end; 2395 2396 function PointsF(const pts: array of TPointF): ArrayOfTPointF; 2397 var 2398 i: Integer; 2399 begin 2400 setlength(result, length(pts)); 2401 for i := 0 to high(pts) do result[i] := pts[i]; 2402 end; 2403 2404 operator =(const pt1, pt2: TPointF): boolean; 2405 begin 2406 result := (pt1.x = pt2.x) and (pt1.y = pt2.y); 2407 end; 2408 2409 operator-(const pt1, pt2: TPointF): TPointF; 2410 begin 2411 result.x := pt1.x-pt2.x; 2412 result.y := pt1.y-pt2.y; 2413 end; 2414 2415 operator-(const pt2: TPointF): TPointF; 2416 begin 2417 result.x := -pt2.x; 2418 result.y := -pt2.y; 2419 end; 2420 2421 operator+(const pt1, pt2: TPointF): TPointF; 2422 begin 2423 result.x := pt1.x+pt2.x; 2424 result.y := pt1.y+pt2.y; 2425 end; 2426 2427 operator*(const pt1, pt2: TPointF): single; 2428 begin 2429 result := pt1.x*pt2.x + pt1.y*pt2.y; 2430 end; 2431 2432 operator*(const pt1: TPointF; factor: single): TPointF; 2433 begin 2434 result.x := pt1.x*factor; 2435 result.y := pt1.y*factor; 2436 end; 2437 2438 operator*(factor: single; const pt1: TPointF): TPointF; 2439 begin 2440 result.x := pt1.x*factor; 2441 result.y := pt1.y*factor; 528 2442 end; 529 2443 … … 548 2462 end; 549 2463 550 function StrToGradientType(str: string): TGradientType; 551 var gt: TGradientType; 552 begin 553 result := gtLinear; 554 str := LowerCase(str); 555 for gt := low(TGradientType) to high(TGradientType) do 556 if str = LowerCase(GradientTypeStr[gt]) then 2464 function VectLen(dx, dy: single): single; 2465 begin 2466 result := sqrt(dx*dx+dy*dy); 2467 end; 2468 2469 function VectLen(v: TPointF): single; 2470 begin 2471 result := sqrt(v.x*v.x+v.y*v.y); 2472 end; 2473 2474 function IntersectLine(line1, line2: TLineDef): TPointF; 2475 var parallel: boolean; 2476 begin 2477 result := IntersectLine(line1,line2,parallel); 2478 end; 2479 2480 function IntersectLine(line1, line2: TLineDef; out parallel: boolean): TPointF; 2481 var divFactor: double; 2482 begin 2483 parallel := false; 2484 //if lines are parallel 2485 if ((line1.dir.x = line2.dir.x) and (line1.dir.y = line2.dir.y)) or 2486 ((abs(line1.dir.y) < 1e-6) and (abs(line2.dir.y) < 1e-6)) then 2487 begin 2488 parallel := true; 2489 //return the center of the segment between line origins 2490 result.x := (line1.origin.x+line2.origin.x)/2; 2491 result.y := (line1.origin.y+line2.origin.y)/2; 2492 end else 2493 if abs(line1.dir.y) < 1e-6 then //line1 is horizontal 2494 begin 2495 result.y := line1.origin.y; 2496 result.x := line2.origin.x + (result.y - line2.origin.y) 2497 /line2.dir.y*line2.dir.x; 2498 end else 2499 if abs(line2.dir.y) < 1e-6 then //line2 is horizontal 2500 begin 2501 result.y := line2.origin.y; 2502 result.x := line1.origin.x + (result.y - line1.origin.y) 2503 /line1.dir.y*line1.dir.x; 2504 end else 2505 begin 2506 divFactor := line1.dir.x/line1.dir.y - line2.dir.x/line2.dir.y; 2507 if abs(divFactor) < 1e-6 then //almost parallel 2508 begin 2509 parallel := true; 2510 //return the center of the segment between line origins 2511 result.x := (line1.origin.x+line2.origin.x)/2; 2512 result.y := (line1.origin.y+line2.origin.y)/2; 2513 end else 2514 begin 2515 result.y := (line2.origin.x - line1.origin.x + 2516 line1.origin.y*line1.dir.x/line1.dir.y - 2517 line2.origin.y*line2.dir.x/line2.dir.y) 2518 / divFactor; 2519 result.x := line1.origin.x + (result.y - line1.origin.y) 2520 /line1.dir.y*line1.dir.x; 2521 end; 2522 end; 2523 end; 2524 2525 { Check if a polygon is convex, i.e. it always turns in the same direction } 2526 function IsConvex(const pts: array of TPointF; IgnoreAlign: boolean = true): boolean; 2527 var 2528 positive,negative,zero: boolean; 2529 product: single; 2530 i: Integer; 2531 begin 2532 positive := false; 2533 negative := false; 2534 zero := false; 2535 for i := 0 to high(pts) do 2536 begin 2537 product := (pts[(i+1) mod length(pts)].x-pts[i].x)*(pts[(i+2) mod length(pts)].y-pts[i].y) - 2538 (pts[(i+1) mod length(pts)].y-pts[i].y)*(pts[(i+2) mod length(pts)].x-pts[i].x); 2539 if product > 0 then 557 2540 begin 558 result := gt; 559 exit; 2541 if negative then 2542 begin 2543 result := false; 2544 exit; 2545 end; 2546 positive := true; 2547 end else 2548 if product < 0 then 2549 begin 2550 if positive then 2551 begin 2552 result := false; 2553 exit; 2554 end; 2555 negative := true; 2556 end else 2557 zero := true; 2558 end; 2559 if not IgnoreAlign and zero then 2560 result := false 2561 else 2562 result := true; 2563 end; 2564 2565 { Check if two segments intersect } 2566 function DoesSegmentIntersect(pt1,pt2,pt3,pt4: TPointF): boolean; 2567 var 2568 seg1: TLineDef; 2569 seg1len: single; 2570 seg2: TLineDef; 2571 seg2len: single; 2572 inter: TPointF; 2573 pos1,pos2: single; 2574 para: boolean; 2575 2576 begin 2577 { Determine line definitions } 2578 seg1.origin := pt1; 2579 seg1.dir := pt2-pt1; 2580 seg1len := sqrt(sqr(seg1.dir.X)+sqr(seg1.dir.Y)); 2581 if seg1len = 0 then 2582 begin 2583 result := false; 2584 exit; 2585 end; 2586 seg1.dir *= 1/seg1len; 2587 2588 seg2.origin := pt3; 2589 seg2.dir := pt4-pt3; 2590 seg2len := sqrt(sqr(seg2.dir.X)+sqr(seg2.dir.Y)); 2591 if seg2len = 0 then 2592 begin 2593 result := false; 2594 exit; 2595 end; 2596 seg2.dir *= 1/seg2len; 2597 2598 //obviously parallel 2599 if seg1.dir = seg2.dir then 2600 result := false 2601 else 2602 begin 2603 //try to compute intersection 2604 inter := IntersectLine(seg1,seg2,para); 2605 if para then 2606 result := false 2607 else 2608 begin 2609 //check if intersections are inside the segments 2610 pos1 := (inter-seg1.origin)*seg1.dir; 2611 pos2 := (inter-seg2.origin)*seg2.dir; 2612 if (pos1 >= 0) and (pos1 <= seg1len) and 2613 (pos2 >= 0) and (pos2 <= seg2len) then 2614 result := true 2615 else 2616 result := false; 560 2617 end; 561 end; 562 563 function BGRAToStr(c: TBGRAPixel): string; 564 begin 565 result := IntToHex(c.red,2)+IntToHex(c.green,2)+IntToHex(c.Blue,2)+IntToHex(c.Alpha,2); 566 end; 567 568 {$hints off} 569 {$notes off} 570 function StrToBGRA(str: string): TBGRAPixel; 571 var errPos: integer; 572 begin 573 if length(str)=6 then str += 'FF'; 574 if length(str)=3 then str += 'F'; 575 if length(str)=8 then 576 begin 577 val('$'+copy(str,1,2),result.red,errPos); 578 val('$'+copy(str,3,2),result.green,errPos); 579 val('$'+copy(str,5,2),result.blue,errPos); 580 val('$'+copy(str,7,2),result.alpha,errPos); 2618 end; 2619 end; 2620 2621 { Check if a quaduadrilateral intersects itself } 2622 function DoesQuadIntersect(pt1,pt2,pt3,pt4: TPointF): boolean; 2623 begin 2624 result := DoesSegmentIntersect(pt1,pt2,pt3,pt4) or DoesSegmentIntersect(pt2,pt3,pt4,pt1); 2625 end; 2626 2627 {************************** Cyclic functions *******************} 2628 2629 // Get the cyclic value in the range [0..cycle-1] 2630 function PositiveMod(value, cycle: integer): integer; inline; 2631 begin 2632 result := value mod cycle; 2633 if result < 0 then //modulo can be negative 2634 Inc(result, cycle); 2635 end; 2636 2637 { Table of precalc values. Note : the value is stored for 2638 the first half of the cycle, and values are stored 'minus 1' 2639 in order to stay in the range 0..65535 } 2640 var 2641 sinTab65536: packed array of word; 2642 2643 function Sin65536(value: word): integer; 2644 var b: integer; 2645 begin 2646 //allocate array 2647 if sinTab65536 = nil then 2648 setlength(sinTab65536,32768); 2649 2650 if value >= 32768 then //function is upside down after half-period 2651 begin 2652 b := value xor 32768; 2653 if sinTab65536[b] = 0 then //precalc 2654 sinTab65536[b] := round((sin(b*2*Pi/65536)+1)*65536/2)-1; 2655 result := not sinTab65536[b]; 581 2656 end else 582 if length(str)=4 then 583 begin 584 val('$'+copy(str,1,1),result.red,errPos); 585 val('$'+copy(str,2,1),result.green,errPos); 586 val('$'+copy(str,3,1),result.blue,errPos); 587 val('$'+copy(str,4,1),result.alpha,errPos); 588 result.red *= $11; 589 result.green *= $11; 590 result.blue *= $11; 591 result.alpha *= $11; 592 end else 593 result := BGRAPixelTransparent; 594 end; 595 {$notes on} 596 {$hints on} 2657 begin 2658 b := value; 2659 if sinTab65536[b] = 0 then //precalc 2660 sinTab65536[b] := round((sin(b*2*Pi/65536)+1)*65536/2)-1; 2661 {$hints off} 2662 result := sinTab65536[b]+1; 2663 {$hints on} 2664 end; 2665 end; 2666 2667 function Cos65536(value: word): integer; 2668 begin 2669 result := Sin65536(value+16384); //cosine is translated 2670 end; 2671 2672 procedure PrecalcSin65536; 2673 var 2674 i: Integer; 2675 begin 2676 for i := 0 to 32767 do Sin65536(i); 2677 end; 597 2678 598 2679 initialization 599 2680 600 2681 InitGamma; 2682 CSSColors := TBGRAColorList.Create; 2683 CSSColors.Add('AliceBlue',CSSAliceBlue); 2684 CSSColors.Add('AntiqueWhite',CSSAntiqueWhite); 2685 CSSColors.Add('Aqua',CSSAqua); 2686 CSSColors.Add('Aquamarine',CSSAquamarine); 2687 CSSColors.Add('Azure',CSSAzure); 2688 CSSColors.Add('Beige',CSSBeige); 2689 CSSColors.Add('Bisque',CSSBisque); 2690 CSSColors.Add('Black',CSSBlack); 2691 CSSColors.Add('BlanchedAlmond',CSSBlanchedAlmond); 2692 CSSColors.Add('Blue',CSSBlue); 2693 CSSColors.Add('BlueViolet',CSSBlueViolet); 2694 CSSColors.Add('Brown',CSSBrown); 2695 CSSColors.Add('BurlyWood',CSSBurlyWood); 2696 CSSColors.Add('CadetBlue',CSSCadetBlue); 2697 CSSColors.Add('Chartreuse',CSSChartreuse); 2698 CSSColors.Add('Chocolate',CSSChocolate); 2699 CSSColors.Add('Coral',CSSCoral); 2700 CSSColors.Add('CornflowerBlue',CSSCornflowerBlue); 2701 CSSColors.Add('Cornsilk',CSSCornsilk); 2702 CSSColors.Add('Crimson',CSSCrimson); 2703 CSSColors.Add('Cyan',CSSCyan); 2704 CSSColors.Add('DarkBlue',CSSDarkBlue); 2705 CSSColors.Add('DarkCyan',CSSDarkCyan); 2706 CSSColors.Add('DarkGoldenrod',CSSDarkGoldenrod); 2707 CSSColors.Add('DarkGray',CSSDarkGray); 2708 CSSColors.Add('DarkGreen',CSSDarkGreen); 2709 CSSColors.Add('DarkKhaki',CSSDarkKhaki); 2710 CSSColors.Add('DarkMagenta',CSSDarkMagenta); 2711 CSSColors.Add('DarkOliveGreen',CSSDarkOliveGreen); 2712 CSSColors.Add('DarkOrange',CSSDarkOrange); 2713 CSSColors.Add('DarkOrchid',CSSDarkOrchid); 2714 CSSColors.Add('DarkRed',CSSDarkRed); 2715 CSSColors.Add('DarkSalmon',CSSDarkSalmon); 2716 CSSColors.Add('DarkSeaGreen',CSSDarkSeaGreen); 2717 CSSColors.Add('DarkSlateBlue',CSSDarkSlateBlue); 2718 CSSColors.Add('DarkSlateGray',CSSDarkSlateGray); 2719 CSSColors.Add('DarkTurquoise',CSSDarkTurquoise); 2720 CSSColors.Add('DarkViolet',CSSDarkViolet); 2721 CSSColors.Add('DeepPink',CSSDeepPink); 2722 CSSColors.Add('DeepSkyBlue',CSSDeepSkyBlue); 2723 CSSColors.Add('DimGray',CSSDimGray); 2724 CSSColors.Add('DodgerBlue',CSSDodgerBlue); 2725 CSSColors.Add('FireBrick',CSSFireBrick); 2726 CSSColors.Add('FloralWhite',CSSFloralWhite); 2727 CSSColors.Add('ForestGreen',CSSForestGreen); 2728 CSSColors.Add('Fuchsia',CSSFuchsia); 2729 CSSColors.Add('Gainsboro',CSSGainsboro); 2730 CSSColors.Add('GhostWhite',CSSGhostWhite); 2731 CSSColors.Add('Gold',CSSGold); 2732 CSSColors.Add('Goldenrod',CSSGoldenrod); 2733 CSSColors.Add('Gray',CSSGray); 2734 CSSColors.Add('Green',CSSGreen); 2735 CSSColors.Add('GreenYellow',CSSGreenYellow); 2736 CSSColors.Add('Honeydew',CSSHoneydew); 2737 CSSColors.Add('HotPink',CSSHotPink); 2738 CSSColors.Add('IndianRed',CSSIndianRed); 2739 CSSColors.Add('Indigo',CSSIndigo); 2740 CSSColors.Add('Ivory',CSSIvory); 2741 CSSColors.Add('Khaki',CSSKhaki); 2742 CSSColors.Add('Lavender',CSSLavender); 2743 CSSColors.Add('LavenderBlush',CSSLavenderBlush); 2744 CSSColors.Add('LawnGreen',CSSLawnGreen); 2745 CSSColors.Add('LemonChiffon',CSSLemonChiffon); 2746 CSSColors.Add('LightBlue',CSSLightBlue); 2747 CSSColors.Add('LightCoral',CSSLightCoral); 2748 CSSColors.Add('LightCyan',CSSLightCyan); 2749 CSSColors.Add('LightGoldenrodYellow',CSSLightGoldenrodYellow); 2750 CSSColors.Add('LightGray',CSSLightGray); 2751 CSSColors.Add('LightGreen',CSSLightGreen); 2752 CSSColors.Add('LightPink',CSSLightPink); 2753 CSSColors.Add('LightSalmon',CSSLightSalmon); 2754 CSSColors.Add('LightSeaGreen',CSSLightSeaGreen); 2755 CSSColors.Add('LightSkyBlue',CSSLightSkyBlue); 2756 CSSColors.Add('LightSlateGray',CSSLightSlateGray); 2757 CSSColors.Add('LightSteelBlue',CSSLightSteelBlue); 2758 CSSColors.Add('LightYellow',CSSLightYellow); 2759 CSSColors.Add('Lime',CSSLime); 2760 CSSColors.Add('LimeGreen',CSSLimeGreen); 2761 CSSColors.Add('Linen',CSSLinen); 2762 CSSColors.Add('Magenta',CSSMagenta); 2763 CSSColors.Add('Maroon',CSSMaroon); 2764 CSSColors.Add('MediumAquamarine',CSSMediumAquamarine); 2765 CSSColors.Add('MediumBlue',CSSMediumBlue); 2766 CSSColors.Add('MediumOrchid',CSSMediumOrchid); 2767 CSSColors.Add('MediumPurple',CSSMediumPurple); 2768 CSSColors.Add('MediumSeaGreen',CSSMediumSeaGreen); 2769 CSSColors.Add('MediumSlateBlue',CSSMediumSlateBlue); 2770 CSSColors.Add('MediumSpringGreen',CSSMediumSpringGreen); 2771 CSSColors.Add('MediumTurquoise',CSSMediumTurquoise); 2772 CSSColors.Add('MediumVioletRed',CSSMediumVioletRed); 2773 CSSColors.Add('MidnightBlue',CSSMidnightBlue); 2774 CSSColors.Add('MintCream',CSSMintCream); 2775 CSSColors.Add('MistyRose',CSSMistyRose); 2776 CSSColors.Add('Moccasin',CSSMoccasin); 2777 CSSColors.Add('NavajoWhite',CSSNavajoWhite); 2778 CSSColors.Add('Navy',CSSNavy); 2779 CSSColors.Add('OldLace',CSSOldLace); 2780 CSSColors.Add('Olive',CSSOlive); 2781 CSSColors.Add('OliveDrab',CSSOliveDrab); 2782 CSSColors.Add('Orange',CSSOrange); 2783 CSSColors.Add('OrangeRed',CSSOrangeRed); 2784 CSSColors.Add('Orchid',CSSOrchid); 2785 CSSColors.Add('PaleGoldenrod',CSSPaleGoldenrod); 2786 CSSColors.Add('PaleGreen',CSSPaleGreen); 2787 CSSColors.Add('PaleTurquoise',CSSPaleTurquoise); 2788 CSSColors.Add('PaleVioletRed',CSSPaleVioletRed); 2789 CSSColors.Add('PapayaWhip',CSSPapayaWhip); 2790 CSSColors.Add('PeachPuff',CSSPeachPuff); 2791 CSSColors.Add('Peru',CSSPeru); 2792 CSSColors.Add('Pink',CSSPink); 2793 CSSColors.Add('Plum',CSSPlum); 2794 CSSColors.Add('PowderBlue',CSSPowderBlue); 2795 CSSColors.Add('Purple',CSSPurple); 2796 CSSColors.Add('Red',CSSRed); 2797 CSSColors.Add('RosyBrown',CSSRosyBrown); 2798 CSSColors.Add('RoyalBlue',CSSRoyalBlue); 2799 CSSColors.Add('SaddleBrown',CSSSaddleBrown); 2800 CSSColors.Add('Salmon',CSSSalmon); 2801 CSSColors.Add('SandyBrown',CSSSandyBrown); 2802 CSSColors.Add('SeaGreen',CSSSeaGreen); 2803 CSSColors.Add('Seashell',CSSSeashell); 2804 CSSColors.Add('Sienna',CSSSienna); 2805 CSSColors.Add('Silver',CSSSilver); 2806 CSSColors.Add('SkyBlue',CSSSkyBlue); 2807 CSSColors.Add('SlateBlue',CSSSlateBlue); 2808 CSSColors.Add('SlateGray',CSSSlateGray); 2809 CSSColors.Add('Snow',CSSSnow); 2810 CSSColors.Add('SpringGreen',CSSSpringGreen); 2811 CSSColors.Add('SteelBlue',CSSSteelBlue); 2812 CSSColors.Add('Tan',CSSTan); 2813 CSSColors.Add('Teal',CSSTeal); 2814 CSSColors.Add('Thistle',CSSThistle); 2815 CSSColors.Add('Tomato',CSSTomato); 2816 CSSColors.Add('Turquoise',CSSTurquoise); 2817 CSSColors.Add('Violet',CSSViolet); 2818 CSSColors.Add('Wheat',CSSWheat); 2819 CSSColors.Add('White',CSSWhite); 2820 CSSColors.Add('WhiteSmoke',CSSWhiteSmoke); 2821 CSSColors.Add('Yellow',CSSYellow); 2822 CSSColors.Add('YellowGreen',CSSYellowGreen); 2823 CSSColors.Finished; 2824 2825 finalization 2826 2827 CSSColors.Free; 601 2828 602 2829 end. 603
Note:
See TracChangeset
for help on using the changeset viewer.