FPDF 和电视/电影剧本格式

发布于 2024-12-20 17:52:55 字数 5548 浏览 1 评论 0原文

我想创建一个 PHP 脚本,将 XML 格式化为电视/电影剧本,事实证明这比预期的要困难一些。我已经创建了一些代码,但是,有一些特定的地方我遇到了困难。

一点背景

剧本中存在多个标签,如角色、对话、场景标题、过渡等。它们具有不同的宽度和左右边距,决定了页面上的位置。

有两个主要领域值得关注,即我无法弄清楚:

  • 父/子 XML 标记,无法分开。
  • 如果子标签很长并且必须继续到另一个页面,则必须创建后续标签以表明它仍然是父标签。例如,如果显示“字符”标签,并且计算该标签(子级)的对话框(通过宽度、字符长度和行高)以继续下一页,则必须在以下位置再次显示父级“字符”下一页的顶部。
    • 此类父/孤立标签包括:
    • “场景头”->任何标签。
    • “字符”->对话或括号
    • “括号”->对话框

情况下,父/子标签的存储方式应该使得可以添加更多标签而无需大量代码。

经过多次 FPDF 配置和尝试后,到目前为止,这是我所得到的:

// Parse the XML string which has been requested from the database.
$xml                        = new SimpleXmlIterator($file, null);
$namespaces                 = $xml->getNamespaces(true);
/*
 * An external function which converts the XML into an ORDERED array.
 * This returns all the attributes of the xml and the following:
 *  "@type"     Refers to the type, i.e. character/dialog etc,
 *  "@content"  What was actually within the tags of the XML.
 */
$source                     = $parseXML($xml, $namespaces);
$saved                      = array ();
// For every line of the XML.
foreach ($source as $index => $line) {
    /*
     * We are going to save the current line of the XML so that we
     * can check the size of the saved cells against the size of the 
     * page. If there is not enough space for specific tags which are
     * required such as character and dialog, then we create a new page.
     * 
     */
    $saved[]                = $line;
    $forward                = false;
    /*
     * Here is where I get somewhat confused - I have attempted to create
     * a mechanism that determines the "@types" which are needed as parents
     * and children of one another. 
     *
     * The $forward variable refers to the possibilty of writing the tag to
     * the PDF. If the parent/orphan is possible or there are non, then it
     * should be able to write.
     */
    if ($forward) {
        $width              = 0;
        foreach ($saved as $index => $value) {
            /*
             * Everything is measured in inches, therefore, I have created a 
             * point() function which turns inches into mm so that FPDF understands
             * everything.
             * 
             * The $format variable is an array which has margins, either top,
             * left or right. We use this to position the Cell of a specific @type
             * so that it appears in the correct format for a TV/Film script.
             *
             * The width variable is deduced via finding the full width of the page,
             * then subtracting the subsequent left and right margin of the said
             * @type.
             */     
            $width          = (point ($setting["width"])
                            - (point ($format[$value["@type"]]["margin-left"])
                            +  point ($format[$value["@type"]]["margin-right"])));
            /*
             * The $pdf variable is that of the FPDF Class.
             */
            $pdf->SetLeftMargin (point($format[$value["@type"]]["margin-left"]));
            $pdf->SetRightMargin (point($format[$value["@type"]]["margin-right"]));
            // Formatting purposes.
            $pdf->Ln (0);   
            $pdf->MultiCell (
                $width,
                point ($setting["line-height"]), //Line height? Still needs fixing.
                $value["@content"], // Physical text
                1); // A temporary border to see what's going on.
        }
        // Reset the $saved, after no more parent/children?
        $saved              = array ();
    }
}

此外,我编写了一个函数来计算组合的“$saved”行的高度:

