[DEVELOPMENT ENVIRONMENT]
* NEW: ImageEditor: Invert the current selected shape reverses its points order. Selection offset has been implemented on top of the new gb.clipper component. Many bug fixes. [GB.CLIPPER] * NEW: This a new component based on the "Clipper" library. At the moment, it only allows to offset a group of polygons from a specified pixel delta. git-svn-id: svn://localhost/gambas/trunk@5788 867c0c6c-44f3-4631-809d-bfa615b0a4ec
@ -547,7 +547,7 @@ msgstr ""
|
||||
#: FEditor.class:2373 FExportData.class:126 FFieldChooser.form:138
|
||||
#: FFileProperty.class:140 FFontChooser.form:40 FForm.class:3132
|
||||
#: FGotoLine.form:23 FHelpBrowser.form:61 FImageEditor.class:348
|
||||
#: FImageResize.form:49 FImageResizeSelection.form:33 FImageRotate.form:32
|
||||
#: FImageOffsetSelection.form:33 FImageResize.form:49 FImageRotate.form:32
|
||||
#: FInfo.class:263 FList.form:121 FMain.class:212 FMakeInstall.class:350
|
||||
#: FMenu.form:377 FNewConnection.form:255 FNewTable.form:86
|
||||
#: FNewTranslation.form:21 FOpenProject.form:158 FOption.class:675
|
||||
@ -647,7 +647,7 @@ msgstr ""
|
||||
|
||||
#: Design.module:428 FColorChooser.form:54 FConnectionEditor.class:452
|
||||
#: FCreateFile.form:443 FFieldChooser.form:132 FFontChooser.form:34
|
||||
#: FGotoLine.form:17 FImageResize.form:103 FImageResizeSelection.form:27
|
||||
#: FGotoLine.form:17 FImageOffsetSelection.form:27 FImageResize.form:103
|
||||
#: FImageRotate.form:26 FInfo.form:181 FList.form:115 FMain.class:1839
|
||||
#: FMakeInstall.class:299 FMenu.form:372 FNewConnection.form:249
|
||||
#: FNewTable.form:80 FNewTranslation.form:15 FOpenProject.form:152
|
||||
@ -719,31 +719,31 @@ msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:53 FConnectionEditor.form:358 FEditor.form:144
|
||||
#: FForm.form:239 FImageEditor.form:110 FMenu.form:107 FOutput.form:58
|
||||
#: FForm.form:239 FImageEditor.form:112 FMenu.form:107 FOutput.form:58
|
||||
#: FProjectVersion.form:234 FTextEditor.form:108
|
||||
msgid "Cut"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:59 FConnectionEditor.form:147 FEditor.form:150
|
||||
#: FForm.form:246 FImageEditor.form:118 FMenu.form:113 FOutput.form:65
|
||||
#: FForm.form:246 FImageEditor.form:120 FMenu.form:113 FOutput.form:65
|
||||
#: FProjectVersion.form:240 FTextEditor.form:115
|
||||
msgid "Copy"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:65 FConnectionEditor.form:379 FEditor.form:157
|
||||
#: FForm.form:259 FImageEditor.form:125 FMenu.form:119 FOutput.form:72
|
||||
#: FForm.form:259 FImageEditor.form:127 FMenu.form:119 FOutput.form:72
|
||||
#: FPasteTable.form:101 FProjectVersion.form:246 FTextEditor.form:122
|
||||
msgid "Paste"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:71 FConnectionEditor.form:386 FEditor.form:128
|
||||
#: FForm.form:222 FImageEditor.form:91 FOption.form:561 FOutput.form:41
|
||||
#: FForm.form:222 FImageEditor.form:93 FOption.form:561 FOutput.form:41
|
||||
#: FProjectVersion.form:252 FTextEditor.form:91
|
||||
msgid "Undo"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:77 FConnectionEditor.form:393 FEditor.form:135
|
||||
#: FForm.form:229 FImageEditor.form:99 FOutput.form:48
|
||||
#: FForm.form:229 FImageEditor.form:101 FOutput.form:48
|
||||
#: FProjectVersion.form:258 FTextEditor.form:98
|
||||
msgid "Redo"
|
||||
msgstr ""
|
||||
@ -788,7 +788,7 @@ msgid "Sol&ve"
|
||||
msgstr ""
|
||||
|
||||
#: FConflict.form:184 FDebugInfo.form:270 FEditor.form:310
|
||||
#: FFileProperty.form:75 FForm.form:408 FImageEditor.form:270
|
||||
#: FFileProperty.form:75 FForm.form:408 FImageEditor.form:281
|
||||
#: FImportTable.form:217 FProjectVersion.form:323 FSystemInfo.form:83
|
||||
#: FTextEditor.form:244 FTips.form:83
|
||||
msgid "Close"
|
||||
@ -837,12 +837,12 @@ msgid "Connection editor"
|
||||
msgstr ""
|
||||
|
||||
#: FConnectionEditor.form:100 FEditor.form:323 FForm.form:421
|
||||
#: FImageEditor.form:263 FMenu.class:68 FTextEditor.form:237
|
||||
#: FImageEditor.form:274 FMenu.class:68 FTextEditor.form:237
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: FConnectionEditor.form:108 FEditor.form:317 FForm.form:415
|
||||
#: FHelpBrowser.form:67 FImageEditor.form:256 FTextEditor.form:231
|
||||
#: FHelpBrowser.form:67 FImageEditor.form:267 FTextEditor.form:231
|
||||
#: FTranslate.class:650
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
@ -1437,7 +1437,7 @@ msgstr ""
|
||||
msgid "Function"
|
||||
msgstr ""
|
||||
|
||||
#: FDebugInfo.class:55 FImageEditor.form:429 FImportTable.class:66
|
||||
#: FDebugInfo.class:55 FImageEditor.form:440 FImportTable.class:66
|
||||
#: FOption.form:642
|
||||
msgid "Line"
|
||||
msgstr ""
|
||||
@ -1466,7 +1466,7 @@ msgstr ""
|
||||
msgid "Do you want to clear the expression list ?"
|
||||
msgstr ""
|
||||
|
||||
#: FDebugInfo.class:570 FImageEditor.form:511 FList.class:153
|
||||
#: FDebugInfo.class:570 FImageEditor.form:529 FList.class:153
|
||||
#: FOption.class:675 FOutput.form:79
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
@ -1503,7 +1503,7 @@ msgstr ""
|
||||
msgid "&Startup class"
|
||||
msgstr ""
|
||||
|
||||
#: FEditor.form:167 FImageEditor.form:135 FTextEditor.form:132
|
||||
#: FEditor.form:167 FImageEditor.form:137 FTextEditor.form:132
|
||||
msgid "Select &All"
|
||||
msgstr ""
|
||||
|
||||
@ -2025,11 +2025,11 @@ msgstr ""
|
||||
msgid "Show help tree"
|
||||
msgstr ""
|
||||
|
||||
#: FHelpBrowser.form:85 FImageEditor.form:222
|
||||
#: FHelpBrowser.form:85 FImageEditor.form:233
|
||||
msgid "Zoom in"
|
||||
msgstr ""
|
||||
|
||||
#: FHelpBrowser.form:91 FImageEditor.form:230
|
||||
#: FHelpBrowser.form:91 FImageEditor.form:241
|
||||
msgid "Zoom out"
|
||||
msgstr ""
|
||||
|
||||
@ -2049,114 +2049,126 @@ msgstr ""
|
||||
msgid "Default language"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:141
|
||||
#: FImageEditor.form:143
|
||||
msgid "Hide selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:148
|
||||
#: FImageEditor.form:150
|
||||
msgid "Invert selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:156
|
||||
#: FImageEditor.form:158
|
||||
msgid "Duplicate selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:164
|
||||
#: FImageEditor.form:166 FImageOffsetSelection.form:12
|
||||
msgid "Offset selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:175
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:169
|
||||
#: FImageEditor.form:180
|
||||
msgid "Crop"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:176 FImageProperty.form:289
|
||||
#: FImageEditor.form:187 FImageProperty.form:289
|
||||
msgid "Horizontal flip"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:183 FImageProperty.form:283
|
||||
#: FImageEditor.form:194 FImageProperty.form:283
|
||||
msgid "Vertical flip"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:190 FImageProperty.form:277
|
||||
#: FImageEditor.form:201 FImageProperty.form:277
|
||||
msgid "Rotate counter-clockwise"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:197 FImageProperty.form:271
|
||||
#: FImageEditor.form:208 FImageProperty.form:271
|
||||
msgid "Rotate clockwise"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:204
|
||||
#: FImageEditor.form:215
|
||||
msgid "Resize..."
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:211
|
||||
#: FImageEditor.form:222
|
||||
msgid "Rotate..."
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:217
|
||||
#: FImageEditor.form:228
|
||||
msgid "Zoom"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:238
|
||||
#: FImageEditor.form:249
|
||||
msgid "Zoom normal"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:245
|
||||
#: FImageEditor.form:256
|
||||
msgid "Zoom fit"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:279
|
||||
#: FImageEditor.form:290
|
||||
msgid "Image editor"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:379
|
||||
#: FImageEditor.form:390
|
||||
msgid "Drawing grid"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:394
|
||||
#: FImageEditor.form:405
|
||||
msgid "Move"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:405
|
||||
#: FImageEditor.form:416
|
||||
msgid "Draw"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:415
|
||||
#: FImageEditor.form:426
|
||||
msgid "Erase"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:439
|
||||
#: FImageEditor.form:450
|
||||
msgid "Rectangle"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:449
|
||||
#: FImageEditor.form:460
|
||||
msgid "Ellipse"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:461
|
||||
#: FImageEditor.form:472
|
||||
msgid "Magic wand"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:471
|
||||
#: FImageEditor.form:482
|
||||
msgid "Edit selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:497
|
||||
#: FImageEditor.form:515
|
||||
msgid "Stroke"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:504
|
||||
#: FImageEditor.form:522
|
||||
msgid "Fill"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:557
|
||||
#: FImageEditor.form:575
|
||||
msgid "Resize or stretch image"
|
||||
msgstr ""
|
||||
|
||||
#: FImageEditor.form:566 FImageRotate.form:11
|
||||
#: FImageEditor.form:584 FImageRotate.form:11
|
||||
msgid "Rotate image"
|
||||
msgstr ""
|
||||
|
||||
#: FImageOffsetSelection.form:22 FImageResize.form:127
|
||||
msgid "px"
|
||||
msgstr ""
|
||||
|
||||
#: FImageOffsetSelection.form:40
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#: FImageProperty.form:126 FReportBrushChooser.form:49
|
||||
msgid "Color"
|
||||
msgstr ""
|
||||
@ -2258,7 +2270,7 @@ msgstr ""
|
||||
msgid "Grid resolution"
|
||||
msgstr ""
|
||||
|
||||
#: FImageProperty.form:654
|
||||
#: FImageProperty.form:655
|
||||
msgid "Subdivision"
|
||||
msgstr ""
|
||||
|
||||
@ -2318,18 +2330,6 @@ msgstr ""
|
||||
msgid "Ratio"
|
||||
msgstr ""
|
||||
|
||||
#: FImageResize.form:127 FImageResizeSelection.form:22
|
||||
msgid "px"
|
||||
msgstr ""
|
||||
|
||||
#: FImageResizeSelection.form:12
|
||||
msgid "Enlarge selection"
|
||||
msgstr ""
|
||||
|
||||
#: FImageResizeSelection.form:40
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
|
||||
#: FImageRotate.form:21
|
||||
msgid "°"
|
||||
msgstr ""
|
||||
|
@ -8,6 +8,7 @@ VersionFile=1
|
||||
Component=gb.image
|
||||
Component=gb.qt4
|
||||
Component=gb.form
|
||||
Component=gb.clipper
|
||||
Component=gb.db
|
||||
Component=gb.db.form
|
||||
Component=gb.debug
|
||||
|
@ -219,7 +219,11 @@ End
|
||||
|
||||
Public Sub Invert()
|
||||
|
||||
_Invert = Not _Invert
|
||||
If _Current >= 0 Then
|
||||
Shapes[_Current].Invert
|
||||
Else
|
||||
_Invert = Not _Invert
|
||||
Endif
|
||||
|
||||
End
|
||||
|
||||
@ -233,6 +237,7 @@ End
|
||||
Public Sub Clear()
|
||||
|
||||
Shapes.Clear
|
||||
_Magnets.Clear
|
||||
|
||||
End
|
||||
|
||||
@ -708,3 +713,49 @@ Public Sub Duplicate()
|
||||
Next
|
||||
|
||||
End
|
||||
|
||||
Public Sub Offset(fOffset As Float, bDup As Boolean)
|
||||
|
||||
Dim aPolygons As New PointF[][]
|
||||
Dim hShape As CImageShape
|
||||
Dim I As Integer
|
||||
|
||||
If _Current < 0 Then
|
||||
|
||||
For I = 0 To Shapes.Max
|
||||
aPolygons.Add(Shapes[I].Points)
|
||||
Next
|
||||
|
||||
aPolygons = Clipper.OffsetPolygons(aPolygons, fOffset)
|
||||
|
||||
If Not bDup Then Clear()
|
||||
|
||||
For I = 0 To aPolygons.Max
|
||||
hShape = New CImageShape
|
||||
hShape.Points = aPolygons[I]
|
||||
hShape.AddMagnetsFromExtent()
|
||||
AddShape(hShape)
|
||||
Next
|
||||
|
||||
Else
|
||||
|
||||
aPolygons.Add(Shapes[_Current].Points)
|
||||
|
||||
aPolygons = Clipper.OffsetPolygons(aPolygons, fOffset)
|
||||
|
||||
If aPolygons.Count Then
|
||||
If Not bDup Then
|
||||
Shapes[_Current].Points = aPolygons[0]
|
||||
Shapes[_Current].AddMagnetsFromExtent()
|
||||
Else
|
||||
hShape = New CImageShape
|
||||
hShape.Points = aPolygons[0]
|
||||
hShape.AddMagnetsFromExtent()
|
||||
AddShape(hShape)
|
||||
_Current = Shapes.Max
|
||||
Endif
|
||||
Endif
|
||||
|
||||
Endif
|
||||
|
||||
End
|
||||
|
@ -238,3 +238,20 @@ Public Sub SetPoint(iPoint As Integer, hPoint As PointF)
|
||||
_Extents = Null
|
||||
|
||||
End
|
||||
|
||||
Public Sub AddMagnetsFromExtent()
|
||||
|
||||
Dim hExt As RectF = GetExtents()
|
||||
|
||||
AddMagnet(PointF(hExt.X, hExt.Y))
|
||||
AddMagnet(PointF(hExt.X + hExt.W, hExt.Y))
|
||||
AddMagnet(PointF(hExt.X, hExt.Y + hExt.H))
|
||||
AddMagnet(PointF(hExt.X + hExt.W, hExt.Y + hExt.H))
|
||||
|
||||
End
|
||||
|
||||
Public Sub Invert()
|
||||
|
||||
Points.Reverse
|
||||
|
||||
End
|
||||
|
@ -660,7 +660,7 @@ Public Sub imvImage_MouseDown()
|
||||
|
||||
If $iChangeAction = CHANGE_INSERT Then
|
||||
$vChangeIndex = $hSelect.InsertPoint($hLastPoint, $vChangeIndex)
|
||||
$hLastPoint.X = -1000000 ' Avoid automatic undo at MouseUp
|
||||
AddUndo($hSelect.Copy()) ' Avoid automatic undo at MouseUp
|
||||
$iChangeAction = CHANGE_POINT
|
||||
RefreshSelection
|
||||
Else If $iChangeAction = CHANGE_SELECT Then
|
||||
@ -1002,11 +1002,11 @@ Public Sub imvImage_MouseMove()
|
||||
Endif
|
||||
|
||||
If $iChangeAction = CHANGE_NOTHING Then
|
||||
If Hyp(Abs($hChangeRect.X - $hCurrentPoint.X), Abs($hChangeRect.Y - $hCurrentPoint.Y)) < 16 Then
|
||||
If Hyp(Abs($hChangeRect.X - $hCurrentPoint.X), Abs($hChangeRect.Y - $hCurrentPoint.Y)) < (16 / imvImage.Zoom) Then
|
||||
iMouse = Mouse.Cross
|
||||
$iChangeAction = CHANGE_ROTATE
|
||||
SetMagnet(Null)
|
||||
Else If Hyp(Abs($hChangeRect.X + $hChangeRect.W - $hCurrentPoint.X), Abs($hChangeRect.Y + $hChangeRect.H - $hCurrentPoint.Y)) < 16 Then
|
||||
Else If Hyp(Abs($hChangeRect.X + $hChangeRect.W - $hCurrentPoint.X), Abs($hChangeRect.Y + $hChangeRect.H - $hCurrentPoint.Y)) < (16 / imvImage.Zoom) Then
|
||||
iMouse = Mouse.Cross
|
||||
$iChangeAction = CHANGE_RESIZE
|
||||
SetMagnet(Null)
|
||||
@ -1051,7 +1051,6 @@ Public Sub Form_KeyPress()
|
||||
$bCtrl = Key.Control
|
||||
$bAlt = Key.Alt
|
||||
UpdateTool
|
||||
imvImage_MouseMove
|
||||
|
||||
If $hSelect And If $hChangeRect Then
|
||||
If Key.Code = Key.Delete Or If Key.Code = Key.Backspace Then
|
||||
@ -1067,6 +1066,8 @@ Public Sub Form_KeyPress()
|
||||
Endif
|
||||
Endif
|
||||
|
||||
imvImage_MouseMove
|
||||
|
||||
End
|
||||
|
||||
Public Sub Form_KeyRelease()
|
||||
@ -1139,39 +1140,54 @@ End
|
||||
Private Sub DrawTool()
|
||||
|
||||
Dim I As Integer
|
||||
Dim bDraw As Boolean
|
||||
|
||||
Select Case $sTool
|
||||
|
||||
Case "draw", "erase"
|
||||
|
||||
$hImage = $hSaveImage.Copy()
|
||||
Paint.Begin($hImage)
|
||||
If $aStroke.Count Then
|
||||
|
||||
FImageProperty.PaintForStroke
|
||||
'Paint.Brush.Scale(Paint.LineWidth, Paint.LineWidth)
|
||||
$hImage = $hSaveImage.Copy()
|
||||
Paint.Begin($hImage)
|
||||
|
||||
If $sTool = "erase" Then
|
||||
Paint.Operator = Paint.OperatorDestOut
|
||||
Endif
|
||||
FImageProperty.PaintForStroke
|
||||
'Paint.Brush.Scale(Paint.LineWidth, Paint.LineWidth)
|
||||
|
||||
If $aStroke.Count = 2 Then
|
||||
If Not Paint.AntiAlias Then
|
||||
Paint.Rectangle($aStroke[0], $aStroke[1], 1, 1)
|
||||
Paint.Fill
|
||||
Else
|
||||
Paint.Arc($aStroke[0], $aStroke[1], Paint.LineWidth / 2)
|
||||
Paint.Fill
|
||||
If $sTool = "erase" Then
|
||||
Paint.Operator = Paint.OperatorDestOut
|
||||
Endif
|
||||
Else
|
||||
Paint.MoveTo($aStroke[0], $aStroke[1])
|
||||
For I = 2 To $aStroke.Max Step 2
|
||||
Paint.LineTo($aStroke[I], $aStroke[I + 1])
|
||||
Next
|
||||
Paint.Stroke
|
||||
Endif
|
||||
|
||||
Paint.End
|
||||
Modify
|
||||
If Not Paint.AntiAlias Then
|
||||
Paint.MoveTo(CInt($aStroke[0]), CInt($aStroke[1]))
|
||||
For I = 2 To $aStroke.Max Step 2
|
||||
If CInt($aStroke[I]) = Paint.X And If CInt($aStroke[I + 1]) = Paint.Y Then Continue
|
||||
Paint.LineTo(CInt($aStroke[I]), CInt($aStroke[I + 1]))
|
||||
bDraw = True
|
||||
Next
|
||||
Paint.Stroke
|
||||
If Not bDraw Then
|
||||
Paint.Rectangle($aStroke[0], $aStroke[1], 1, 1)
|
||||
Paint.Fill
|
||||
Endif
|
||||
Else
|
||||
Paint.MoveTo($aStroke[0], $aStroke[1])
|
||||
For I = 2 To $aStroke.Max Step 2
|
||||
If CInt($aStroke[I]) = CInt(Paint.X) And If CInt($aStroke[I + 1]) = CInt(Paint.Y) Then Continue
|
||||
Paint.LineTo($aStroke[I], $aStroke[I + 1])
|
||||
bDraw = True
|
||||
Next
|
||||
Paint.Stroke
|
||||
If Not bDraw Then
|
||||
Paint.Arc($aStroke[0], $aStroke[1], Paint.LineWidth / 2)
|
||||
Paint.Fill
|
||||
Endif
|
||||
Endif
|
||||
|
||||
Paint.End
|
||||
Modify
|
||||
|
||||
Endif
|
||||
|
||||
Case "line", "rectangle"
|
||||
|
||||
@ -1193,6 +1209,7 @@ Public Sub imvImage_Draw(hZoom As Image)
|
||||
Dim X As Integer
|
||||
Dim Y As Integer
|
||||
Dim iGrid As Integer
|
||||
Dim W As Float
|
||||
|
||||
If Project.ActiveForm = Me And If FImageProperty.HasBalance() Then bBalance = True
|
||||
|
||||
@ -1473,6 +1490,24 @@ Public Sub imvImage_Draw(hZoom As Image)
|
||||
Paint.Rectangle($hChangeRect.X + $hChangeRect.W + (0.5 - 6) / imvImage.Zoom, $hChangeRect.Y + $hChangeRect.H + (0.5 - 6) / imvImage.Zoom, 12 / imvImage.Zoom, 12 / imvImage.Zoom)
|
||||
Paint.Fill
|
||||
|
||||
If $iChangeAction = CHANGE_POINT Or If $iChangeAction = CHANGE_INSERT Then
|
||||
|
||||
Paint.Background = Color.SetAlpha(Color.White, 128)
|
||||
W = 3 / imvImage.Zoom
|
||||
If $iChangeAction = CHANGE_INSERT Then
|
||||
With ($hSelect.Shapes[$vChangeIndex[0]].Points[$vChangeIndex[1]] + $hSelect.Shapes[$vChangeIndex[0]].Points[$vChangeIndex[1] + 1]) / 2
|
||||
Paint.Rectangle(.X - W, .Y - W, W * 2, W * 2)
|
||||
Paint.Fill
|
||||
End With
|
||||
Else
|
||||
With $hSelect.Shapes[$vChangeIndex[0]].Points[$vChangeIndex[1]]
|
||||
Paint.Rectangle(.X - W, .Y - W, W * 2, W * 2)
|
||||
Paint.Fill
|
||||
End With
|
||||
Endif
|
||||
|
||||
Endif
|
||||
|
||||
Paint.Restore
|
||||
|
||||
Endif
|
||||
@ -1946,10 +1981,10 @@ Public Sub RefreshSelection()
|
||||
|
||||
imvImage.Refresh
|
||||
If $sTool = "change" Then
|
||||
If $hSelect Then
|
||||
$hChangeRect = $hSelect.GetExtents()
|
||||
If Not $hSelect Or If $hSelect.IsVoid() Then
|
||||
ClearSelection
|
||||
Else
|
||||
$hChangeRect = Null
|
||||
$hChangeRect = $hSelect.GetExtents()
|
||||
Endif
|
||||
Endif
|
||||
|
||||
@ -2049,17 +2084,6 @@ Public Sub panToolBar_Configure()
|
||||
|
||||
End
|
||||
|
||||
Public Sub btnResizeSelection_Click()
|
||||
|
||||
If Not $hSelect Then Return
|
||||
If FImageResizeSelection.Run() Then Return
|
||||
|
||||
AddUndo($hSelect.Copy())
|
||||
$hSelect.Enlarge(FImageResizeSelection.Size, FImageResizeSelection.Duplicate)
|
||||
RefreshSelection
|
||||
|
||||
End
|
||||
|
||||
Public Sub btnRotate_Click()
|
||||
|
||||
If FImageRotate.Run(Me) Then
|
||||
@ -2146,8 +2170,6 @@ End
|
||||
|
||||
Public Sub btnDuplicate_Click()
|
||||
|
||||
Dim I As Integer
|
||||
|
||||
If $hSelect Then
|
||||
|
||||
AddUndo($hSelect.Copy())
|
||||
@ -2157,3 +2179,15 @@ Public Sub btnDuplicate_Click()
|
||||
Endif
|
||||
|
||||
End
|
||||
|
||||
Public Sub btnOffset_Click()
|
||||
|
||||
If Not $hSelect Then Return
|
||||
|
||||
If FImageOffsetSelection.Run() Then Return
|
||||
|
||||
AddUndo($hSelect.Copy())
|
||||
$hSelect.Offset(FImageOffsetSelection.Size, FImageOffsetSelection.Duplicate)
|
||||
RefreshSelection
|
||||
|
||||
End
|
||||
|
@ -65,6 +65,14 @@
|
||||
Action = ".duplicate"
|
||||
Text = ("Duplicate selection")
|
||||
Picture = Picture["img/draw/duplicate.png"]
|
||||
Shortcut = "Ctrl+D"
|
||||
}
|
||||
{ mnuOffset Menu btnOffset
|
||||
Name = "mnuOffset"
|
||||
Action = ".offset"
|
||||
Text = ("Offset selection")
|
||||
Picture = Picture["img/draw/offset.png"]
|
||||
Shortcut = "Ctrl+*"
|
||||
}
|
||||
{ mnuSep4 Menu
|
||||
}
|
||||
@ -304,7 +312,7 @@
|
||||
}
|
||||
{ btnRectangle ToolButton btnTool
|
||||
Name = "btnRectangle"
|
||||
MoveScaled(70,0,4,4)
|
||||
MoveScaled(69,0,4,4)
|
||||
Tag = "rectangle"
|
||||
ToolTip = ("Rectangle")
|
||||
Action = ".tool-rectangle"
|
||||
@ -313,7 +321,7 @@
|
||||
}
|
||||
{ btnEllipse ToolButton btnTool
|
||||
Name = "btnEllipse"
|
||||
MoveScaled(74,0,4,4)
|
||||
MoveScaled(72,0,4,4)
|
||||
Tag = "ellipse"
|
||||
ToolTip = ("Ellipse")
|
||||
Action = ".tool-ellipse"
|
||||
@ -322,7 +330,7 @@
|
||||
}
|
||||
{ btnMagic ToolButton btnTool
|
||||
Name = "btnMagic"
|
||||
MoveScaled(78,0,4,4)
|
||||
MoveScaled(75,0,4,4)
|
||||
Visible = False
|
||||
Enabled = False
|
||||
Tag = "magic"
|
||||
@ -333,7 +341,7 @@
|
||||
}
|
||||
{ btnEditSelection ToolButton btnTool
|
||||
Name = "btnEditSelection"
|
||||
MoveScaled(82,0,4,4)
|
||||
MoveScaled(79,0,4,4)
|
||||
Tag = "change"
|
||||
ToolTip = ("Edit selection")
|
||||
Action = ".tool-change"
|
||||
@ -341,17 +349,23 @@
|
||||
Toggle = True
|
||||
}
|
||||
{ btnInvert ToolButton
|
||||
MoveScaled(87,0,4,4)
|
||||
MoveScaled(83,0,4,4)
|
||||
ToolTip = ("Invert selection")
|
||||
Action = ".invert"
|
||||
Picture = Picture["img/draw/invert.png"]
|
||||
}
|
||||
{ btnDuplicate ToolButton
|
||||
MoveScaled(90,0,4,4)
|
||||
MoveScaled(86,0,4,4)
|
||||
ToolTip = ("Duplicate selection")
|
||||
Action = ".duplicate"
|
||||
Picture = Picture["img/draw/duplicate.png"]
|
||||
}
|
||||
{ btnOffset ToolButton
|
||||
MoveScaled(90,0,4,4)
|
||||
ToolTip = ("Offset selection")
|
||||
Action = ".offset"
|
||||
Picture = Picture["img/draw/offset.png"]
|
||||
}
|
||||
{ Separator5 Separator
|
||||
MoveScaled(95,0,1,4)
|
||||
}
|
||||
@ -480,7 +494,7 @@
|
||||
}
|
||||
{ Action duplicate
|
||||
Text = "Duplicate selection"
|
||||
Shortcut = ""
|
||||
Shortcut = "Ctrl+D"
|
||||
Picture = "img/draw/duplicate.png"
|
||||
}
|
||||
{ Action fill
|
||||
@ -510,6 +524,11 @@
|
||||
Shortcut = "Ctrl+I"
|
||||
Picture = "img/draw/invert.png"
|
||||
}
|
||||
{ Action offset
|
||||
Text = "Offset selection"
|
||||
Shortcut = "Ctrl+*"
|
||||
Picture = "img/draw/offset.png"
|
||||
}
|
||||
{ Action paste
|
||||
Text = "Paste"
|
||||
Shortcut = "Ctrl+V"
|
||||
@ -636,7 +655,7 @@
|
||||
{ Toolbars
|
||||
{ Toolbar image
|
||||
Text = "Image editor"
|
||||
List = "save,reload,undo,redo,copy,cut,tool-paste,zoom-in,zoom,zoom-out,zoom-normal,zoom-fit,grid,tool-move,tool-draw,tool-erase,tool-line,tool-rectangle,tool-ellipse,tool-magic,tool-change,invert,duplicate,stroke,fill,clear,crop,flip-h,flip-v,rotate-r,rotate-l,resize,rotate"
|
||||
Default = "save,reload,undo,redo,|,copy,cut,tool-paste,|,zoom-in,zoom,zoom-out,zoom-normal,zoom-fit,grid,|,tool-move,tool-draw,tool-erase,|,tool-line,tool-rectangle,tool-ellipse,tool-change,invert,duplicate,|,stroke,fill,clear,|,crop,flip-h,flip-v,rotate-r,rotate-l,resize,rotate"
|
||||
List = "save,reload,undo,redo,copy,cut,tool-paste,zoom-in,zoom,zoom-out,zoom-normal,zoom-fit,grid,tool-move,tool-draw,tool-erase,tool-line,tool-rectangle,tool-ellipse,tool-magic,tool-change,invert,duplicate,offset,stroke,fill,clear,crop,flip-h,flip-v,rotate-r,rotate-l,resize,rotate"
|
||||
Default = "save,reload,undo,redo,|,copy,cut,tool-paste,|,zoom-in,zoom,zoom-out,zoom-normal,zoom-fit,grid,|,tool-move,tool-draw,tool-erase,|,tool-line,tool-rectangle,tool-ellipse,tool-change,invert,duplicate,offset,|,stroke,fill,clear,|,crop,flip-h,flip-v,rotate-r,rotate-l,resize,rotate"
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ Static Public Duplicate As Boolean
|
||||
Public Sub Run() As Boolean
|
||||
|
||||
txtSize.Value = Size
|
||||
chkDuplicate.Value = Duplicate
|
||||
Return Not Me.ShowDialog()
|
||||
|
||||
End
|
@ -2,7 +2,7 @@
|
||||
|
||||
{ Form Form
|
||||
MoveScaled(0,0,39,12)
|
||||
Text = ("Enlarge selection")
|
||||
Text = ("Offset selection")
|
||||
{ txtSize SpinBox
|
||||
MoveScaled(1,1,10,4)
|
||||
MinValue = -256
|
||||
@ -24,7 +24,7 @@
|
||||
}
|
||||
{ chkDuplicate CheckBox
|
||||
MoveScaled(1,6,16,1)
|
||||
Visible = False
|
||||
AutoResize = True
|
||||
Text = ("Duplicate")
|
||||
}
|
||||
}
|
@ -458,6 +458,7 @@
|
||||
MinValue = 16
|
||||
MaxValue = 512
|
||||
Step = 16
|
||||
Value = 64
|
||||
}
|
||||
{ Label13 Label
|
||||
MoveScaled(31,0,14,4)
|
||||
|
Before Width: | Height: | Size: 224 B After Width: | Height: | Size: 260 B |
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 224 B |
Before Width: | Height: | Size: 232 B |
Before Width: | Height: | Size: 196 B After Width: | Height: | Size: 225 B |
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 406 B |
BIN
app/src/gambas3/img/draw/offset.png
Normal file
After Width: | Height: | Size: 221 B |
@ -113,6 +113,7 @@ lib/image.effect/Makefile \
|
||||
lib/signal/Makefile \
|
||||
lib/complex/Makefile \
|
||||
lib/data/Makefile \
|
||||
lib/clipper/Makefile \
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
SUBDIRS = . debug eval db compress vb option geom draw image gui gui.opengl \
|
||||
image.effect signal complex data
|
||||
image.effect signal complex data clipper
|
||||
|
||||
dist_gblib_DATA = gb.component
|
||||
gblib_DATA = gb.component
|
||||
|
26
main/lib/clipper/LICENSE
Normal file
@ -0,0 +1,26 @@
|
||||
The Clipper Library (including Delphi, C++ & C# source code, other accompanying
|
||||
code, examples and documentation), hereafter called "the Software", has been
|
||||
released under the following license, terms and conditions:
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the Software covered by this license to use, reproduce,
|
||||
display, distribute, execute, and transmit the Software, and to prepare
|
||||
derivative works of the Software, and to permit third-parties to whom the
|
||||
Software is furnished to do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including the
|
||||
above license grant, this restriction and the following disclaimer, must be
|
||||
included in all copies of the Software, in whole or in part, and all derivative
|
||||
works of the Software, unless such copies or derivative works are solely in the
|
||||
form of machine-executable object code generated by a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
19
main/lib/clipper/Makefile.am
Normal file
@ -0,0 +1,19 @@
|
||||
COMPONENT = gb.clipper
|
||||
include $(top_srcdir)/component.am
|
||||
|
||||
noinst_LTLIBRARIES = libclipper.la
|
||||
gblib_LTLIBRARIES = gb.clipper.la
|
||||
|
||||
libclipper_la_LIBADD =
|
||||
libclipper_la_LDFLAGS = -module @LD_FLAGS@
|
||||
libclipper_la_CXXFLAGS = -I$(top_srcdir)/share $(AM_CXXFLAGS_OPT) -fexceptions
|
||||
|
||||
libclipper_la_SOURCES = \
|
||||
clipper.hpp clipper.cpp
|
||||
|
||||
gb_clipper_la_LIBADD = libclipper.la
|
||||
gb_clipper_la_LDFLAGS = -module @LD_FLAGS@
|
||||
gb_clipper_la_CXXFLAGS = -I$(top_srcdir)/share $(AM_CXXFLAGS)
|
||||
|
||||
gb_clipper_la_SOURCES = \
|
||||
main.h main.cpp gb.geom.h c_clipper.cpp c_clipper.h
|
160
main/lib/clipper/c_clipper.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/***************************************************************************
|
||||
|
||||
c_clipper.cpp
|
||||
|
||||
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define __C_CLIPPER_CPP
|
||||
|
||||
#include "main.h"
|
||||
#include "gb.geom.h"
|
||||
#include "c_clipper.h"
|
||||
#include "clipper.hpp"
|
||||
|
||||
using namespace ClipperLib;
|
||||
|
||||
#define SCALE 1000000.0
|
||||
|
||||
static IntPoint to_point(GEOM_POINTF *point)
|
||||
{
|
||||
return IntPoint(point->x * SCALE + 0.5, point->y * SCALE + 0.5);
|
||||
}
|
||||
|
||||
static GEOM_POINTF *from_point(IntPoint p)
|
||||
{
|
||||
return GEOM.CreatePointF((double)p.X / SCALE, (double)p.Y / SCALE);
|
||||
}
|
||||
|
||||
/*static bool is_closed(GB_ARRAY p)
|
||||
{
|
||||
if (!p)
|
||||
return false;
|
||||
|
||||
int count = GB.Array.Count(p);
|
||||
if (count <= 1)
|
||||
return false;
|
||||
|
||||
GEOM_POINTF **ap = (GEOM_POINTF **)GB.Array.Get(p, 0);
|
||||
return ap[0]->x == ap[count - 1]->x && ap[0]->y == ap[count - 1]->y;
|
||||
}*/
|
||||
|
||||
static bool to_polygons(Polygons &polygons, GB_ARRAY array)
|
||||
{
|
||||
int count;
|
||||
GB_ARRAY a;
|
||||
int i, j;
|
||||
GEOM_POINTF **ap;
|
||||
GEOM_POINTF *pp;
|
||||
|
||||
if (GB.CheckObject(array))
|
||||
return true;
|
||||
|
||||
count = GB.Array.Count(array);
|
||||
if (count == 0)
|
||||
return false;
|
||||
|
||||
polygons.resize(count);
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
a = *(GB_ARRAY *)GB.Array.Get(array, i);
|
||||
if (!a)
|
||||
continue;
|
||||
ap = (GEOM_POINTF **)GB.Array.Get(a, 0);
|
||||
|
||||
for (j = 0; j < GB.Array.Count(a); j++)
|
||||
{
|
||||
pp = ap[j];
|
||||
if (!pp)
|
||||
continue;
|
||||
//fprintf(stderr, "<< %d %d: %g %g\n", i, j, pp->x, pp->y);
|
||||
polygons[i].push_back(to_point(pp));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static GB_ARRAY from_polygons(Polygons &polygons, GB_ARRAY array)
|
||||
{
|
||||
GB_ARRAY a;
|
||||
GB_ARRAY p;
|
||||
uint i, j, n;
|
||||
GEOM_POINTF *pp;
|
||||
|
||||
GB.Array.New(&a, GB.FindClass("PointF[]"), polygons.size());
|
||||
for (i = 0; i < polygons.size(); i++)
|
||||
{
|
||||
n = polygons[i].size();
|
||||
GB.Array.New(&p, GB.FindClass("PointF"), n);
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
pp = from_point(polygons[i][j]);
|
||||
//fprintf(stderr, ">> %d %d: %g %g\n", i, j, pp->x, pp->y);
|
||||
*(GEOM_POINTF **)GB.Array.Get(p, j) = pp;
|
||||
GB.Ref(pp);
|
||||
}
|
||||
|
||||
// Close polygon
|
||||
pp = from_point(polygons[i][0]);
|
||||
//fprintf(stderr, ">> %d %d: %g %g\n", i, j, pp->x, pp->y);
|
||||
*(GEOM_POINTF **)GB.Array.Add(p) = pp;
|
||||
GB.Ref(pp);
|
||||
|
||||
*(GB_ARRAY *)GB.Array.Get(a, i) = p;
|
||||
GB.Ref(p);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
BEGIN_METHOD(Clipper_OffsetPolygons, GB_OBJECT polygons; GB_FLOAT delta; GB_INTEGER join; GB_FLOAT limit; GB_BOOLEAN do_not_fix)
|
||||
|
||||
Polygons polygons;
|
||||
Polygons result;
|
||||
|
||||
if (to_polygons(polygons, VARG(polygons)))
|
||||
return;
|
||||
|
||||
SimplifyPolygons(polygons, result, pftNonZero);
|
||||
polygons = result;
|
||||
OffsetPolygons(polygons, result, VARG(delta) * SCALE, (JoinType)VARGOPT(join, jtSquare), VARGOPT(limit, 0.0), !VARGOPT(do_not_fix, false));
|
||||
|
||||
GB.ReturnObject(from_polygons(result, VARG(polygons)));
|
||||
|
||||
END_METHOD
|
||||
|
||||
GB_DESC ClipperDesc[] =
|
||||
{
|
||||
GB_DECLARE_VIRTUAL("Clipper"),
|
||||
|
||||
//void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, double delta, JoinType jointype = jtSquare, double limit = 0.0, bool autoFix = true);
|
||||
|
||||
GB_CONSTANT("JoinMiter", "i", jtMiter),
|
||||
GB_CONSTANT("JoinSquare", "i", jtSquare),
|
||||
GB_CONSTANT("JoinRound", "i", jtRound),
|
||||
|
||||
GB_STATIC_METHOD("OffsetPolygons", "PointF[][]", Clipper_OffsetPolygons, "(Polygons)PointF[][];(Delta)f[(Join)i(Limit)f(DoNotFix)b]"),
|
||||
|
||||
GB_END_DECLARE
|
||||
};
|
||||
|
||||
|
35
main/lib/clipper/c_clipper.h
Normal file
@ -0,0 +1,35 @@
|
||||
/***************************************************************************
|
||||
|
||||
c_clipper.h
|
||||
|
||||
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __C_CLIPPER_H
|
||||
#define __C_CLIPPER_H
|
||||
|
||||
#include "gambas.h"
|
||||
|
||||
#ifndef __C_CLIPPER_CPP
|
||||
|
||||
extern GB_DESC ClipperDesc[];
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
3700
main/lib/clipper/clipper.cpp
Normal file
349
main/lib/clipper/clipper.hpp
Normal file
@ -0,0 +1,349 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 5.1.6 *
|
||||
* Date : 23 May 2013 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2013 *
|
||||
* *
|
||||
* License: *
|
||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
||||
* http://www.boost.org/LICENSE_1_0.txt *
|
||||
* *
|
||||
* Attributions: *
|
||||
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
|
||||
* "A generic solution to polygon clipping" *
|
||||
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
|
||||
* http://portal.acm.org/citation.cfm?id=129906 *
|
||||
* *
|
||||
* Computer graphics and geometric modeling: implementation and algorithms *
|
||||
* By Max K. Agoston *
|
||||
* Springer; 1 edition (January 4, 2005) *
|
||||
* http://books.google.com/books?q=vatti+clipping+agoston *
|
||||
* *
|
||||
* See also: *
|
||||
* "Polygon Offsetting by Computing Winding Numbers" *
|
||||
* Paper no. DETC2005-85513 pp. 565-575 *
|
||||
* ASME 2005 International Design Engineering Technical Conferences *
|
||||
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
|
||||
* September 24-28, 2005 , Long Beach, California, USA *
|
||||
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef clipper_hpp
|
||||
#define clipper_hpp
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
|
||||
namespace ClipperLib {
|
||||
|
||||
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
|
||||
enum PolyType { ptSubject, ptClip };
|
||||
//By far the most widely used winding rules for polygon filling are
|
||||
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
|
||||
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
|
||||
//see http://glprogramming.com/red/chapter11.html
|
||||
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||
|
||||
typedef signed long long long64;
|
||||
typedef unsigned long long ulong64;
|
||||
|
||||
struct IntPoint {
|
||||
public:
|
||||
long64 X;
|
||||
long64 Y;
|
||||
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {};
|
||||
friend std::ostream& operator <<(std::ostream &s, IntPoint &p);
|
||||
};
|
||||
|
||||
typedef std::vector< IntPoint > Polygon;
|
||||
typedef std::vector< Polygon > Polygons;
|
||||
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, Polygon &p);
|
||||
std::ostream& operator <<(std::ostream &s, Polygons &p);
|
||||
|
||||
class PolyNode;
|
||||
typedef std::vector< PolyNode* > PolyNodes;
|
||||
|
||||
class PolyNode
|
||||
{
|
||||
public:
|
||||
PolyNode();
|
||||
Polygon Contour;
|
||||
PolyNodes Childs;
|
||||
PolyNode* Parent;
|
||||
PolyNode* GetNext() const;
|
||||
bool IsHole() const;
|
||||
int ChildCount() const;
|
||||
private:
|
||||
PolyNode* GetNextSiblingUp() const;
|
||||
unsigned Index; //node index in Parent.Childs
|
||||
void AddChild(PolyNode& child);
|
||||
friend class Clipper; //to access Index
|
||||
};
|
||||
|
||||
class PolyTree: public PolyNode
|
||||
{
|
||||
public:
|
||||
~PolyTree(){Clear();};
|
||||
PolyNode* GetFirst() const;
|
||||
void Clear();
|
||||
int Total() const;
|
||||
private:
|
||||
PolyNodes AllNodes;
|
||||
friend class Clipper; //to access AllNodes
|
||||
};
|
||||
|
||||
enum JoinType { jtSquare, jtRound, jtMiter };
|
||||
enum EndType { etClosed, etButt, etSquare, etRound};
|
||||
|
||||
bool Orientation(const Polygon &poly);
|
||||
double Area(const Polygon &poly);
|
||||
|
||||
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
|
||||
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
|
||||
|
||||
void OffsetPolyLines(const Polygons &in_lines, Polygons &out_lines,
|
||||
double delta, JoinType jointype = jtSquare, EndType endtype = etSquare, double limit = 0, bool autoFix = true);
|
||||
|
||||
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
|
||||
|
||||
void CleanPolygon(const Polygon& in_poly, Polygon& out_poly, double distance = 1.415);
|
||||
void CleanPolygons(const Polygons& in_polys, Polygons& out_polys, double distance = 1.415);
|
||||
|
||||
void PolyTreeToPolygons(const PolyTree& polytree, Polygons& polygons);
|
||||
|
||||
void ReversePolygon(Polygon& p);
|
||||
void ReversePolygons(Polygons& p);
|
||||
|
||||
//used internally ...
|
||||
enum EdgeSide { esLeft = 1, esRight = 2};
|
||||
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
|
||||
//inline IntersectProtects operator|(IntersectProtects a, IntersectProtects b)
|
||||
//{return static_cast<IntersectProtects>(static_cast<int>(a) | static_cast<int>(b));}
|
||||
|
||||
struct TEdge {
|
||||
long64 xbot;
|
||||
long64 ybot;
|
||||
long64 xcurr;
|
||||
long64 ycurr;
|
||||
long64 xtop;
|
||||
long64 ytop;
|
||||
double dx;
|
||||
long64 deltaX;
|
||||
long64 deltaY;
|
||||
PolyType polyType;
|
||||
EdgeSide side;
|
||||
int windDelta; //1 or -1 depending on winding direction
|
||||
int windCnt;
|
||||
int windCnt2; //winding count of the opposite polytype
|
||||
int outIdx;
|
||||
TEdge *next;
|
||||
TEdge *prev;
|
||||
TEdge *nextInLML;
|
||||
TEdge *nextInAEL;
|
||||
TEdge *prevInAEL;
|
||||
TEdge *nextInSEL;
|
||||
TEdge *prevInSEL;
|
||||
};
|
||||
|
||||
struct IntersectNode {
|
||||
TEdge *edge1;
|
||||
TEdge *edge2;
|
||||
IntPoint pt;
|
||||
IntersectNode *next;
|
||||
};
|
||||
|
||||
struct LocalMinima {
|
||||
long64 Y;
|
||||
TEdge *leftBound;
|
||||
TEdge *rightBound;
|
||||
LocalMinima *next;
|
||||
};
|
||||
|
||||
struct Scanbeam {
|
||||
long64 Y;
|
||||
Scanbeam *next;
|
||||
};
|
||||
|
||||
struct OutPt; //forward declaration
|
||||
|
||||
struct OutRec {
|
||||
int idx;
|
||||
bool isHole;
|
||||
OutRec *FirstLeft; //see comments in clipper.pas
|
||||
PolyNode *polyNode;
|
||||
OutPt *pts;
|
||||
OutPt *bottomPt;
|
||||
};
|
||||
|
||||
struct OutPt {
|
||||
int idx;
|
||||
IntPoint pt;
|
||||
OutPt *next;
|
||||
OutPt *prev;
|
||||
};
|
||||
|
||||
struct JoinRec {
|
||||
IntPoint pt1a;
|
||||
IntPoint pt1b;
|
||||
int poly1Idx;
|
||||
IntPoint pt2a;
|
||||
IntPoint pt2b;
|
||||
int poly2Idx;
|
||||
};
|
||||
|
||||
struct HorzJoinRec {
|
||||
TEdge *edge;
|
||||
int savedIdx;
|
||||
};
|
||||
|
||||
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; };
|
||||
|
||||
typedef std::vector < OutRec* > PolyOutList;
|
||||
typedef std::vector < TEdge* > EdgeList;
|
||||
typedef std::vector < JoinRec* > JoinList;
|
||||
typedef std::vector < HorzJoinRec* > HorzJoinList;
|
||||
|
||||
//ClipperBase is the ancestor to the Clipper class. It should not be
|
||||
//instantiated directly. This class simply abstracts the conversion of sets of
|
||||
//polygon coordinates into edge objects that are stored in a LocalMinima list.
|
||||
class ClipperBase
|
||||
{
|
||||
public:
|
||||
ClipperBase();
|
||||
virtual ~ClipperBase();
|
||||
bool AddPolygon(const Polygon &pg, PolyType polyType);
|
||||
bool AddPolygons( const Polygons &ppg, PolyType polyType);
|
||||
virtual void Clear();
|
||||
IntRect GetBounds();
|
||||
protected:
|
||||
void DisposeLocalMinimaList();
|
||||
TEdge* AddBoundsToLML(TEdge *e);
|
||||
void PopLocalMinima();
|
||||
virtual void Reset();
|
||||
void InsertLocalMinima(LocalMinima *newLm);
|
||||
LocalMinima *m_CurrentLM;
|
||||
LocalMinima *m_MinimaList;
|
||||
bool m_UseFullRange;
|
||||
EdgeList m_edges;
|
||||
};
|
||||
|
||||
class Clipper : public virtual ClipperBase
|
||||
{
|
||||
public:
|
||||
Clipper();
|
||||
~Clipper();
|
||||
bool Execute(ClipType clipType,
|
||||
Polygons &solution,
|
||||
PolyFillType subjFillType = pftEvenOdd,
|
||||
PolyFillType clipFillType = pftEvenOdd);
|
||||
bool Execute(ClipType clipType,
|
||||
PolyTree &polytree,
|
||||
PolyFillType subjFillType = pftEvenOdd,
|
||||
PolyFillType clipFillType = pftEvenOdd);
|
||||
void Clear();
|
||||
bool ReverseSolution() {return m_ReverseOutput;};
|
||||
void ReverseSolution(bool value) {m_ReverseOutput = value;};
|
||||
bool ForceSimple() {return m_ForceSimple;};
|
||||
void ForceSimple(bool value) {m_ForceSimple = value;};
|
||||
protected:
|
||||
void Reset();
|
||||
virtual bool ExecuteInternal();
|
||||
private:
|
||||
PolyOutList m_PolyOuts;
|
||||
JoinList m_Joins;
|
||||
HorzJoinList m_HorizJoins;
|
||||
ClipType m_ClipType;
|
||||
Scanbeam *m_Scanbeam;
|
||||
TEdge *m_ActiveEdges;
|
||||
TEdge *m_SortedEdges;
|
||||
IntersectNode *m_IntersectNodes;
|
||||
bool m_ExecuteLocked;
|
||||
PolyFillType m_ClipFillType;
|
||||
PolyFillType m_SubjFillType;
|
||||
bool m_ReverseOutput;
|
||||
bool m_UsingPolyTree;
|
||||
bool m_ForceSimple;
|
||||
void DisposeScanbeamList();
|
||||
void SetWindingCount(TEdge& edge);
|
||||
bool IsEvenOddFillType(const TEdge& edge) const;
|
||||
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
||||
void InsertScanbeam(const long64 Y);
|
||||
long64 PopScanbeam();
|
||||
void InsertLocalMinimaIntoAEL(const long64 botY);
|
||||
void InsertEdgeIntoAEL(TEdge *edge);
|
||||
void AddEdgeToSEL(TEdge *edge);
|
||||
void CopyAELToSEL();
|
||||
void DeleteFromSEL(TEdge *e);
|
||||
void DeleteFromAEL(TEdge *e);
|
||||
void UpdateEdgeIntoAEL(TEdge *&e);
|
||||
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
|
||||
bool IsContributing(const TEdge& edge) const;
|
||||
bool IsTopHorz(const long64 XPos);
|
||||
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
|
||||
void DoMaxima(TEdge *e, long64 topY);
|
||||
void ProcessHorizontals();
|
||||
void ProcessHorizontal(TEdge *horzEdge);
|
||||
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutRec* GetOutRec(int idx);
|
||||
void AppendPolygon(TEdge *e1, TEdge *e2);
|
||||
void IntersectEdges(TEdge *e1, TEdge *e2,
|
||||
const IntPoint &pt, const IntersectProtects protects);
|
||||
OutRec* CreateOutRec();
|
||||
void AddOutPt(TEdge *e, const IntPoint &pt);
|
||||
void DisposeAllPolyPts();
|
||||
void DisposeOutRec(PolyOutList::size_type index);
|
||||
bool ProcessIntersections(const long64 botY, const long64 topY);
|
||||
void InsertIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
void BuildIntersectList(const long64 botY, const long64 topY);
|
||||
void ProcessIntersectList();
|
||||
void ProcessEdgesAtTopOfScanbeam(const long64 topY);
|
||||
void BuildResult(Polygons& polys);
|
||||
void BuildResult2(PolyTree& polytree);
|
||||
void SetHoleState(TEdge *e, OutRec *outrec);
|
||||
void DisposeIntersectNodes();
|
||||
bool FixupIntersectionOrder();
|
||||
void FixupOutPolygon(OutRec &outrec);
|
||||
bool IsHole(TEdge *e);
|
||||
void FixHoleLinkage(OutRec &outrec);
|
||||
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1);
|
||||
void ClearJoins();
|
||||
void AddHorzJoin(TEdge *e, int idx);
|
||||
void ClearHorzJoins();
|
||||
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2);
|
||||
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
|
||||
void JoinCommonEdges();
|
||||
void DoSimplePolygons();
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class clipperException : public std::exception
|
||||
{
|
||||
public:
|
||||
clipperException(const char* description): m_descr(description) {}
|
||||
virtual ~clipperException() throw() {}
|
||||
virtual const char* what() const throw() {return m_descr.c_str();}
|
||||
private:
|
||||
std::string m_descr;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} //ClipperLib namespace
|
||||
|
||||
#endif //clipper_hpp
|
||||
|
||||
|
5
main/lib/clipper/gb.clipper.component
Normal file
@ -0,0 +1,5 @@
|
||||
[Component]
|
||||
Key=gb.image
|
||||
Name=Image buffer support
|
||||
Author=Benoît Minisini
|
||||
State=Experimental
|
1
main/lib/clipper/gb.geom.h
Symbolic link
@ -0,0 +1 @@
|
||||
../geom/gb.geom.h
|
61
main/lib/clipper/main.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
|
||||
main.cpp
|
||||
|
||||
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define __MAIN_CPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "gb_common.h"
|
||||
#include "c_clipper.h"
|
||||
#include "main.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
GB_INTERFACE GB EXPORT;
|
||||
GEOM_INTERFACE GEOM EXPORT;
|
||||
|
||||
GB_DESC *GB_CLASSES [] EXPORT =
|
||||
{
|
||||
ClipperDesc,
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *GB_INCLUDE EXPORT = "gb.geom";
|
||||
|
||||
int EXPORT GB_INIT(void)
|
||||
{
|
||||
GB.Component.Load("gb.geom");
|
||||
GB.GetInterface("gb.geom", GEOM_INTERFACE_VERSION, &GEOM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void EXPORT GB_EXIT()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
36
main/lib/clipper/main.h
Normal file
@ -0,0 +1,36 @@
|
||||
/***************************************************************************
|
||||
|
||||
main.h
|
||||
|
||||
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
MA 02110-1301, USA.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#include "gambas.h"
|
||||
#include "gb.geom.h"
|
||||
#include "gb_common.h"
|
||||
|
||||
#ifndef __MAIN_C
|
||||
extern "C" GB_INTERFACE GB;
|
||||
extern "C" GEOM_INTERFACE GEOM;
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|