1. 默认构造函数实现
cpp
RS_Pen::RS_Pen() :
RS_Pen(RS_Color{Qt::black}, RS2::WidthByLayer, RS2::LineByLayer)
{}
关键点:
- 委托构造函数:使用 C++11 的委托构造函数特性
- 默认值 :
- 颜色:黑色(
Qt::black) - 线宽:按图层(
RS2::WidthByLayer) - 线型:按图层(
RS2::LineByLayer)
- 颜色:黑色(
- 设计意图:创建一个"继承图层属性"的默认笔
2. 流输出运算符实现
cpp
std::ostream& operator << (std::ostream& os, const RS_Pen& p) {
os << " pen color: " << p.getColor()
<< " pen width: " << p.getWidth()
<< " pen screen width: " << p.getScreenWidth()
<< " pen line type: " << p.getLineType()
<< " flags: " << (p.getFlag(RS2::FlagInvalid) ? "INVALID" : "")
<< std::endl;
return os;
}
输出内容:
- 颜色 :通过
getColor()获取 - 线宽:逻辑线宽(枚举值)
- 屏幕宽度:实际显示像素宽度
- 线型:线条样式
- 标志:显示是否为无效笔
3. 类设计的完整理解
3.1 构造函数的三种模式
cpp
// 1. 默认构造:黑色,属性继承图层
RS_Pen pen1;
// 2. 指定属性构造
RS_Pen pen2(RS_Color(Qt::red), RS2::Width03, RS2::DashLine);
// 3. 标志位构造(常用于无效笔)
RS_Pen pen3(RS2::FlagInvalid);
3.2 属性继承机制
cpp
// 检查各种继承状态
pen.isColorByLayer(); // 颜色是否继承图层
pen.isWidthByLayer(); // 线宽是否继承图层
pen.isLineTypeByLayer(); // 线型是否继承图层
3.3 属性更新机制
cpp
// 从另一个笔复制属性
pen.updateBy(otherPen);
// 这会复制颜色、线型、线宽、透明度、虚线偏移等
// 选择性复制
pen.setColorFromPen(otherPen);
pen.setWidthFromPen(otherPen);
4. 重要特性详解
4.1 透明度支持
cpp
float alpha = pen.getAlpha(); // 获取透明度 (0.0-1.0)
pen.setAlpha(0.5); // 设置为半透明
4.2 虚线偏移
cpp
pen.setDashOffset(2.5); // 设置虚线图案偏移
double offset = pen.dashOffset(); // 获取偏移值
4.3 有效性检查
cpp
if (pen.isValid()) {
// 笔有效,可以使用
}
4.4 比较操作
cpp
// 简单比较(忽略alpha和dashOffset)
if (pen1 == pen2) { ... }
// 精确比较(包含所有属性)
if (pen1.isSameAs(pen2, patternOffset)) { ... }
5. 实际应用示例
示例1:创建和使用笔
cpp
// 创建红色实线,中等宽度
RS_Pen drawingPen(RS_Color(Qt::red),
RS2::Width03,
RS2::SolidLine);
// 设置为半透明
drawingPen.setAlpha(0.7);
// 设置虚线偏移
drawingPen.setDashOffset(10.0);
// 检查有效性
if (drawingPen.isValid()) {
// 使用笔进行绘制
}
示例2:图层继承
cpp
// 创建按图层继承的笔
RS_Pen layerPen; // 默认就是按图层
// 检查属性继承
if (layerPen.hasByLayerAttributes()) {
// 当实体添加到图层时,会自动获取图层属性
}
示例3:调试输出
cpp
RS_Pen pen;
std::cout << pen; // 输出: "pen color: [black] pen width: -1 ..."
6. 设计模式分析
6.1 Builder模式元素
虽然不完全是Builder模式,但提供了链式设置的潜力:
cpp
pen.setColor(red).setWidth(RS2::Width03).setLineType(RS2::DashLine);
6.2 Flyweight模式元素
- 可能共享常用笔设置以减少内存使用
- 通过比较运算符支持对象复用
6.3 Strategy模式元素
- 笔的渲染策略(线型、宽度)可以在运行时改变
- 支持按图层/图块动态切换属性
7. 与其他类的关系
与 RS_Color:
cpp
RS_Color color = pen.getColor(); // 获取颜色对象
pen.setColor(RS_Color(255, 0, 0)); // 设置颜色
与 RS_Entity:
cpp
// 实体类会包含RS_Pen成员
class RS_Entity {
RS_Pen pen; // 实体的绘制属性
// ...
};
与 RS_Layer:
cpp
// 图层提供默认笔属性
class RS_Layer {
RS_Pen pen; // 图层的默认笔设置
// ...
};
8. 性能考虑
- 小对象优化 :
RS_Pen是值类型,适合按值传递 - 内联函数:大部分getter/setter已内联声明
- 默认成员初始化:C++11的类内成员初始化
- 移动语义:支持高效的复制和赋值
总结
RS_Pen 类是 LibreCAD 中一个精心设计的工具类,它:
- 封装了绘图属性:颜色、线宽、线型、透明度
- 支持继承机制:按图层、图块继承属性
- 提供完整接口:getter/setter、比较、输出
- 注重性能:小对象、内联函数
- 扩展性强:支持虚线偏移等高级特性
这个类的设计体现了 CAD 软件对图形属性管理的专业需求,是 LibreCAD 绘图引擎的基础组件之一。