function calculate_page_breaks ($saved_lines, $act_upon = true) {
    $num_lines          = 0;
    foreach ($saved_lines as $value) {
        $column_width   = (point ($setting["width"])
                        - (point ($format[$type][$value["@type"]]["margin-left"])
                        +  point ($format[$type][$value["@type"]]["margin-right"])));
        $num_lines      += ceil($pdf->GetStringWidth($value["@content"]) / ($column_width - 1));
    }
    $cell_height        = 5 + 1; // have cells at a height of five so set to six for a padding
    $height_of_cell     = ceil($num_lines * $cell_height); 
    $space_left         = point($setting["height"]) - $pdf->GetY();
    $space_left         -= point($format[$type]["margin-bottom"]);
    // test if height of cell is greater than space left
    if ($height_of_cell >= $space_left) {
        // If this is not just a check, then we can physically "break" the page.
        if ($act_upon) {
            $pdf->Ln ();                        
            $pdf->AddPage (); // page break
            $pdf->SetTopMargin ($point($format[$type]["margin-top"]));
            $pdf->SetLeftMargin ($point($format[$type]["margin-left"]));
            $pdf->SetRightMargin ($point($format[$type]["margin-right"]));
            $pdf->MultiCell (100,5,'','B',2); // this creates a blank row for formatting reasons
        }
        return false;
    } else {
        return true;
    }
}

编辑

我发现 LaTeX 提供了剧本类(http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/screenplay/screenplay.pdf),然而,我已经广泛搜索以找到一个基于 PHP 的工具转换乳胶PDF,但没有成功。我知道 LaTeX 在服务器端运行,但是我仍然需要基于 PHP 的命令过程才能使用 LaTeX 生成所述 PDF 文件。

此外,在服务器上安装二进制文件、库或工具是禁忌。我可以使用的工具是 PHP 及其内置功能。任何可以将 LaTex 转换为 PDF 的类或 PHP 工具都非常有用。

I would like to create a PHP script which formats XML into a TV/Film Screenplay, this has proved somewhat more difficult than anticipated. I have created some of the code, however, there are particular places where I get stuck.

A little background

In a screenplay there exist multiple tags like character, dialog, sceneheading, transition etc. They have different widths and left and right margins determining the position on the page.

There are two main areas which have come into concern, i.e. I can't figure out:

  • Parent/Children XML tags, which cannot be separated.
  • If a child tag is long and has to continue to another page, then a subsequent tag must be created in order to show that it is still the parent. For instance, if a Character tag is shown and the dialog to that tag, the child, is calculated (through width, character length and line height) to continue to the next page, then the parent, "character" must be shown again at the top of the subsequent page.
    • Such parent/orphan tags include:
    • "sceneheadng" -> Any tag.
    • "character" -> dialog or parenthetical
    • "parenthetical" -> dialog

Ideally, however, the parent/children tags should be storred in such away that more can be added without lots and lots of code.

Here is what I have so far, after much FPDF configuration and attempts:

// Parse the XML string which has been requested from the database.
$xml                        = new SimpleXmlIterator($file, null);
$namespaces                 = $xml->getNamespaces(true);
/*
 * An external function which converts the XML into an ORDERED array.
 * This returns all the attributes of the xml and the following:
 *  "@type"     Refers to the type, i.e. character/dialog etc,
 *  "@content"  What was actually within the tags of the XML.
 */
