Skip to content

Python API Transform Mask and ASL Layer styles, plus a bug fix

Python API: Add Transform Mask Node and get node index

Adds the Transform Mask to the Python API, and the ability to get the finalAffineTransform of the mask.

Also adds the ability to get the index of the current node within the parent node.

Python API: Add ability to import and export layer styles as ASL

Adds layerStyleToAsl and setLayerStyleFromAsl to be able to do basic manipulation of layer styles from the Python API.

Bugfix: Do not prompt for name if import of layer style is cancelled

Test Plan

  1. For the bugfix, right click a layer and go to layer styles. Then hit import. Then cancel the dialog. It should now properly cancel instead of asking for name.

  2. For the other 2, this script can be ran from scripter:

from PyQt5 import QtCore, QtGui, QtWidgets
import re

def matrix_array(mx):
    return [mx.m11(),mx.m12(),mx.m13(),mx.m21(),mx.m22(),mx.m23(),mx.m31(),mx.m32(),mx.m33()]

def setStroke(size):
    return '''<asl>
 <node type="Descriptor" classId="null" name="">
  <node type="UnitFloat" unit="#Prc" key="Scl " value="100"/>
  <node type="Boolean" key="masterFXSwitch" value="1"/>
  <node type="Descriptor" key="FrFX" classId="FrFX" name="">
   <node type="Boolean" key="enab" value="1"/>
   <node type="Enum" key="Styl" value="OutF" typeId="FStl"/>
   <node type="Enum" key="PntT" value="SClr" typeId="FrFl"/>
   <node type="Enum" key="Md  " value="Mltp" typeId="BlnM"/>
   <node type="UnitFloat" unit="#Prc" key="Opct" value="100"/>
   <node type="UnitFloat" unit="#Pxl" key="Sz  " value="''' + str(size) +'''"/>
   <node type="Descriptor" key="Clr " classId="RGBC" name="">
    <node type="Double" key="Rd  " value="0"/>
    <node type="Double" key="Grn " value="0"/>
    <node type="Double" key="Bl  " value="0"/>
   </node>
  </node>
 </node>
 <node type="Descriptor" classId="Styl" name="">
  <node type="Descriptor" key="documentMode" classId="documentMode" name=""/>
 </node>
</asl>'''
    
def stepper(i):
    print ("STEP", i)
    doc = Krita.instance().activeDocument()
    node = doc.activeNode()
    
    if i == 0:
        print ("Creating Vector Layer")
        newLayer = doc.createVectorLayer('VLayer1')
        
        doc.rootNode().addChildNode(newLayer,None)
        doc.setActiveNode(newLayer)
        print ("Done")

    elif i == 1:
        print ("Create Shape")
        newShapes=node.addShapesFromSvg('''<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"><!-- Created using Krita: https://krita.org --><svg xmlns="http://www.w3.org/2000/svg"                xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:krita="http://krita.org/namespaces/svg/krita" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="307.2pt" height="307.2pt" viewBox="0 0 307.2 307.2"><text id="shape0" krita:useRichText="true" krita:textVersion="2" transform="translate(8.9999996710103, 31.4999995065155)" fill="#0026ff" stroke-opacity="0" stroke="#000000" stroke-width="0" stroke-linecap="square" stroke-linejoin="bevel" font-size-adjust="0.372962" font-stretch="normal" letter-spacing="0" word-spacing="0"><tspan x="0">Top Shape2</tspan></text></svg>''')
       
        print ("Done")

    elif i == 2:
        print ("TEST: Set stroke of 2")
        print( "RESULT:", node.setLayerStyleFromAsl(setStroke(2)) )
       
        print ("TEST: Complete")
    elif i == 3:
        print ("TEST: Set stroke of 10")
        print( "RESULT:", node.setLayerStyleFromAsl(setStroke(10)))
       
        print ("TEST: Complete")
    elif i == 4:
        print ("TEST: Get ASL Style")

        print  ( "ASL Layer Style:", node.layerStyleToAsl() )

    elif i == 5:
        print ("TEST: create blank mask")
        mask = doc.createTransformMask("Transform 1")
        node.addChildNode(mask, None)
        print ("TEST: Complete")
    elif i == 6:
        print ("TEST: Get Mask Info")
        
        print ("NODE INDEX:", node.index())

        print ("NODE Final Affine Transform:", matrix_array(node.finalAffineTransform()) )


        print ("TEST: Complete")
        print ("DONE!")  
        

                        
    if i < 6: QtCore.QTimer.singleShot(2000, lambda: stepper(i+1) )
        
print ("Starting Test")  
newdoc = Krita.instance().createDocument(512, 512, "Python test document", "RGBA", "U8", "", 120.0)
Krita.instance().activeWindow().addView(newdoc)
stepper(0)

Formalities Checklist

  • I confirmed this builds.
  • I confirmed Krita ran and the relevant functions work.
  • I tested the relevant unit tests and can confirm they are not broken. (If not possible, don't hesitate to ask for help!)
  • I made sure my commits build individually and have good descriptions as per KDE guidelines.
  • I made sure my code conforms to the standards set in the HACKING file.
  • I can confirm the code is licensed and attributed appropriately, and that unattributed code is mine, as per KDE Licensing Policy.

Merge request reports