Use Krita API to live-update vector layer content?

I’m building a plugin for Krita that allows editing text layers in an external application. Currently, my workflow for updating vector layer text is:

  1. Extract text - Read SVG content from the .kra file (which is a ZIP archive) by accessing layers/[layer].shapelayer/content.svg
  2. Parse and modify - Parse the SVG XML, find <text> and <tspan> elements, and replace their text content using regex-based replacement to preserve Krita’s specific XML formatting
  3. Update the .kra file:
  • Modify the SVG files
  • Close the document (doc.close())
  • Reopen the document (openDocument(kra_path))
  • Add it back to the active window (addView(new_doc))

The Problem:

  • It requires closing and reopening the document
  • User loses their current view/zoom position
  • Maybe slow for multiple documents update

Questions:

  • Is there a proper way to use Krita API to live-update vector layer content without document reload?

Update:

  • Does following workaround works?(have not tested yet)
    • Get all shapes: shapes = layer.shapes()
    • Get SVG for each shape: svg_content = shape.toSvg()
    • Modify the SVG: Parse and update the text content
    • Remove old shape: shape.remove()
    • Add modified shape: layer.addShapesFromSvg(modified_svg)
import sys
from krita import *
doc = Application.activeDocument()
root = doc.rootNode()
for layer in root.childNodes():    
	if (str(layer.type())=="vectorlayer"):        
		for shape in layer.shapes():            
			print(shape.name())            
			print(shape.toSvg())
shape0
<text fill="#000000" stroke-opacity="0" stroke="#000000" stroke-width="0" stroke-linecap="square" stroke-linejoin="bevel" paint-order="stroke fill markers" style="inline-size: 391.69;font-size: 20;white-space: pre-wrap;">Second Text

Test2
NewLine
NewLine2</text>
shape1
<text fill="#000000" stroke-opacity="0" stroke="#000000" stroke-width="0" stroke-linecap="square" stroke-linejoin="bevel" paint-order="stroke fill markers" style="inline-size: 292.429614181439;font-size: 20;white-space: pre-wrap;"><tspan>Second Text

</tspan><tspan style="font-size: 24;">Test2</tspan></text>
shape0
<text fill="#000000" stroke-opacity="0" stroke="#000000" stroke-width="0" stroke-linecap="square" stroke-linejoin="bevel" paint-order="stroke fill markers" style="inline-size: 277.451511991658;font-size: 22;white-space: pre-wrap;">Second Layer123

Test1

Test2 234
123</text>

2 Likes

I have found the solution:

  • For each vector layer, get the uniqueId and SVG data using toSvg()
  • Update the SVG data on the app side
  • Remove existing shapes in each vector layer, then call addShapesFromSvg()

1 Like