OFDRW提供了一种扩展机制,允许用户自定义元素,以满足用户对OFD文档生成的更高级别的需求。
目前OFDRW主要提供了两种方式来扩展自定义元素:
若你需要使用OFDRW深入控制OFD文档的生成过程,你可能还需了解一些OFDRW布局和元素的概念,详见后续章节 3.OFDRW元素概论 。
基于Canvas的扩展是一种较为简单,也是较为推荐扩展实现方式。
Canvas是Div一种特殊的扩展,Canvas集成了Div的所有功能,提供了图形化的绘制接口(ctx),该方式下调用者不必关心OFD图元以及资源管理,通过控制Canvas的绘制接口(ctx)来实现绘制效果。
扩展方式如下:
CanvasBase
类。Drawer#draw
方法。Drawer#draw
方法中通过ctx
对象绘制图形。// 1. 创建自定义元素Line,继承CanvasBase类
public class Line extends CanvasBase {
private double[] beginPoint = new double[]{0, 0};
private double[] endPoint = new double[]{0, 0};
// 2. 重写Canvas的构造器
public Line(double x, double y, double w, double h, double[] beginPoint, double[] endPoint) {
super(x, y, w, h);
this.beginPoint = beginPoint;
this.endPoint = endPoint;
}
public Line(double w, double h, double[] beginPoint, double[] endPoint) {
super(w, h);
this.beginPoint = beginPoint;
this.endPoint = endPoint;
}
// 3. 实现Drawer#draw方法
public void draw(DrawContext ctx) throws IOException {
// 4. 在Drawer#draw方法中通过ctx对象绘制图形
ctx.save();
try {
ctx.setLineWidth(0.353d);
ctx.beginPath();
ctx.strokeStyle = "#000000";
ctx.moveTo(beginPoint[0], beginPoint[1]);
ctx.lineTo(endPoint[0], endPoint[1]);
ctx.stroke();
} finally {
ctx.restore();
}
}
}
基于Canvas的扩展方式也有一些问题:
基于Div的扩展是一种较为高级的扩展方式也较为复杂。
在详细讲解如何扩展之前,您可以需要了解OFDRW布局和OFDRW元素的基本原理,详见后续章节 3.OFDRW元素概论 。
基于Div的扩展方式,您可以完全控制OFDRW元素转换为OFD图元的过程,并支持操作OFD虚拟容器,进行资源的管理等高级功能。
由于OFDRW具有流式布局和固定布局,在流式布局中:
扩展方式如下:
Div
类,Div为MVC中的模型层,在这里主要存储一些数据和配置参数,不做具体图元生成逻辑的控制。Div#doPrepare
方法,用于提供在指定宽度下元素的最终大小。Div#split
方法,用于在流式布局时将元素分割为多个元素,您可能还需重写clone
完成分割时的复制。Div#elementType
方法,用于返回元素的类型供解析引擎识别选择对应的渲染器。Processor
,渲染器为MVC中的控制器层,用于将您的自定义元素转换为OFD图元,在render
方法中您可以通过资源管理获取到文档的虚拟容器进行深度的操作。以Img对象为例,Img对象是OFDRW中的一个自定义元素,它继承自Div,用于表示OFD中的图片对象。
图片对象Img.java 如下:
// 1. 创建自定义元素Img,继承Div类
public class Img extends Div<Img> {
private Path src;
// 2. 固定大小,提供构造器设置元素大小
public Img(double width, double height, Path src) throws IOException {
// 3. 在构造器中设置元素不可分割
this.setIntegrity(true);
this.src = src;
this.setWidth(width);
this.setHeight(height);
}
public Path getSrc() { return src; }
// 4. 返回元素的类型供解析引擎识别选择对应的渲染器。
@Override
public String elementType() {
return "Img";
}
}
Img对象的渲染器 ImgRender.java 如下:
// 5. 创建自定义元素的渲染器,实现Processor
public class ImgRender implements Processor {
/**
* 执行图片渲染
*
* @param pageLoc 页面在虚拟容器中绝对路径。
* @param layer 图片将要放置的图层
* @param resManager 资源管理器
* @param div 图片对象
* @param maxUnitID 最大元素ID提供器
* @throws RenderException 渲染发生错误
*/
@Override
public void render(ST_Loc pageLoc, CT_PageBlock layer, ResManager resManager, Div div, AtomicInteger maxUnitID)throws RenderException {
Img e = (Img) div;
Path p = e.getSrc();
// 资源管理
ST_ID id = null;
try {
id = resManager.addImage(p);
} catch (IOException ex) {
throw new RenderException("渲染图片复制失败:" + ex.getMessage(), ex);
}
// 构造OFD图片图元
ImageObject imgObj = new ImageObject(maxUnitID.incrementAndGet());
imgObj.setResourceID(id.ref());
double x = e.getX() + e.getMarginLeft() + e.getBorderLeft() + e.getPaddingLeft();
double y = e.getY() + e.getMarginTop() + e.getBorderTop() + e.getPaddingTop();
imgObj.setBoundary(x, y, e.getWidth(), e.getHeight());
imgObj.setCTM(new ST_Array(e.getWidth(), 0, 0, e.getHeight(), 0, 0));
// 将OFD 图片图元对象加入图层。
layer.addPageBlock(imgObj);
}
}
向虚拟页面解析引擎(VPageParseEngine)中注册您自定义元素的渲染器。
class Main {
public static void main(String[] args) {
// 注册Img对象的渲染器
VPageParseEngine.register("Img", new ImgRender());
// ...
}
}
完整代码详见:
若您需要支持分割元素扩展示例,您可以参考:
为了让OFD页面上显示文字图形等元素,必须使用OFD中的对象描述这些图形图像,这些对象被称作图元(CT_GraphicUnit)常见的图元有:TextObject
、PathObject
、ImageObject
等。
OFDRW元素是对OFD对象生成方法的封装,通过OFDRW元素可以简化OFD图元的创建过程,减少开发者对OFD对象的直接操作, 这样开发者便不需要关心OFD图元对象的ID、资源ID、虚拟容器等细节,更多关注于文档内容的生成。
通常一个OFDRW元素往往需要多个OFD图元来实现,从OFD文档本身来说OFDRW元素是一个高层次的抽象,而OFD图元是一个低层次的实现。
基于上述设计OFDRW设计时采用了 模型-控制器-视图(Model-Controller-View) 的设计模式,在OFDRW中它们分别代表:
实际用户在操作OFDRW元素是可能还会接触到 虚拟页面、流式布局等概念,详见 《OFD 布局设计文档》 。
在OFDRW中,用户通过创建一个OFDRW元素,设置元素的属性,然后将元素添加到虚拟页面或文档中。 当文档关闭时,OFDRW会将虚拟页面中的OFDRW元素转换为OFD对象,也就是控制器驱动模型转换为视图的过程,该过程由 虚拟页面解析引擎(VPageParseEngine) 实现。
在虚拟页面解析引擎(VPageParseEngine)中,存储了每种OFDRW元素的 Render 对象,当 VPageParseEngine 得到一个OFDRW元素时,会根据元素的类型找到对应的 Render 对象,然后调用 Render 对象的 render 方法,将OFDRW元素转换为OFD对象。
任何OFDRW自定义元素都是基于Div扩展得到,因此任何OFDRW元素转换为图元前总是会先调用Div的 Render 对象的 render 方法,然后再调用自身的 render 方法。
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )