Warning, file /office/calligra/libs/text/KoTextBlockBorderData.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2006 Thomas Zander <zander@kde.org>
0003  * Copyright (C) 2011 Stuart Dickson <stuart@furkinfantastic.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "KoTextBlockBorderData.h"
0022 
0023 #include <QPainter>
0024 
0025 #include "TextDebug.h"
0026 
0027 struct Edge {
0028     Edge() : distance(0.0) { innerPen.setWidthF(0.); outerPen.setWidthF(0.); }
0029     QPen innerPen;
0030     QPen outerPen;
0031     qreal distance;
0032 };
0033 
0034 class Q_DECL_HIDDEN KoTextBlockBorderData::Private
0035 {
0036 public:
0037     Private() : refCount(0), mergeWithNext(true) {}
0038     Edge edges[4];
0039 
0040     QAtomicInt refCount;
0041     bool mergeWithNext;
0042 };
0043 
0044 KoTextBlockBorderData::KoTextBlockBorderData(const QRectF &paragRect)
0045         : d(new Private())
0046 {
0047     ///TODO Remove parameter paragRect and update references to this constructor.
0048     Q_UNUSED(paragRect);
0049 }
0050 
0051 KoTextBlockBorderData::~KoTextBlockBorderData()
0052 {
0053     delete d;
0054 }
0055 
0056 KoTextBlockBorderData::KoTextBlockBorderData(const KoTextBlockBorderData &other)
0057         : d(new Private())
0058 {
0059     d->mergeWithNext = other.d->mergeWithNext;
0060 
0061     for (int i = Top; i <= Right; i++)
0062         d->edges[i] = other.d->edges[i];
0063 }
0064 
0065 void KoTextBlockBorderData::setMergeWithNext(bool merge)
0066 {
0067     d->mergeWithNext = merge;
0068 }
0069 
0070 bool KoTextBlockBorderData::hasBorders() const
0071 {
0072     for (int i = Top; i <= Right; i++)
0073         if (d->edges[i].outerPen.widthF() > 0.0)
0074             return true;
0075     return false;
0076 }
0077 
0078 bool KoTextBlockBorderData::operator==(const KoTextBlockBorderData &border) const
0079 {
0080     return equals(border);
0081 }
0082 bool KoTextBlockBorderData::equals(const KoTextBlockBorderData &border) const
0083 {
0084     if (!d->mergeWithNext) {
0085         return false;
0086     }
0087     for (int i = Top; i <= Right; i++) {
0088         if (d->edges[i].outerPen != border.d->edges[i].outerPen)
0089             return false;
0090         if (d->edges[i].innerPen != border.d->edges[i].innerPen)
0091             return false;
0092         if (qAbs(d->edges[i].distance - border.d->edges[i].distance) > 1E-10)
0093             return false;
0094     }
0095     return true;
0096 }
0097 
0098 void KoTextBlockBorderData::paint(QPainter &painter, const QRectF &bounds) const
0099 {
0100     QRectF innerBounds = bounds;
0101     if (d->edges[Top].outerPen.widthF() > 0) {
0102         QPen pen = d->edges[Top].outerPen;
0103         painter.setPen(pen);
0104         const qreal t = bounds.top() + pen.widthF() / 2.0;
0105         painter.drawLine(QLineF(bounds.left(), t, bounds.right(), t));
0106         innerBounds.setTop(bounds.top() + d->edges[Top].distance + pen.widthF());
0107     }
0108     if (d->edges[Bottom].outerPen.widthF() > 0) {
0109         QPen pen = d->edges[Bottom].outerPen;
0110         painter.setPen(pen);
0111         const qreal b = bounds.bottom() - pen.widthF() / 2.0;
0112         innerBounds.setBottom(bounds.bottom() - d->edges[Bottom].distance - pen.widthF());
0113         painter.drawLine(QLineF(bounds.left(), b, bounds.right(), b));
0114     }
0115     if (d->edges[Left].outerPen.widthF() > 0) {
0116         QPen pen = d->edges[Left].outerPen;
0117         painter.setPen(pen);
0118         const qreal l = bounds.left() + pen.widthF() / 2.0;
0119         innerBounds.setLeft(bounds.left() + d->edges[Left].distance + pen.widthF());
0120         painter.drawLine(QLineF(l, bounds.top(), l, bounds.bottom()));
0121     }
0122     if (d->edges[Right].outerPen.widthF() > 0) {
0123         QPen pen = d->edges[Right].outerPen;
0124         painter.setPen(pen);
0125         const qreal r = bounds.right() - pen.widthF() / 2.0;
0126         innerBounds.setRight(bounds.right() - d->edges[Right].distance - pen.widthF());
0127         painter.drawLine(QLineF(r, bounds.top(), r, bounds.bottom()));
0128     }
0129     // inner lines
0130     if (d->edges[Top].innerPen.widthF() > 0) {
0131         QPen pen = d->edges[Top].innerPen;
0132         painter.setPen(pen);
0133         const qreal t = innerBounds.top() + pen.widthF() / 2.0;
0134         painter.drawLine(QLineF(innerBounds.left(), t, innerBounds.right(), t));
0135     }
0136     if (d->edges[Bottom].innerPen.widthF() > 0) {
0137         QPen pen = d->edges[Bottom].innerPen;
0138         painter.setPen(pen);
0139         const qreal b = innerBounds.bottom() - pen.widthF() / 2.0;
0140         painter.drawLine(QLineF(innerBounds.left(), b, innerBounds.right(), b));
0141     }
0142     if (d->edges[Left].innerPen.widthF() > 0) {
0143         QPen pen = d->edges[Left].innerPen;
0144         painter.setPen(pen);
0145         const qreal l = innerBounds.left() + pen.widthF() / 2.0;
0146         painter.drawLine(QLineF(l, innerBounds.top(), l, innerBounds.bottom()));
0147     }
0148     if (d->edges[Right].innerPen.widthF() > 0) {
0149         QPen pen = d->edges[Right].innerPen;
0150         painter.setPen(pen);
0151         const qreal r = innerBounds.right() - pen.widthF() / 2.0;
0152         painter.drawLine(QLineF(r, innerBounds.top(), r, innerBounds.bottom()));
0153     }
0154 }
0155 
0156 qreal KoTextBlockBorderData::inset(Side side) const
0157 {
0158     return d->edges[side].outerPen.widthF() + d->edges[side].distance + d->edges[side].innerPen.widthF();
0159 }
0160 
0161 void KoTextBlockBorderData::setEdge(Side side, const QTextBlockFormat &bf,
0162                                     KoParagraphStyle::Property style, KoParagraphStyle::Property width,
0163                                     KoParagraphStyle::Property color, KoParagraphStyle::Property space,
0164                                     KoParagraphStyle::Property innerWidth)
0165 {
0166 
0167     Edge edge;
0168     KoBorder::BorderStyle  borderStyle;
0169     borderStyle = static_cast<KoBorder::BorderStyle>(bf.intProperty(style));
0170     switch (borderStyle) {
0171     case KoBorder::BorderDotted: edge.innerPen.setStyle(Qt::DotLine); break;
0172     case KoBorder::BorderDashed: edge.innerPen.setStyle(Qt::DashLine); break;
0173     case KoBorder::BorderDashDot: edge.innerPen.setStyle(Qt::DashDotLine); break;
0174     case KoBorder::BorderDashDotDot: edge.innerPen.setStyle(Qt::DashDotDotLine); break;
0175     case KoBorder::BorderGroove: /* TODO */ break;
0176     case KoBorder::BorderRidge: /* TODO */ break;
0177     case KoBorder::BorderInset: /* TODO */ break;
0178     case KoBorder::BorderOutset: /* TODO */ break;
0179     default:
0180         edge.innerPen.setStyle(Qt::SolidLine);
0181     }
0182     edge.innerPen.setColor(bf.colorProperty(color));
0183     edge.innerPen.setJoinStyle(Qt::MiterJoin);
0184     edge.innerPen.setCapStyle(Qt::FlatCap);
0185     edge.outerPen = edge.innerPen;
0186     edge.outerPen.setWidthF(bf.doubleProperty(width));   // TODO check if this does not need any conversion
0187 
0188     edge.distance = bf.doubleProperty(space);
0189     edge.innerPen.setWidthF(bf.doubleProperty(innerWidth));
0190 
0191     d->edges[side] = edge;
0192 }
0193 
0194 bool KoTextBlockBorderData::ref()
0195 {
0196     return d->refCount.ref();
0197 }
0198 
0199 bool KoTextBlockBorderData::deref()
0200 {
0201     return d->refCount.deref();
0202 }
0203 
0204 int KoTextBlockBorderData::useCount() const
0205 {
0206     return d->refCount;
0207 }