$source                     = $parseXML($xml, $namespaces);
$saved                      = array ();
// For every line of the XML.
foreach ($source as $index => $line) {
    /*
     * We are going to save the current line of the XML so that we
     * can check the size of the saved cells against the size of the 
     * page. If there is not enough space for specific tags which are
     * required such as character and dialog, then we create a new page.
     * 
     */
    $saved[]                = $line;
    $forward                = false;
    /*
     * Here is where I get somewhat confused - I have attempted to create
     * a mechanism that determines the "@types" which are needed as parents
     * and children of one another. 
     *
     * The $forward variable refers to the possibilty of writing the tag to
     * the PDF. If the parent/orphan is possible or there are non, then it
     * should be able to write.
     */
    if ($forward) {
        $width              = 0;
        foreach ($saved as $index => $value) {
            /*
             * Everything is measured in inches, therefore, I have created a 
             * point() function which turns inches into mm so that FPDF understands
             * everything.
             * 
             * The $format variable is an array which has margins, either top,
             * left or right. We use this to position the Cell of a specific @type
             * so that it appears in the correct format for a TV/Film script.
             *
             * The width variable is deduced via finding the full width of the page,
             * then subtracting the subsequent left and right margin of the said
             * @type.
             */     
            $width          = (point ($setting["width"])
                            - (point ($format[$value["@type"]]["margin-left"])
                            +  point ($format[$value["@type"]]["margin-right"])));
            /*
             * The $pdf variable is that of the FPDF Class.
             */
            $pdf->SetLeftMargin (point($format[$value["@type"]]["margin-left"]));
            $pdf->SetRightMargin (point($format[$value["@type"]]["margin-right"]));
            // Formatting purposes.
            $pdf->Ln (0);   
            $pdf->MultiCell (
                $width,
                point ($setting["line-height"]), //Line height? Still needs fixing.
                $value["@content"], // Physical text
                1); // A temporary border to see what's going on.
        }
        // Reset the $saved, after no more parent/children?
        $saved              = array ();
    }
}

Additionally, I have written a function which calculates the height of the combined "$saved" lines:

function calculate_page_breaks ($saved_lines, $act_upon = true) {
    $num_lines          = 0;
    foreach ($saved_lines as $value) {
        $column_width   = (point ($setting["width"])
                        - (point ($format[$type][$value["@type"]]["margin-left"])
                        +  point ($format[$type][$value["@type"]]["margin-right"])));
        $num_lines      += ceil($pdf->GetStringWidth($value["@content"]) / ($column_width - 1));
    }
    $cell_height        = 5 + 1; // have cells at a height of five so set to six for a padding
    $height_of_cell     = ceil($num_lines * $cell_height); 
    $space_left         = point($setting["height"]) - $pdf->GetY();
    $space_left         -= point($format[$type]["margin-bottom"]);
    // test if height of cell is greater than space left
    if ($height_of_cell >= $space_left) {
        // If this is not just a check, then we can physically "break" the page.
        if ($act_upon) {
            $pdf->Ln ();                        
            $pdf->AddPage (); // page break
            $pdf->SetTopMargin ($point($format[$type]["margin-top"]));
            $pdf->SetLeftMargin ($point($format[$type]["margin-left"]));
            $pdf->SetRightMargin ($point($format[$type]["margin-right"]));
            $pdf->MultiCell (100,5,'','B',2); // this creates a blank row for formatting reasons
        }
        return false;
    } else {
        return true;
    }
}

Edit

I have discovered that LaTeX offers a Screenplay Class (http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/screenplay/screenplay.pdf), however, I have searched far and wide to find a PHP-based tool to convert LaTeX to PDF, but have had no success. I understand that LaTeX runs on the server side, however I still require a PHP-based command process in order to generate said PDF files using LaTeX.

Additionally, installing binaries, libraries or tools on to the server is a no-no. The tool at my disposal is PHP and the functionalities it has built in. Any class or PHP tool that can convert LaTex to PDF is incredibly useful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

书间行客 2024-12-27 17:52:55

根据您的要求,我建议使用在线网络服务来推送您的 LateX 文件并获得编译后的 PDF 作为回报。

这意味着您可以获得完整的 PDF 文件,无需任何编译、无需安装,仅基于纯 PHP Web 服务和 API。

有许多在线解决方案,其中一些是免费的,因此请检查适合您需要的一个:编译文档在线

祝你好运!

Given your requirements, I would recommend using online web services to push your LateX file and get a compiled PDF in return.

This means you get a full PDF file without any compilation, no installing, just pure PHP-based web services and API.

There are a number of online solutions, some are free, so please check the one that fits your need : Compiling documents online

Good luck !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文