bs_pnp_tools_docker.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. from krita import DockWidget
  2. from PyQt5.QtWidgets import QWidget, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QPushButton
  3. from PyQt5.QtCore import QByteArray
  4. DOCKER_TITLE = 'Button Shy PNP Tools'
  5. class BsPnpTools(DockWidget):
  6. def __init__(self):
  7. super().__init__()
  8. self.setWindowTitle(DOCKER_TITLE)
  9. widget = QWidget()
  10. layout = QVBoxLayout()
  11. widget.setLayout(layout)
  12. layout.addSpacing(10)
  13. layout.addWidget(QLabel('Expand the Button Shy 6-card PNP layout to 8-cards'))
  14. # Expand Direction. Do we put the 2 new cards on the left or right?
  15. self.expandDir = QComboBox()
  16. dirs = ['Right', 'Left']
  17. self.expandDir.addItems(dirs)
  18. row0 = QHBoxLayout()
  19. row0.addWidget(QLabel('Expand Direction:'))
  20. row0.addWidget(self.expandDir)
  21. layout.addLayout(row0)
  22. # Button (Shy)!
  23. layout.addSpacing(20)
  24. goButton = QPushButton("Expand")
  25. goButton.setIcon( Krita.instance().icon('animation_play') )
  26. layout.addWidget(goButton)
  27. crop3Button = QPushButton("Create 3x2 Cropmarks")
  28. crop3Button.setIcon( Krita.instance().icon('animation_play') )
  29. layout.addWidget(crop3Button)
  30. crop4Button = QPushButton("Create 4x2 Cropmarks")
  31. crop4Button.setIcon( Krita.instance().icon('animation_play') )
  32. layout.addWidget(crop4Button)
  33. # Add a stretch to prevent the rest of the content from stretching.
  34. layout.addStretch()
  35. # Add widget to the docker.
  36. self.setWidget(widget)
  37. # Hook up the action to the button.
  38. goButton.clicked.connect( self.expandBsPnp )
  39. crop3Button.clicked.connect( self.add3x2CropMarks )
  40. crop4Button.clicked.connect( self.add4x2CropMarks )
  41. # notifies when views are added or removed
  42. # 'pass' means do not do anything
  43. def canvasChanged(self, canvas):
  44. pass
  45. ##########
  46. # Slots
  47. ##########
  48. # Actually expands the PNP.
  49. def expandBsPnp(self, e):
  50. # dialog = QDialog()
  51. # dialog.setWindowTitle("DEBUG")
  52. # layout = QVBoxLayout()
  53. # dialog.setLayout(layout)
  54. # Get the current layer.
  55. doc = Krita.instance().activeDocument()
  56. layer = doc.activeNode()
  57. if layer.type() != 'paintlayer':
  58. dialog = QDialog()
  59. dialog.setWindowTitle("Paint Layer Required")
  60. layout = QVBoxLayout()
  61. layout.addWidget(QLabel('Expander only works on paint layers. Please select one.'))
  62. dialog.setLayout(layout)
  63. dialog.exec_()
  64. return
  65. direction = self.expandDir.currentText()
  66. layerPos = layer.position()
  67. # Move layer 411 pixels left or right, which is half a card and gap width: (752 + 70) / 2
  68. xDiff = 411 if direction == 'Left' else -411
  69. layer.move(layerPos.x() + xDiff, layerPos.y())
  70. # Fill in empty document area with white
  71. overlapHCrop = 341 # x-offset to overwrite old horizontal crop marks.
  72. whitePixel = b'\xff\xff\xff\xff'
  73. bds = layer.bounds()
  74. fillX = 0 if direction == 'Left' else bds.right() - overlapHCrop
  75. fillY = 0
  76. fillWidth = bds.left() + overlapHCrop if direction == 'Left' else doc.width() - fillX
  77. fillHeight = doc.height()
  78. whiteFill = QByteArray(whitePixel * fillWidth * fillHeight)
  79. layer.setPixelData(whiteFill, fillX, fillY, fillWidth, fillHeight)
  80. # Create horizontal cropmarks at image edges.
  81. # Vertical distances (px): 1047 (38 midY 37) 1048
  82. # 61px long.
  83. blackPixel = b'\x00\x00\x00\xff'
  84. cropMarkWidth = 61
  85. cropMarkHeight = 2
  86. cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
  87. midX = doc.width() / 2
  88. midY = doc.height() / 2
  89. ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ]
  90. for x in [midX - 1706, midX + 1645]:
  91. for y in ySet:
  92. layer.setPixelData(cropMark, x, y - 1, cropMarkWidth, cropMarkHeight)
  93. # Create vertical cropmarks for new card spaces
  94. # Horizontal distances (px): 752 70 752 (35 midX 35) 752 70 752
  95. # For these marks, we only want either the first or last 2 positions.
  96. # 37px long.
  97. cropMarkWidth = 2
  98. cropMarkHeight = 37
  99. cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
  100. xSet = [ midX - 1609, midX - 857 ] if direction == 'Left' else [ midX + 857, midX + 1609 ]
  101. for y in [ midY - 1192, midY + 1155 ]:
  102. for x in xSet:
  103. layer.setPixelData(cropMark, x - 1, y, cropMarkWidth, cropMarkHeight)
  104. # Place guides on crop marks for new card spaces
  105. vList = doc.verticalGuides()
  106. hList = doc.horizontalGuides()
  107. vList.clear()
  108. hList.clear()
  109. doc.setVerticalGuides(xSet)
  110. doc.setHorizontalGuides(ySet)
  111. doc.setGuidesLocked(True)
  112. doc.setGuidesVisible(True)
  113. # Refresh the view, or the moved will not be immediately reflected.
  114. doc.refreshProjection()
  115. # Add 3x2 Internal cropmarks.
  116. def add3x2CropMarks(self, e):
  117. self.addCropMarks(3)
  118. # Add 4x2 Internal cropmarks.
  119. def add4x2CropMarks(self, e):
  120. self.addCropMarks(4)
  121. def addCropMarks(self, gridSize):
  122. # Cropmarks will be on a new layer.
  123. doc = Krita.instance().activeDocument()
  124. layer = doc.createNode('BSCropmarks', 'paintLayer')
  125. root = doc.rootNode()
  126. root.addChildNode(layer, None)
  127. # Calculate grid dimensions, assuming page is in centre position.
  128. midX = doc.width() / 2
  129. midY = doc.height() / 2
  130. xSet = []
  131. ySet = []
  132. if gridSize == 3:
  133. # Horizontal distances (px): 752 70 (376 midX 376) 70 752
  134. # Vertical distances (px): 1047 (38 midY 37) 1048
  135. xSet = [ midX - 1198, midX - 446, midX - 376, midX + 376, midX + 446, midX + 1198 ]
  136. ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ]
  137. else:
  138. # Horizontal distances (px): 752 70 752 (35 midX 35) 752 70 752
  139. # Vertical distances (px): 1047 (38 midY 37) 1048
  140. xSet = [ midX - 1609, midX - 857, midX - 787, midX - 35, midX + 35, midX + 787, midX + 857, midX + 1609 ]
  141. ySet = [ midY - 1085, midY - 38, midY + 37, midY + 1085 ]
  142. # Create cropmarks.
  143. blackPixel = b'\x00\x00\x00\xff'
  144. cropMarkWidth = 2
  145. cropMarkHeight = 48
  146. cropMark = QByteArray(blackPixel * cropMarkWidth * cropMarkHeight)
  147. for x in xSet:
  148. for y in ySet:
  149. layer.setPixelData(cropMark, x - 1, y - cropMarkHeight/2, cropMarkWidth, cropMarkHeight) # vertical line
  150. layer.setPixelData(cropMark, x - cropMarkHeight/2, y - 1, cropMarkHeight, cropMarkWidth) # horizontal line
  151. # Refresh the view, or the cropmarks will not be immediately shown.
  152. doc.refreshProjection()