View Issue Details

IDProjectCategoryView StatusLast Update
0017298ScribusScripterpublic2024-10-30 20:49
Reporterhugowett Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status newResolutionopen 
Product Version1.6.2 
Summary0017298: Add functions for getting and setting the size of the current page, and getting the bounding box of a page item
DescriptionI was writing a script for "cropping" a document to a set of elements and realised that we were missing functions for getting and setting the page size. There is a `getPageSize`, but only for getting the document setting.

While calculating the bounds to crop to I also noticed that we don't have a way to get the actual size of an item if it has been rotated, getSize always returns the size pre-transform.

* getCurrentPageSize() -> (width, height) - get the size of the current page
* setCurrentPageSize(width, height) - changes the size of the current page
* getBoundingBox() -> (x, y, width, height) - get the bounding box of a page item
Additional InformationExample of what I did whith these functions. The idea is that the elements we want to crop to would be named with a common prefix, f.ex. "A1_Headline".

import scribus

def extractObjects(prefix):
    all = scribus.getAllObjects()
    names = []

    # Collect all page items that have the name prefix, delete all others.
    for name in all:
        if not name.startswith(prefix):
            scribus.deleteObject(name)
        else:
            names.append(name)

    if len(names) == 0:
        raise Exception("unknown prefix")

    # Delete pages until only the page containing our page items remain.
    page = scribus.getItemPageNumber(names[0])+1
    while scribus.pageCount() > 1:
        page = scribus.getItemPageNumber(names[0])+1

        for i in range(1, scribus.pageCount()+1):
            if i == page:
                continue
            
            scribus.deletePage(i)
            break
    
    bounds = False

    # Get the bounding box for the page items.
    for name in names:
        x, y, width, height = scribus.getBoundingBox(name)

        print(f"{name} {x},{y} {width}x{height}")
        
        if not bounds:
            bounds = BoundingRect(x, y, width, height)
        else:
            bounds.extend(x, y, width, height)
        print(bounds)

    # We're going to move the page items to the top left of the page, make sure
    # that the baseline offset remains the same relative to the moved
    # frames.
    gridV, gridOff = scribus.getBaseLine()
    gridOff += gridV-(bounds.y%gridV)
    scribus.setBaseLine(gridV, gridOff)

    for name in names:
        scribus.moveObject(-bounds.x, -bounds.y, name)

    # Crop to content.
    scribus.setCurrentPageSize(bounds.width, bounds.height)

class BoundingRect:
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height

    def extend(self, x, y, width, height):
        new_x_min = min(self.x, x)
        new_y_min = min(self.y, y)
        new_x_max = max(self.x + self.width, x + width)
        new_y_max = max(self.y + self.height, y + height)
        
        self.x = new_x_min
        self.y = new_y_min
        self.width = new_x_max - new_x_min
        self.height = new_y_max - new_y_min

    def __repr__(self):
        return f"BoundingRect(x={self.x}, y={self.y}, width={self.width}, height={self.height})"
TagsNo tags attached.
PatchYes

Activities

hugowett

2024-10-23 11:38

reporter  

pagesize_bb.patch (7,130 bytes)   
Index: scribus/plugins/scriptplugin/cmdgetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetprop.cpp	(revision 26360)
+++ scribus/plugins/scriptplugin/cmdgetprop.cpp	(working copy)
@@ -328,6 +328,25 @@
 	return PyFloat_FromDouble(item->rotation() * -1.0);
 }
 
