jjzjj

php - FPDF 和电视/电影剧本格式

coder 2024-07-03 原文

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

一点背景

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

有两个主要方面引起了关注,即我无法弄清楚:

  • Parent/Children XML 标签,不能分开。
  • 如果子标签很长并且必须继续到另一个页面,则必须创建后续标签以表明它仍然是父标签。例如,如果显示了一个 Character 标签,并且该标签的对话(通过宽度、字符长度和行高)计算(通过宽度、字符长度和行高)继续到下一页,那么必须再次显示父“字符”下一页的顶部。
    • 此类父/孤儿标签包括:
    • "sceneheadng"-> 任何标签。
    • “字符”-> 对话框或括号
    • “括号”-> 对话框

然而,理想情况下,父/子标签应该存储在这样的地方,这样就可以在没有大量代码的情况下添加更多标签。

经过大量 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 提供了一个 Screenplay 类 (http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/screenplay/screenplay.pdf),但是,我搜索了很远并广泛寻找基于 PHP 的工具将 LaTeX 转换为 PDF,但没有成功。我知道 LaTeX 在服务器端运行,但是我仍然需要基于 PHP 的命令过程才能使用 LaTeX 生成上述 PDF 文件。

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

最佳答案

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

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

有许多在线解决方案,有些是免费的,因此请选择适合您需要的解决方案:Compiling documents online

祝你好运!

关于php - FPDF 和电视/电影剧本格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8478720/

有关php - FPDF 和电视/电影剧本格式的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  3. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  6. ruby-on-rails - 如何在 Rails 中设置路由的默认格式? - 2

    路由有如下代码:resources:orders,only:[:create],defaults:{format:'json'}resources:users,only:[:create,:update],defaults:{format:'json'}resources:delivery_types,only:[:index],defaults:{format:'json'}resources:time_corrections,only:[:index],defaults:{format:'json'}是否可以使用1个字符串为所有资源设置默认格式,每行不带“默认值”散列?谢谢。

  7. ruby-on-rails - Rails 4 WYSIWYG Bootsy 不显示格式 - 2

    我刚刚按照thebootsygempage上的安装说明进行操作在我保存并查看帖子内容之前,一切看起来都不错。这是输出在View中的样子:HeaderSubhead:似乎没有呈现任何html格式,因为它被引号或类似的东西转义了-其他人有这个问题吗?我没有在github页面或SO上看到任何问题来指出我正确的方向。除了遵循gem安装说明之外,我还没有做任何事情,但也许我错过了什么或者只是犯了一个愚蠢的错误。如果你还有什么想知道的,请尽管问。干杯 最佳答案 你需要有这样的东西,转义html: 关

  8. ruby - 在 Ruby 中将整数格式化为固定长度的字符串 - 2

    有没有一种简单的方法可以将给定的整数格式化为具有固定长度和前导零的字符串?#convertnumberstostringsoffixedlength3[1,12,123,1234].map{|e|???}=>["001","012","123","234"]我找到了解决方案,但也许还有更聪明的方法。format('%03d',e)[-3..-1] 最佳答案 如何使用%1000而不是进行字符串操作来获取最后三位数字?[1,12,123,1234].map{|e|format('%03d',e%1000)}更新:根据theTinMan的

  9. ruby-on-rails - 如何正确格式化字符串,如 'mccdougal' 到 'McDougal' - 2

    什么Ruby或RailsDSL会将字符串"mccdougal"格式化为"McDougal",同时留下字符串"McDougal"原样?将titleize传递给"McDougal"结果如下:"McDougal".titleize#=>"McDougal" 最佳答案 据我所知,没有可以处理这种情况的Rails助手。这是一个非标准的边缘案例,需要特殊处理。但是,您可以创建自定义字符串变形。您可以将这段代码放入初始化程序中:ActiveSupport::Inflector.inflections(:en)do|inflect|inflect.

  10. ruby-on-rails - Rails 格式验证——字母数字,但不是纯数字 - 2

    什么是测试格式验证的最佳方法让我们说一个用户名,使用字母数字的正则表达式,但不是纯数字?我一直在我的模型中使用以下验证validates:username,:format=>{:with=>/^[a-z0-9]+[-a-z0-9]*[a-z0-9]+$/i}数字用户名(例如“342”)通过了验证,这是我不想要的。 最佳答案 您想“向前看”一封信:/\A(?=.*[a-z])[a-z\d]+\Z/i 关于ruby-on-rails-Rails格式验证——字母数字,但不是纯数字,我们在Sta

随机推荐