File indexing completed on 2024-04-21 04:32:13

0001 /*
0002  * Copyright (C) 2010-2015 by Stephen Allewell
0003  * steve.allewell@gmail.com
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation; either version 2 of the License, or
0008  * (at your option) any later version.
0009  */
0010 
0011 #include "Renderer.h"
0012 
0013 #include <QPaintEngine>
0014 #include <QPainter>
0015 #include <QPen>
0016 #include <QWidget>
0017 
0018 #include "Document.h"
0019 #include "DocumentFloss.h"
0020 #include "Stitch.h"
0021 #include "Symbol.h"
0022 #include "SymbolLibrary.h"
0023 #include "SymbolManager.h"
0024 
0025 class RendererData : public QSharedData
0026 {
0027 public:
0028     RendererData();
0029     RendererData(const RendererData &);
0030 
0031     friend class Renderer;
0032 
0033 private:
0034     int m_cellHorizontalGrouping;
0035     int m_cellVerticalGrouping;
0036 
0037     double m_thinLineWidth;
0038     double m_thickLineWidth;
0039 
0040     QColor m_thinLineColor;
0041     QColor m_thickLineColor;
0042 
0043     Configuration::EnumRenderer_RenderStitchesAs::type m_renderStitchesAs;
0044     Configuration::EnumRenderer_RenderBackstitchesAs::type m_renderBackstitchesAs;
0045     Configuration::EnumRenderer_RenderKnotsAs::type m_renderKnotsAs;
0046 
0047     QPainter *m_painter;
0048 
0049     Document *m_document;
0050     Pattern *m_pattern;
0051     SymbolLibrary *m_symbolLibrary;
0052 
0053     int m_highlight;
0054 
0055     QPointF m_topLeft;
0056     QPointF m_topRight;
0057     QPointF m_bottomLeft;
0058     QPointF m_bottomRight;
0059     QPointF m_center;
0060     QPointF m_centerTop;
0061     QPointF m_centerLeft;
0062     QPointF m_centerRight;
0063     QPointF m_centerBottom;
0064 
0065     QRectF m_renderCell;
0066     QRectF m_renderTLCell;
0067     QRectF m_renderTL3Cell;
0068     QRectF m_renderTRCell;
0069     QRectF m_renderTR3Cell;
0070     QRectF m_renderBLCell;
0071     QRectF m_renderBL3Cell;
0072     QRectF m_renderBRCell;
0073     QRectF m_renderBR3Cell;
0074 
0075     QPolygonF m_renderTLQ;
0076     QPolygonF m_renderTRQ;
0077     QPolygonF m_renderBLQ;
0078     QPolygonF m_renderBRQ;
0079 
0080     QPolygonF m_renderBLTRH;
0081     QPolygonF m_renderTLBRH;
0082 
0083     QPolygonF m_renderTL3Q;
0084     QPolygonF m_renderTR3Q;
0085     QPolygonF m_renderBL3Q;
0086     QPolygonF m_renderBR3Q;
0087 };
0088 
0089 RendererData::RendererData()
0090     : QSharedData()
0091     , m_cellHorizontalGrouping(Configuration::editor_CellHorizontalGrouping())
0092     , m_cellVerticalGrouping(Configuration::editor_CellVerticalGrouping())
0093     , m_thinLineColor(Configuration::editor_ThinLineColor())
0094     , m_thickLineColor(Configuration::editor_ThickLineColor())
0095     , m_renderStitchesAs(Configuration::renderer_RenderStitchesAs())
0096     , m_renderBackstitchesAs(Configuration::renderer_RenderBackstitchesAs())
0097     , m_renderKnotsAs(Configuration::renderer_RenderKnotsAs())
0098     , m_painter(nullptr)
0099     , m_document(nullptr)
0100     , m_pattern(nullptr)
0101     , m_symbolLibrary(nullptr)
0102 {
0103     m_topLeft = QPointF(0.0, 0.0);
0104     m_topRight = QPointF(1.0, 0.0);
0105     m_bottomLeft = QPointF(0.0, 1.0);
0106     m_bottomRight = QPointF(1.0, 1.0);
0107     m_center = QPointF(0.5, 0.5);
0108     m_centerTop = QPointF(0.5, 0.0);
0109     m_centerLeft = QPointF(0.0, 0.5);
0110     m_centerRight = QPointF(1.0, 0.5);
0111     m_centerBottom = QPointF(0.5, 1.0);
0112 
0113     double oneThird = 1.0 / 3.0;
0114     double twoThird = 2.0 / 3.0;
0115 
0116     m_renderCell = QRectF(m_topLeft, m_bottomRight);
0117     m_renderTLCell = QRectF(m_topLeft, m_center);
0118     m_renderTL3Cell = QRectF(m_topLeft, QSize(twoThird, twoThird));
0119     m_renderTRCell = QRectF(m_centerTop, m_centerRight);
0120     m_renderTR3Cell = QRectF(oneThird, 0, twoThird, twoThird);
0121     m_renderBLCell = QRectF(m_centerLeft, m_centerBottom);
0122     m_renderBL3Cell = QRectF(0, oneThird, twoThird, twoThird);
0123     m_renderBRCell = QRectF(m_center, m_bottomRight);
0124     m_renderBR3Cell = QRectF(oneThird, oneThird, twoThird, twoThird);
0125 
0126     m_renderTLQ << m_topLeft << m_centerTop << m_centerLeft;
0127     m_renderTRQ << m_centerTop << m_topRight << m_centerRight;
0128     m_renderBLQ << m_centerLeft << m_centerBottom << m_bottomLeft;
0129     m_renderBRQ << m_centerRight << m_bottomRight << m_centerBottom;
0130     m_renderBLTRH << m_bottomLeft << m_centerLeft << m_centerTop << m_topRight << m_centerRight << m_centerBottom;
0131     m_renderTLBRH << m_topLeft << m_centerTop << m_centerRight << m_bottomRight << m_centerBottom << m_centerLeft;
0132     m_renderTL3Q << m_topLeft << m_topRight << m_centerRight << m_centerBottom << m_bottomLeft;
0133     m_renderTR3Q << m_topLeft << m_topRight << m_bottomRight << m_centerBottom << m_centerLeft;
0134     m_renderBL3Q << m_topLeft << m_centerTop << m_centerRight << m_bottomRight << m_bottomLeft;
0135     m_renderBR3Q << m_centerTop << m_topRight << m_bottomRight << m_bottomLeft << m_centerLeft;
0136 }
0137 
0138 RendererData::RendererData(const RendererData &other)
0139     : QSharedData(other)
0140     , m_cellHorizontalGrouping(other.m_cellHorizontalGrouping)
0141     , m_cellVerticalGrouping(other.m_cellVerticalGrouping)
0142     , m_thinLineWidth(other.m_thinLineWidth)
0143     , m_thickLineWidth(other.m_thickLineWidth)
0144     , m_thinLineColor(other.m_thinLineColor)
0145     , m_thickLineColor(other.m_thickLineColor)
0146     , m_renderStitchesAs(other.m_renderStitchesAs)
0147     , m_renderBackstitchesAs(other.m_renderBackstitchesAs)
0148     , m_renderKnotsAs(other.m_renderKnotsAs)
0149     , m_document(other.m_document)
0150     , m_pattern(other.m_pattern)
0151     , m_symbolLibrary(other.m_symbolLibrary)
0152     , m_topLeft(other.m_topLeft)
0153     , m_topRight(other.m_topRight)
0154     , m_bottomLeft(other.m_bottomLeft)
0155     , m_bottomRight(other.m_bottomRight)
0156     , m_center(other.m_center)
0157     , m_renderCell(other.m_renderCell)
0158     , m_renderTLCell(other.m_renderTLCell)
0159     , m_renderTL3Cell(other.m_renderTL3Cell)
0160     , m_renderTRCell(other.m_renderTRCell)
0161     , m_renderTR3Cell(other.m_renderTR3Cell)
0162     , m_renderBLCell(other.m_renderBLCell)
0163     , m_renderBL3Cell(other.m_renderBL3Cell)
0164     , m_renderBRCell(other.m_renderBRCell)
0165     , m_renderBR3Cell(other.m_renderBR3Cell)
0166     , m_renderTLQ(other.m_renderTLQ)
0167     , m_renderTRQ(other.m_renderTRQ)
0168     , m_renderBLQ(other.m_renderBLQ)
0169     , m_renderBRQ(other.m_renderBRQ)
0170     , m_renderBLTRH(other.m_renderBLTRH)
0171     , m_renderTLBRH(other.m_renderTLBRH)
0172     , m_renderTL3Q(other.m_renderTL3Q)
0173     , m_renderTR3Q(other.m_renderTR3Q)
0174     , m_renderBL3Q(other.m_renderBL3Q)
0175     , m_renderBR3Q(other.m_renderBR3Q)
0176 {
0177 }
0178 
0179 const Renderer::renderStitchCallPointer Renderer::renderStitchCallPointers[] = {
0180     &Renderer::renderStitchesAsStitches,
0181     &Renderer::renderStitchesAsBlackWhiteSymbols,
0182     &Renderer::renderStitchesAsColorSymbols,
0183     &Renderer::renderStitchesAsColorBlocks,
0184     &Renderer::renderStitchesAsColorBlocksSymbols,
0185 };
0186 
0187 const Renderer::renderBackstitchCallPointer Renderer::renderBackstitchCallPointers[] = {
0188     &Renderer::renderBackstitchesAsColorLines,
0189     &Renderer::renderBackstitchesAsBlackWhiteSymbols,
0190 };
0191 
0192 const Renderer::renderKnotCallPointer Renderer::renderKnotCallPointers[] = {
0193     &Renderer::renderKnotsAsColorBlocks,
0194     &Renderer::renderKnotsAsColorBlocksSymbols,
0195     &Renderer::renderKnotsAsColorSymbols,
0196     &Renderer::renderKnotsAsBlackWhiteSymbols,
0197 };
0198 
0199 Renderer::Renderer()
0200     : d(new RendererData)
0201 {
0202     setGridLineWidths(Configuration::editor_ThinLineWidth(), Configuration::editor_ThickLineWidth());
0203 }
0204 
0205 Renderer::Renderer(const Renderer &other)
0206     : d(other.d)
0207 {
0208 }
0209 
0210 Renderer::~Renderer()
0211 {
0212 }
0213 
0214 void Renderer::setCellGrouping(int cellHorizontalGrouping, int cellVerticalGrouping)
0215 {
0216     d->m_cellHorizontalGrouping = cellHorizontalGrouping;
0217     d->m_cellVerticalGrouping = cellVerticalGrouping;
0218 }
0219 
0220 void Renderer::setGridLineWidths(double thinLineWidth, double thickLineWidth)
0221 {
0222     thinLineWidth /= 100;
0223     thickLineWidth /= 100;
0224 
0225     if (thinLineWidth == 0.0) {
0226         thinLineWidth = 0.025;
0227     }
0228 
0229     if (thickLineWidth == 0.0) {
0230         thickLineWidth = 0.15;
0231     }
0232 
0233     d->m_thinLineWidth = thinLineWidth;
0234     d->m_thickLineWidth = thickLineWidth;
0235 }
0236 
0237 void Renderer::setGridLineColors(QColor thinLineColor, QColor thickLineColor)
0238 {
0239     d->m_thinLineColor = thinLineColor;
0240     d->m_thickLineColor = thickLineColor;
0241 }
0242 
0243 void Renderer::setRenderStitchesAs(Configuration::EnumRenderer_RenderStitchesAs::type renderStitchesAs)
0244 {
0245     d->m_renderStitchesAs = renderStitchesAs;
0246 }
0247 
0248 void Renderer::setRenderBackstitchesAs(Configuration::EnumRenderer_RenderBackstitchesAs::type renderBackstitchesAs)
0249 {
0250     d->m_renderBackstitchesAs = renderBackstitchesAs;
0251 }
0252 
0253 void Renderer::setRenderKnotsAs(Configuration::EnumRenderer_RenderKnotsAs::type renderKnotsAs)
0254 {
0255     d->m_renderKnotsAs = renderKnotsAs;
0256 }
0257 
0258 void Renderer::render(QPainter *painter,
0259                       Pattern *pattern,
0260                       QRect updateCells,
0261                       bool renderGrid,
0262                       bool renderStitches,
0263                       bool renderBackstitches,
0264                       bool renderKnots,
0265                       int colorHighlight)
0266 {
0267     updateCells &= painter->window();
0268 
0269     painter->save();
0270 
0271     d->m_painter = painter;
0272     d->m_pattern = pattern;
0273     d->m_symbolLibrary = SymbolManager::library(pattern->palette().symbolLibrary());
0274     d->m_highlight = colorHighlight;
0275 
0276     int patternLeft = updateCells.left();
0277     int patternRight = updateCells.right();
0278     int patternTop = updateCells.top();
0279     int patternBottom = updateCells.bottom();
0280     int patternWidth = updateCells.width();
0281     int patternHeight = updateCells.height();
0282 
0283     if (renderGrid) {
0284         QPen thickPen(d->m_thickLineColor);
0285         QPen thinPen(d->m_thinLineColor);
0286         thickPen.setWidthF(d->m_thickLineWidth);
0287         thinPen.setWidthF(d->m_thinLineWidth);
0288 
0289         for (int y = patternTop; y <= patternTop + patternHeight; ++y) {
0290             painter->setPen((y % d->m_cellVerticalGrouping) ? thinPen : thickPen);
0291             painter->drawLine(patternLeft, y, patternLeft + patternWidth, y);
0292         }
0293 
0294         for (int x = patternLeft; x <= patternLeft + patternWidth; ++x) {
0295             painter->setPen((x % d->m_cellHorizontalGrouping) ? thinPen : thickPen);
0296             painter->drawLine(x, patternTop, x, patternTop + patternHeight);
0297         }
0298     }
0299 
0300     if (renderStitches) {
0301         QTransform transform = painter->transform();
0302 
0303         for (int y = patternTop; y <= patternBottom; ++y) {
0304             for (int x = patternLeft; x <= patternRight; ++x) {
0305                 if (StitchQueue *queue = pattern->stitches().stitchQueueAt(QPoint(x, y))) {
0306                     painter->translate(x, y);
0307                     (this->*renderStitchCallPointers[d->m_renderStitchesAs])(queue);
0308                     painter->setTransform(transform);
0309                 }
0310             }
0311         }
0312     }
0313 
0314     if (renderBackstitches) {
0315         QList<Backstitch *> backstitches = pattern->stitches().backstitches();
0316 
0317         for (int i = 0; i < backstitches.count(); ++i) {
0318             (this->*renderBackstitchCallPointers[d->m_renderBackstitchesAs])(backstitches.at(i));
0319         }
0320     }
0321 
0322     if (renderKnots) {
0323         QList<Knot *> knots = pattern->stitches().knots();
0324 
0325         for (int i = 0; i < knots.count(); ++i) {
0326             (this->*renderKnotCallPointers[d->m_renderKnotsAs])(knots.at(i));
0327         }
0328     }
0329 
0330     painter->restore();
0331 }
0332 
0333 void Renderer::renderStitchesAsStitches(StitchQueue *stitchQueue)
0334 {
0335     QPen pen(Qt::lightGray, 0, Qt::SolidLine, Qt::RoundCap);
0336 
0337     int i = stitchQueue->count();
0338 
0339     while (i) {
0340         Stitch *stitch = stitchQueue->at(--i);
0341         DocumentFloss *documentFloss = d->m_pattern->palette().flosses().value(stitch->colorIndex);
0342 
0343         if ((d->m_highlight == -1) || (stitch->colorIndex == d->m_highlight)) {
0344             pen.setColor(documentFloss->flossColor());
0345             pen.setWidthF(documentFloss->stitchStrands() / 10.0);
0346         } else {
0347             pen.setColor(Qt::lightGray);
0348             pen.setWidthF(0);
0349         }
0350 
0351         d->m_painter->setPen(pen);
0352 
0353         switch (stitch->type) {
0354         case Stitch::Delete:
0355             break;
0356 
0357         case Stitch::TLQtr:
0358             d->m_painter->drawLine(d->m_topLeft, d->m_center);
0359             break;
0360 
0361         case Stitch::TRQtr:
0362             d->m_painter->drawLine(d->m_topRight, d->m_center);
0363             break;
0364 
0365         case Stitch::BLQtr:
0366             d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0367             break;
0368 
0369         case Stitch::BTHalf:
0370             d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0371             break;
0372 
0373         case Stitch::TL3Qtr:
0374             d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0375             d->m_painter->drawLine(d->m_topLeft, d->m_center);
0376             break;
0377 
0378         case Stitch::BRQtr:
0379             d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0380             break;
0381 
0382         case Stitch::TBHalf:
0383             d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0384             break;
0385 
0386         case Stitch::TR3Qtr:
0387             d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0388             d->m_painter->drawLine(d->m_topRight, d->m_center);
0389             break;
0390 
0391         case Stitch::BL3Qtr:
0392             d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0393             d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0394             break;
0395 
0396         case Stitch::BR3Qtr:
0397             d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0398             d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0399             break;
0400 
0401         case Stitch::Full:
0402             d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0403             d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0404             break;
0405 
0406         case Stitch::TLSmallHalf:
0407             d->m_painter->drawLine(d->m_centerLeft, d->m_centerTop);
0408             break;
0409 
0410         case Stitch::TRSmallHalf:
0411             d->m_painter->drawLine(d->m_centerTop, d->m_centerRight);
0412             break;
0413 
0414         case Stitch::BLSmallHalf:
0415             d->m_painter->drawLine(d->m_centerLeft, d->m_centerBottom);
0416             break;
0417 
0418         case Stitch::BRSmallHalf:
0419             d->m_painter->drawLine(d->m_centerBottom, d->m_centerRight);
0420             break;
0421 
0422         case Stitch::TLSmallFull:
0423             d->m_painter->drawLine(d->m_topLeft, d->m_center);
0424             d->m_painter->drawLine(d->m_centerLeft, d->m_centerTop);
0425             break;
0426 
0427         case Stitch::TRSmallFull:
0428             d->m_painter->drawLine(d->m_centerTop, d->m_centerRight);
0429             d->m_painter->drawLine(d->m_center, d->m_topRight);
0430             break;
0431 
0432         case Stitch::BLSmallFull:
0433             d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0434             d->m_painter->drawLine(d->m_centerLeft, d->m_centerBottom);
0435             break;
0436 
0437         case Stitch::BRSmallFull:
0438             d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0439             d->m_painter->drawLine(d->m_centerBottom, d->m_centerRight);
0440             break;
0441 
0442         case Stitch::FrenchKnot:
0443             break;
0444         }
0445     }
0446 }
0447 
0448 void Renderer::renderStitchesAsBlackWhiteSymbols(StitchQueue *stitchQueue)
0449 {
0450     int i = stitchQueue->count();
0451 
0452     while (i) {
0453         Stitch *stitch = stitchQueue->at(--i);
0454         DocumentFloss *documentFloss = d->m_pattern->palette().flosses().value(stitch->colorIndex);
0455         Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0456 
0457         QPen symbolPen = symbol.pen();
0458         QBrush symbolBrush = symbol.brush();
0459 
0460         if ((d->m_highlight == -1) || (stitch->colorIndex == d->m_highlight)) {
0461             // the symbolPen and symbolBrush are already set up as black at this point
0462         } else {
0463             symbolPen.setColor(Qt::lightGray);
0464             symbolBrush.setColor(Qt::lightGray);
0465         }
0466 
0467         d->m_painter->setPen(symbolPen);
0468         d->m_painter->setBrush(symbolBrush);
0469 
0470         d->m_painter->drawPath(symbol.path(stitch->type));
0471 
0472         if (Configuration::renderer_RenderStitchHints()) {
0473             renderStitchHints(stitch);
0474         }
0475     }
0476 }
0477 
0478 void Renderer::renderStitchesAsColorSymbols(StitchQueue *stitchQueue)
0479 {
0480     int i = stitchQueue->count();
0481 
0482     while (i) {
0483         Stitch *stitch = stitchQueue->at(--i);
0484         DocumentFloss *documentFloss = d->m_pattern->palette().flosses().value(stitch->colorIndex);
0485         Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0486 
0487         QPen symbolPen = symbol.pen();
0488         QBrush symbolBrush = symbol.brush();
0489 
0490         if ((d->m_highlight == -1) || (stitch->colorIndex == d->m_highlight)) {
0491             symbolPen.setColor(documentFloss->flossColor());
0492             symbolBrush.setColor(documentFloss->flossColor());
0493         } else {
0494             symbolPen.setColor(Qt::lightGray);
0495             symbolBrush.setColor(Qt::lightGray);
0496         }
0497 
0498         d->m_painter->setPen(symbolPen);
0499         d->m_painter->setBrush(symbolBrush);
0500 
0501         d->m_painter->drawPath(symbol.path(stitch->type));
0502 
0503         if (Configuration::renderer_RenderStitchHints()) {
0504             renderStitchHints(stitch);
0505         }
0506     }
0507 }
0508 
0509 void Renderer::renderStitchesAsColorBlocks(StitchQueue *stitchQueue)
0510 {
0511     QBrush blockBrush(Qt::SolidPattern);
0512 
0513     int i = stitchQueue->count();
0514 
0515     while (i) {
0516         Stitch *stitch = stitchQueue->at(--i);
0517         DocumentFloss *documentFloss = d->m_pattern->palette().flosses().value(stitch->colorIndex);
0518 
0519         if ((d->m_highlight == -1) || (stitch->colorIndex == d->m_highlight)) {
0520             blockBrush.setColor(documentFloss->flossColor());
0521         } else {
0522             blockBrush.setColor(Qt::lightGray);
0523         }
0524 
0525         d->m_painter->setPen(Qt::NoPen);
0526         d->m_painter->setBrush(blockBrush);
0527 
0528         switch (stitch->type) {
0529         case Stitch::Delete:
0530             break;
0531 
0532         case Stitch::TLQtr:
0533             d->m_painter->drawPolygon(d->m_renderTLQ);
0534             break;
0535 
0536         case Stitch::TRQtr:
0537             d->m_painter->drawPolygon(d->m_renderTRQ);
0538             break;
0539 
0540         case Stitch::BLQtr:
0541             d->m_painter->drawPolygon(d->m_renderBLQ);
0542             break;
0543 
0544         case Stitch::BTHalf:
0545             d->m_painter->drawPolygon(d->m_renderBLTRH);
0546             break;
0547 
0548         case Stitch::TL3Qtr:
0549             d->m_painter->drawPolygon(d->m_renderTL3Q);
0550             break;
0551 
0552         case Stitch::BRQtr:
0553             d->m_painter->drawPolygon(d->m_renderBRQ);
0554             break;
0555 
0556         case Stitch::TBHalf:
0557             d->m_painter->drawPolygon(d->m_renderTLBRH);
0558             break;
0559 
0560         case Stitch::TR3Qtr:
0561             d->m_painter->drawPolygon(d->m_renderTR3Q);
0562             break;
0563 
0564         case Stitch::BL3Qtr:
0565             d->m_painter->drawPolygon(d->m_renderBL3Q);
0566             break;
0567 
0568         case Stitch::BR3Qtr:
0569             d->m_painter->drawPolygon(d->m_renderBR3Q);
0570             break;
0571 
0572         case Stitch::Full:
0573             d->m_painter->fillRect(d->m_renderCell, blockBrush);
0574             break;
0575 
0576         case Stitch::TLSmallHalf:
0577             d->m_painter->fillRect(d->m_renderTLCell, blockBrush);
0578             break;
0579 
0580         case Stitch::TRSmallHalf:
0581             d->m_painter->fillRect(d->m_renderTRCell, blockBrush);
0582             break;
0583 
0584         case Stitch::BLSmallHalf:
0585             d->m_painter->fillRect(d->m_renderBLCell, blockBrush);
0586             break;
0587 
0588         case Stitch::BRSmallHalf:
0589             d->m_painter->fillRect(d->m_renderBRCell, blockBrush);
0590             break;
0591 
0592         case Stitch::TLSmallFull:
0593             d->m_painter->fillRect(d->m_renderTLCell, blockBrush);
0594             break;
0595 
0596         case Stitch::TRSmallFull:
0597             d->m_painter->fillRect(d->m_renderTRCell, blockBrush);
0598             break;
0599 
0600         case Stitch::BLSmallFull:
0601             d->m_painter->fillRect(d->m_renderBLCell, blockBrush);
0602             break;
0603 
0604         case Stitch::BRSmallFull:
0605             d->m_painter->fillRect(d->m_renderBRCell, blockBrush);
0606             break;
0607 
0608         case Stitch::FrenchKnot:
0609             break;
0610         }
0611 
0612         if (Configuration::renderer_RenderStitchHints()) {
0613             renderStitchHints(stitch);
0614         }
0615     }
0616 }
0617 
0618 void Renderer::renderStitchesAsColorBlocksSymbols(StitchQueue *stitchQueue)
0619 {
0620     QBrush blockBrush(Qt::SolidPattern);
0621 
0622     int i = stitchQueue->count();
0623 
0624     while (i) {
0625         Stitch *stitch = stitchQueue->at(--i);
0626         DocumentFloss *documentFloss = d->m_pattern->palette().flosses().value(stitch->colorIndex);
0627         Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0628 
0629         QPen symbolPen = symbol.pen();
0630         QBrush symbolBrush = symbol.brush();
0631 
0632         if ((d->m_highlight == -1) || (stitch->colorIndex == d->m_highlight)) {
0633             QColor flossColor = documentFloss->flossColor();
0634             QColor symbolColor = (qGray(flossColor.rgb()) < 128) ? Qt::white : Qt::black;
0635             symbolPen.setColor(symbolColor);
0636             symbolBrush.setColor(symbolColor);
0637             blockBrush.setColor(flossColor);
0638         } else {
0639             symbolPen.setColor(Qt::darkGray);
0640             symbolBrush.setColor(Qt::darkGray);
0641             blockBrush.setColor(Qt::lightGray);
0642         }
0643 
0644         d->m_painter->setPen(Qt::NoPen);
0645         d->m_painter->setBrush(blockBrush);
0646 
0647         switch (stitch->type) {
0648         case Stitch::Delete:
0649             break;
0650 
0651         case Stitch::TLQtr:
0652             d->m_painter->drawPolygon(d->m_renderTLQ);
0653             break;
0654 
0655         case Stitch::TRQtr:
0656             d->m_painter->drawPolygon(d->m_renderTRQ);
0657             break;
0658 
0659         case Stitch::BLQtr:
0660             d->m_painter->drawPolygon(d->m_renderBLQ);
0661             break;
0662 
0663         case Stitch::BTHalf:
0664             d->m_painter->drawPolygon(d->m_renderBLTRH);
0665             break;
0666 
0667         case Stitch::TL3Qtr:
0668             d->m_painter->drawPolygon(d->m_renderTL3Q);
0669             break;
0670 
0671         case Stitch::BRQtr:
0672             d->m_painter->drawPolygon(d->m_renderBRQ);
0673             break;
0674 
0675         case Stitch::TBHalf:
0676             d->m_painter->drawPolygon(d->m_renderTLBRH);
0677             break;
0678 
0679         case Stitch::TR3Qtr:
0680             d->m_painter->drawPolygon(d->m_renderTR3Q);
0681             break;
0682 
0683         case Stitch::BL3Qtr:
0684             d->m_painter->drawPolygon(d->m_renderBL3Q);
0685             break;
0686 
0687         case Stitch::BR3Qtr:
0688             d->m_painter->drawPolygon(d->m_renderBR3Q);
0689             break;
0690 
0691         case Stitch::Full:
0692             d->m_painter->fillRect(d->m_renderCell, blockBrush);
0693             break;
0694 
0695         case Stitch::TLSmallHalf:
0696             d->m_painter->fillRect(d->m_renderTLCell, blockBrush);
0697             break;
0698 
0699         case Stitch::TRSmallHalf:
0700             d->m_painter->fillRect(d->m_renderTRCell, blockBrush);
0701             break;
0702 
0703         case Stitch::BLSmallHalf:
0704             d->m_painter->fillRect(d->m_renderBLCell, blockBrush);
0705             break;
0706 
0707         case Stitch::BRSmallHalf:
0708             d->m_painter->fillRect(d->m_renderBRCell, blockBrush);
0709             break;
0710 
0711         case Stitch::TLSmallFull:
0712             d->m_painter->fillRect(d->m_renderTLCell, blockBrush);
0713             break;
0714 
0715         case Stitch::TRSmallFull:
0716             d->m_painter->fillRect(d->m_renderTRCell, blockBrush);
0717             break;
0718 
0719         case Stitch::BLSmallFull:
0720             d->m_painter->fillRect(d->m_renderBLCell, blockBrush);
0721             break;
0722 
0723         case Stitch::BRSmallFull:
0724             d->m_painter->fillRect(d->m_renderBRCell, blockBrush);
0725             break;
0726 
0727         case Stitch::FrenchKnot:
0728             break;
0729         }
0730 
0731         d->m_painter->setPen(symbolPen);
0732         d->m_painter->setBrush(symbolBrush);
0733 
0734         d->m_painter->drawPath(symbol.path(stitch->type));
0735 
0736         if (Configuration::renderer_RenderStitchHints()) {
0737             renderStitchHints(stitch);
0738         }
0739     }
0740 }
0741 
0742 void Renderer::renderStitchHints(Stitch *stitch)
0743 {
0744     d->m_painter->setPen(QPen(Qt::lightGray, 0));
0745 
0746     switch (stitch->type) {
0747     case Stitch::Delete:
0748         break;
0749 
0750     case Stitch::TLQtr:
0751         d->m_painter->drawLine(d->m_topLeft, d->m_center);
0752         break;
0753 
0754     case Stitch::TRQtr:
0755         d->m_painter->drawLine(d->m_center, d->m_topRight);
0756         break;
0757 
0758     case Stitch::BLQtr:
0759         d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0760         break;
0761 
0762     case Stitch::BTHalf:
0763         d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0764         break;
0765 
0766     case Stitch::TL3Qtr:
0767         d->m_painter->drawLine(d->m_topRight, d->m_bottomLeft);
0768         d->m_painter->drawLine(d->m_topLeft, d->m_center);
0769         break;
0770 
0771     case Stitch::BRQtr:
0772         d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0773         break;
0774 
0775     case Stitch::TBHalf:
0776         d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0777         break;
0778 
0779     case Stitch::TR3Qtr:
0780         d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0781         d->m_painter->drawLine(d->m_topRight, d->m_center);
0782         break;
0783 
0784     case Stitch::BL3Qtr:
0785         d->m_painter->drawLine(d->m_topLeft, d->m_bottomRight);
0786         d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0787         break;
0788 
0789     case Stitch::BR3Qtr:
0790         d->m_painter->drawLine(d->m_bottomLeft, d->m_topRight);
0791         d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0792         break;
0793 
0794     case Stitch::Full:
0795         break;
0796 
0797     case Stitch::TLSmallHalf:
0798         d->m_painter->drawLine(d->m_centerLeft, d->m_centerTop);
0799         break;
0800 
0801     case Stitch::TRSmallHalf:
0802         d->m_painter->drawLine(d->m_centerTop, d->m_centerRight);
0803         break;
0804 
0805     case Stitch::BLSmallHalf:
0806         d->m_painter->drawLine(d->m_centerLeft, d->m_centerBottom);
0807         break;
0808 
0809     case Stitch::BRSmallHalf:
0810         d->m_painter->drawLine(d->m_centerBottom, d->m_centerRight);
0811         break;
0812 
0813     case Stitch::TLSmallFull:
0814         d->m_painter->drawLine(d->m_topLeft, d->m_center);
0815         d->m_painter->drawLine(d->m_centerTop, d->m_centerLeft);
0816         break;
0817 
0818     case Stitch::TRSmallFull:
0819         d->m_painter->drawLine(d->m_centerTop, d->m_centerRight);
0820         d->m_painter->drawLine(d->m_center, d->m_topRight);
0821         break;
0822 
0823     case Stitch::BLSmallFull:
0824         d->m_painter->drawLine(d->m_centerLeft, d->m_centerBottom);
0825         d->m_painter->drawLine(d->m_bottomLeft, d->m_center);
0826         break;
0827 
0828     case Stitch::BRSmallFull:
0829         d->m_painter->drawLine(d->m_center, d->m_bottomRight);
0830         d->m_painter->drawLine(d->m_centerRight, d->m_centerBottom);
0831         break;
0832 
0833     case Stitch::FrenchKnot:
0834         break;
0835     }
0836 }
0837 
0838 void Renderer::renderBackstitchesAsColorLines(Backstitch *backstitch)
0839 {
0840     QPointF start(QPointF(backstitch->start) / 2);
0841     QPointF end(QPointF(backstitch->end) / 2);
0842 
0843     DocumentFloss *documentFloss = d->m_pattern->palette().floss(backstitch->colorIndex);
0844 
0845     QPen pen;
0846 
0847     if ((d->m_highlight == -1) || (backstitch->colorIndex == d->m_highlight)) {
0848         pen.setColor(documentFloss->flossColor());
0849         pen.setWidthF(double(documentFloss->backstitchStrands()) / 5);
0850         pen.setCapStyle(Qt::RoundCap);
0851     } else {
0852         pen.setColor(Qt::lightGray);
0853         pen.setWidth(0);
0854     }
0855 
0856     d->m_painter->setPen(pen);
0857     d->m_painter->drawLine(start, end);
0858 }
0859 
0860 void Renderer::renderBackstitchesAsBlackWhiteSymbols(Backstitch *backstitch)
0861 {
0862     QPointF start(QPointF(backstitch->start) / 2);
0863     QPointF end(QPointF(backstitch->end) / 2);
0864 
0865     DocumentFloss *documentFloss = d->m_pattern->palette().floss(backstitch->colorIndex);
0866 
0867     QPen pen;
0868     pen.setStyle(documentFloss->backstitchSymbol());
0869 
0870     if ((d->m_highlight == -1) || (backstitch->colorIndex == d->m_highlight)) {
0871         pen.setColor(Qt::black);
0872         pen.setWidthF(double(documentFloss->backstitchStrands()) / 5);
0873         pen.setCapStyle(Qt::RoundCap);
0874     } else {
0875         pen.setColor(Qt::lightGray);
0876         pen.setWidth(0);
0877     }
0878 
0879     d->m_painter->setPen(pen);
0880     d->m_painter->drawLine(start, end);
0881 }
0882 
0883 void Renderer::renderKnotsAsColorBlocks(Knot *knot)
0884 {
0885     DocumentFloss *documentFloss = d->m_pattern->palette().floss(knot->colorIndex);
0886 
0887     QBrush brush(Qt::SolidPattern);
0888 
0889     if ((d->m_highlight == -1) || (knot->colorIndex == d->m_highlight)) {
0890         brush.setColor(documentFloss->flossColor());
0891     } else {
0892         brush.setColor(Qt::lightGray);
0893     }
0894 
0895     d->m_painter->setPen(QPen(Qt::NoPen));
0896     d->m_painter->setBrush(brush);
0897 
0898     QRectF rect(0, 0, 0.75, 0.75);
0899     rect.moveCenter(QPointF(knot->position) / 2);
0900 
0901     d->m_painter->drawEllipse(rect);
0902 }
0903 
0904 void Renderer::renderKnotsAsColorBlocksSymbols(Knot *knot)
0905 {
0906     DocumentFloss *documentFloss = d->m_pattern->palette().floss(knot->colorIndex);
0907     Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0908 
0909     QPen symbolPen = symbol.pen();
0910     QBrush symbolBrush = symbol.brush();
0911 
0912     QBrush blockBrush(Qt::SolidPattern);
0913 
0914     if ((d->m_highlight == -1) || (knot->colorIndex == d->m_highlight)) {
0915         QColor flossColor = documentFloss->flossColor();
0916         QColor symbolColor = (qGray(flossColor.rgb()) < 128) ? Qt::white : Qt::black;
0917         symbolPen.setColor(symbolColor);
0918         symbolBrush.setColor(symbolColor);
0919         blockBrush.setColor(flossColor);
0920     } else {
0921         symbolPen.setColor(Qt::darkGray);
0922         symbolBrush.setColor(Qt::darkGray);
0923         blockBrush.setColor(Qt::lightGray);
0924     }
0925 
0926     d->m_painter->setPen(QPen(Qt::NoPen));
0927     d->m_painter->setBrush(blockBrush);
0928 
0929     QRectF rect(0, 0, 0.75, 0.75);
0930     rect.moveCenter(QPointF(knot->position) / 2);
0931 
0932     d->m_painter->drawEllipse(rect);
0933     d->m_painter->setPen(symbolPen);
0934     d->m_painter->setBrush(symbolBrush);
0935     d->m_painter->drawPath(symbol.path(Stitch::FrenchKnot).translated(QPointF(knot->position) / 2 - QPointF(0.5, 0.5)));
0936 }
0937 
0938 void Renderer::renderKnotsAsColorSymbols(Knot *knot)
0939 {
0940     DocumentFloss *documentFloss = d->m_pattern->palette().floss(knot->colorIndex);
0941     Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0942 
0943     QPen outlinePen(Qt::lightGray, 0);
0944 
0945     QPen symbolPen = symbol.pen();
0946     QBrush symbolBrush = symbol.brush();
0947 
0948     if ((d->m_highlight == -1) || (knot->colorIndex == d->m_highlight)) {
0949         QColor flossColor = documentFloss->flossColor();
0950         symbolPen.setColor(flossColor);
0951         symbolBrush.setColor(flossColor);
0952         outlinePen.setColor(flossColor);
0953     } else {
0954         symbolPen.setColor(Qt::lightGray);
0955         symbolBrush.setColor(Qt::lightGray);
0956     }
0957 
0958     d->m_painter->setPen(outlinePen);
0959     d->m_painter->setBrush(Qt::NoBrush);
0960 
0961     QRectF rect(0, 0, 0.75, 0.75);
0962     rect.moveCenter(QPointF(knot->position) / 2);
0963 
0964     d->m_painter->drawEllipse(rect);
0965 
0966     d->m_painter->setPen(symbolPen);
0967     d->m_painter->setBrush(symbolBrush);
0968     d->m_painter->drawPath(symbol.path(Stitch::FrenchKnot).translated(QPointF(knot->position) / 2 - QPointF(0.5, 0.5)));
0969 }
0970 
0971 void Renderer::renderKnotsAsBlackWhiteSymbols(Knot *knot)
0972 {
0973     DocumentFloss *documentFloss = d->m_pattern->palette().floss(knot->colorIndex);
0974     Symbol symbol = d->m_symbolLibrary->symbol(documentFloss->stitchSymbol());
0975 
0976     QPen outlinePen(Qt::lightGray, 0);
0977 
0978     QPen symbolPen = symbol.pen();
0979     QBrush symbolBrush = symbol.brush();
0980 
0981     if ((d->m_highlight == -1) || (knot->colorIndex == d->m_highlight)) {
0982         symbolPen.setColor(Qt::black);
0983         symbolBrush.setColor(Qt::black);
0984         outlinePen.setColor(Qt::black);
0985     } else {
0986         symbolPen.setColor(Qt::lightGray);
0987         symbolBrush.setColor(Qt::lightGray);
0988     }
0989 
0990     d->m_painter->setPen(outlinePen);
0991     d->m_painter->setBrush(Qt::NoBrush);
0992 
0993     QRectF rect(0, 0, 0.75, 0.75);
0994     rect.moveCenter(QPointF(knot->position) / 2);
0995 
0996     d->m_painter->drawEllipse(rect);
0997 
0998     d->m_painter->setPen(symbolPen);
0999     d->m_painter->setBrush(symbolBrush);
1000     d->m_painter->drawPath(symbol.path(Stitch::FrenchKnot).translated(QPointF(knot->position) / 2 - QPointF(0.5, 0.5)));
1001 }
1002 
1003 Renderer &Renderer::operator=(const Renderer &other)
1004 {
1005     d = other.d;
1006     return *this;
1007 }