+PyObject *scribus_getboundingbox(PyObject* /* self */, PyObject* args)
+{
+    PyESString name;
+    if (!PyArg_ParseTuple(args, "|es", "utf-8", name.ptr()))
+        return nullptr;
+    if (!checkHaveDocument())
+        return nullptr;
+    PageItem *item = GetUniqueItem(QString::fromUtf8(name.c_str()));
+    if (item == nullptr)
+        return nullptr;
+
+    return Py_BuildValue("(dddd)",
+                         docUnitXToPageX(item->BoundingX),
+                         docUnitYToPageY(item->BoundingY),
+                         PointToValue(item->BoundingW),
+                         PointToValue(item->BoundingH)
+                         );
+}
+
 PyObject *scribus_getallobjects(PyObject* /* self */, PyObject* args, PyObject *keywds)
 {
 	int itemType = -1;
Index: scribus/plugins/scriptplugin/cmdgetprop.h
===================================================================
--- scribus/plugins/scriptplugin/cmdgetprop.h	(revision 26360)
+++ scribus/plugins/scriptplugin/cmdgetprop.h	(working copy)
@@ -252,6 +252,18 @@
 PyObject *scribus_getrotation(PyObject * /*self*/, PyObject* args);
 
 /*! docstring */
+PyDoc_STRVAR(scribus_getboundingbox__doc__,
+QT_TR_NOOP("getBoundingBox([\"name\"]) -> (x, y, width, height)\n\
+\n\
+Returns a (x, y, width, height) tuple with the position and size of the object \"name\".\n\
+If \"name\" is not given the currently selected item is used. The size is\n\
+expressed in the current measurement unit of the document - see UNIT_<type>\n\
+for reference.\n\
+"));
+/*! Returns size of the object */
+PyObject *scribus_getboundingbox(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
 PyDoc_STRVAR(scribus_getallobjects__doc__,
 QT_TR_NOOP("getAllObjects([type, page, \"layer\"]) -> list\n\
 \n\
Index: scribus/plugins/scriptplugin/cmdpage.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdpage.cpp	(revision 26360)
+++ scribus/plugins/scriptplugin/cmdpage.cpp	(working copy)
@@ -195,6 +195,49 @@
 	return t;
 }
 
+PyObject *scribus_getcurrentpagesize(PyObject* /* self */)
+{
+    if (!checkHaveDocument())
+        return nullptr;
+    ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
+    ScPage* currentPage = currentDoc->currentPage();
+
+    if (currentPage == nullptr)
+        return nullptr;
+
+    PyObject *t;
+    t = Py_BuildValue(
+        "(dd)",
+        PointToValue(currentPage->width()),
+        PointToValue(currentDoc->pageHeight())
+        );
+    return t;
+}
+
+PyObject *scribus_setcurrentpagesize(PyObject* /* self */, PyObject* args)
+{
+    double width, height;
+    if (!PyArg_ParseTuple(args, "dd", &width, &height))
+        return nullptr;
+    if (!checkHaveDocument())
+        return nullptr;
+
+    ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
+    ScribusView* currentView = ScCore->primaryMainWindow()->view;
+    ScPage* currentPage = currentDoc->currentPage();
+
+    if (currentPage == nullptr)
+        return nullptr;
+
+    currentPage->setWidth(ValueToPoint(width));
+    currentPage->setHeight(ValueToPoint(height));
+
+    currentView->reformPagesView();
+    currentView->DrawNew();
+
+    Py_RETURN_NONE;
+}
+
 PyObject *scribus_getpagensize(PyObject* /* self */, PyObject* args)
 {
 	int e;
Index: scribus/plugins/scriptplugin/cmdpage.h
===================================================================
--- scribus/plugins/scriptplugin/cmdpage.h	(revision 26360)
+++ scribus/plugins/scriptplugin/cmdpage.h	(working copy)
@@ -217,6 +217,25 @@
 PyObject *scribus_getpagesize(PyObject * /*self*/);
 
 /*! docstring */
+PyDoc_STRVAR(scribus_getcurrentpagesize__doc__,
+QT_TR_NOOP("getCurrentPageSize() ->  (width, height)\n\
+\n\
+Returns a tuple with current page dimensions measured in the document's current units.\n\
+See UNIT_<type> constants and getPageMargins()\n\
+"));
+PyObject *scribus_getcurrentpagesize(PyObject * /*self*/);
+
+
+/*! docstring */
+PyDoc_STRVAR(scribus_setcurrentpagesize__doc__,
+QT_TR_NOOP("setCurrentPageSize(width, height)\n\
+\n\
+Sets the current page dimensions measured in the document's current units.\n\
+See UNIT_<type> constants and getPageMargins()\n\
+"));
+PyObject *scribus_setcurrentpagesize(PyObject * /*self*/, PyObject* args);
+
+/*! docstring */
 PyDoc_STRVAR(scribus_getpagensize__doc__,
 QT_TR_NOOP("getPageNSize(nr) -> tuple\n\
 \n\
Index: scribus/plugins/scriptplugin/scriptplugin.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptplugin.cpp	(revision 26360)
+++ scribus/plugins/scriptplugin/scriptplugin.cpp	(working copy)
@@ -338,6 +338,7 @@
 	{ "getAllText", scribus_getalltext, METH_VARARGS, tr(scribus_getalltext__doc__)},
 	{ "getBaseLine", (PyCFunction) scribus_getbaseline, METH_NOARGS, tr(scribus_getbaseline__doc__)},
 	{ "getBleeds", scribus_getbleeds, METH_NOARGS, tr(scribus_getbleeds__doc__)},
+	{ "getBoundingBox", scribus_getboundingbox, METH_VARARGS, tr(scribus_getalltext__doc__)},
 	{ "getCellColumnSpan", scribus_getcellcolumnspan, METH_VARARGS, tr(scribus_getcellcolumnspan__doc__)},
 	{ "getCellFillColor", scribus_getcellfillcolor, METH_VARARGS, tr(scribus_getcellfillcolor__doc__)},
 	{ "getCellRowSpan", scribus_getcellrowspan, METH_VARARGS, tr(scribus_getcellrowspan__doc__)},
@@ -355,6 +356,7 @@
 	{ "getColumns", scribus_getcolumns, METH_VARARGS, tr(scribus_getcolumns__doc__)},
 	{ "getColumnGuides", (PyCFunction) scribus_getColumnGuides, METH_VARARGS|METH_KEYWORDS, tr(scribus_getColumnGuides__doc__)},
 	{ "getCornerRadius", scribus_getcornerradius, METH_VARARGS, tr(scribus_getcornerradius__doc__)},
+	{ "getCurrentPageSize", (PyCFunction) scribus_getcurrentpagesize, METH_NOARGS, tr(scribus_getcurrentpagesize__doc__)},
 	{ "getCustomLineStyle", scribus_getcustomlinestyle, METH_VARARGS, tr(scribus_getcustomlinestyle__doc__)},
 	{ "getDocName", (PyCFunction) scribus_getdocname, METH_NOARGS, tr(scribus_getdocname__doc__)},
 	{ "getFillBlendmode", scribus_getfillblendmode, METH_VARARGS, tr(scribus_getfillblendmode__doc__)},
@@ -527,6 +529,7 @@
 	{ "setColumnGuides", (PyCFunction) scribus_setColumnGuides, METH_VARARGS|METH_KEYWORDS, tr(scribus_setColumnGuides__doc__)},
 	{ "setCornerRadius", scribus_setcornerradius, METH_VARARGS, tr(scribus_setcornerradius__doc__)},
 	{ "setCursor", scribus_setcursor, METH_VARARGS, tr(scribus_setcursor__doc__)},
+	{ "setCurrentPageSize", scribus_setcurrentpagesize, METH_VARARGS, tr(scribus_setcurrentpagesize__doc__)},
 	{ "setCustomLineStyle", scribus_setcustomlinestyle, METH_VARARGS, tr(scribus_setcustomlinestyle__doc__)},
 	{ "setDocType", scribus_setdoctype, METH_VARARGS, tr(scribus_setdoctype__doc__)},
 	{ "setEditMode", (PyCFunction) scribus_seteditmode, METH_NOARGS, tr(scribus_seteditmode__doc__)},
pagesize_bb.patch (7,130 bytes)   

cbradney

2024-10-30 20:49

administrator   ~0051506

Ideally, the change page size code should be able to be very simple from scripter.. and call ScribusDoc::changePageProperties somehow, I need to check with Jean on that one.

Issue History

Date Modified Username Field Change
2024-10-23 11:38 hugowett New Issue
2024-10-23 11:38 hugowett File Added: pagesize_bb.patch
2024-10-30 20:47 cbradney Patch No => Yes
2024-10-30 20:49 cbradney Note Added: 0051506