// **************************************************************************** // // Function Name: RWindowView::RWindowView( ) // // Description: Render this views background // // Returns: Nothing // // Exceptions: None // // **************************************************************************** // void RWindowView::RenderBackground( RDrawingSurface& drawingSurface, const R2dTransform&, const RIntRect& rcRender ) const { // Fill in the background if( !drawingSurface.IsPrinting( ) ) { RColor backgroundColor = GetBackgroundColor( ); if ( backgroundColor.GetFillMethod() == RColor::kSolid ) { RSolidColor solid = backgroundColor.GetSolidColor( ); // Check for something close to TRUE GRAY and alter it slightly #ifdef _WINDOWS const YColorComponent kHitBits = 0xC0; const YColorComponent kNewColor = 0x77; const YColorComponent kGrayColor = 0x80; #elif defined( MAC ) const YColorComponent kHitBits = 0xF000; const YColorComponent kNewColor = 0x7777; const YColorComponent kGrayColor = 0x8000; #endif // _WINDOWS or MAC YColorComponent redColor = (solid.GetRed( ) & kHitBits); YColorComponent greenColor = (solid.GetGreen( ) & kHitBits); YColorComponent blueColor = (solid.GetBlue( ) & kHitBits); if ( (kGrayColor == redColor) && (redColor == greenColor) && (greenColor == blueColor) ) { backgroundColor = RSolidColor( kNewColor, kNewColor, kNewColor ); } } drawingSurface.SetForegroundMode( kNormal ); drawingSurface.SetFillColor( backgroundColor ); drawingSurface.FillRectangle( rcRender ); } }
HRESULT RPathOutlineAttribImp::SetColor( const RColor& crColor ) { if (RColor::kSolid != crColor.GetFillMethod()) return E_INVALIDARG; m_sOutlineFormat.m_yPenColor = crColor.GetSolidColor(); m_pPathDocument->InvalidateAllViews(); return S_OK; }
/** * Creates a color from the given CAD code (index 0...256). */ RColor RColor::createFromCadIndex(int code) { // special colors: if (code==0) { return RColor(RColor::ByBlock); } if (code==256) { return RColor(RColor::ByLayer); } // normal indexed colors: if (code>0 && code<256) { RColor c; c.setRgbF(cadColors[code][0], cadColors[code][1], cadColors[code][2]); return c; } return RColor(); }
QIcon RColor::getIcon(const RColor& color, const QSize& size) { init(); if (iconMap.contains(QPair<RColor, QPair<int, int> >(color, QPair<int, int>(size.width(), size.height())))) { return iconMap[QPair<RColor, QPair<int, int> >(color, QPair<int, int>(size.width(), size.height()))]; } RColor col = color; if (color.isByLayer() || color.isByBlock() || /*color == RColor(Qt::black, RColor::BlackWhite) ||*/ !color.isValid()) { col = Qt::white; } QImage img(size, QImage::Format_ARGB32_Premultiplied); img.fill(0); QPainter painter(&img); int w = img.width(); int h = img.height(); // painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(0, 0, w, h, col); if (!color.isValid()) { // icon for "Other colors..." QLinearGradient grad(0, 0, w, 0); grad.setColorAt(0, Qt::red); grad.setColorAt(0.33, Qt::yellow); grad.setColorAt(0.66, Qt::blue); grad.setColorAt(1, Qt::green); painter.fillRect(QRect(0, 0, w, h), grad); } /*else if (color == RColor(Qt::black, RColor::BlackWhite) || color == RColor(Qt::white, RColor::BlackWhite)) { // icon for black / white painter.setRenderHint(QPainter::Antialiasing); QPainterPath path; path.moveTo(0, 0); path.lineTo(w, 0); path.lineTo(w, h); painter.fillPath(path, Qt::black); painter.setRenderHint(QPainter::Antialiasing, false); }*/ else if (col.alpha() != 255) { // indicate alpha by an inset QBrush opaqueBrush = col; col.setAlpha(255); opaqueBrush.setColor(col); painter.fillRect(w / 4, h / 4, w / 2, h / 2, opaqueBrush); } painter.setPen(Qt::black); painter.drawRect(0, 0, w - 1, h - 1); painter.end(); QIcon ret(QPixmap::fromImage(img)); iconMap.insert(QPair<RColor, QPair<int, int> >(color, QPair<int, int>(size.width(), size.height())), ret); return ret; }
/** * Stream operator for QDebug */ QDebug operator<<(QDebug dbg, const RColor& c) { if (c.isValid()) { if (c.isByLayer()) { dbg.nospace() << "RColor(ByLayer)"; } else if (c.isByBlock()) { dbg.nospace() << "RColor(ByBlock)"; } else { dbg.nospace() << "RColor(RGBA: " << c.red() << ", " << c.green() << ", " << c.blue() << ", " << c.alpha() << ")"; } } else { dbg.nospace() << "RColor(invalid)"; } return dbg.space(); }
//**************************************************************************** // // Function Name: SetColor // // Description: Stores the current color for use in gradient option // determination, and then updates the gradient selections. // // Returns: None // // Exceptions: None // //**************************************************************************** void RColorDialog::SetColor( const RColor& crColor ) { if (RColor::kBitmap == crColor.GetFillMethod()) { if (m_dlgColorPhoto.IsColorPhoto( crColor )) { m_dlgColorPhoto.SetColor( crColor ); m_nStartPage = 2; } else { m_dlgColorTexture.SetColor( crColor ); m_nStartPage = 1; } } else { m_dlgColorPalette.SetColor( crColor ); m_nStartPage = 0; } }
void DisplayList::UpdateRect(SRECT* clip) { if ( bits->LockBits() ) { raster.Attach(bits, clip, antialias); raster.BeginPaint(); // Add the background edges REdge bkEdges[2]; RColor bkColor; if ( backgroundColor.all != 0 ) { // Set up the color bkColor.SetUp(&raster); bkColor.order = 0; bkColor.rgb.alpha = 255; bkColor.rgb.red = backgroundColor.rgb.red; bkColor.rgb.green = backgroundColor.rgb.green; bkColor.rgb.blue = backgroundColor.rgb.blue; bkColor.BuildCache(); // Set up the edges bkEdges[0].nextObj = &bkEdges[1]; bkEdges[1].nextObj = 0; SPOINT pt1, pt2; CURVE c; pt1.y = raster.edgeClip.ymin; pt2.y = raster.edgeClip.ymax; pt1.x = pt2.x = raster.edgeClip.xmin; CurveSetLine(&pt1, &pt2, &c); bkEdges[0].Set(&c); pt1.x = pt2.x = raster.edgeClip.xmax; CurveSetLine(&pt1, &pt2, &c); bkEdges[1].Set(&c); bkEdges[0].dir = bkEdges[1].dir = 0; bkEdges[0].fillRule = bkEdges[1].fillRule = fillEvenOddRule; bkEdges[0].color1 = bkEdges[1].color1 = &bkColor; bkEdges[0].color2 = bkEdges[1].color2 = 0; raster.AddEdges(bkEdges, &bkColor); } else { // It's transparent... raster.getBackground = true; } { // Add the object edges root.Draw(&raster, camera); } #ifndef DISABLE_TAB_FOCUS // Add button focus rectangle RColor yellow; REdge* edges = NULL; if (useFocusRect && !RectIsEmpty(&tabFocusRect)) { // Set up the color yellow.SetUp(&raster); yellow.order = 0; yellow.rgb.alpha = 255; yellow.rgb.red = 255; yellow.rgb.green = 255; yellow.rgb.blue = 0; yellow.BuildCache(); SRECT bounds = tabFocusRect; MATRIX mat; MatrixIdentity(&mat); int border = 3; if (antialias) { border *= 4; } SRECT rect = bounds; rect.xmax = bounds.xmin + border; AddRect(&rect, &mat, &yellow, this, &edges, NULL); rect.xmin = bounds.xmax - border; rect.xmax = bounds.xmax; AddRect(&rect, &mat, &yellow, this, &edges, NULL); rect.xmin = bounds.xmin; rect.ymax = bounds.ymin + border; AddRect(&rect, &mat, &yellow, this, &edges, NULL); rect.ymin = bounds.ymax - border; rect.ymax = bounds.ymax; AddRect(&rect, &mat, &yellow, this, &edges, NULL); raster.AddEdges(edges, &yellow); } #endif raster.PaintBits(); #ifndef DISABLE_TAB_FOCUS if (!RectIsEmpty(&tabFocusRect)) { // Free the edges REdge* e = edges; while ( e ) { REdge* next = e->nextObj; FreeEdge(e); e = next; } edges = 0; yellow.FreeCache(); } #endif if ( backgroundColor.all != 0 ) bkColor.FreeCache(); bits->UnlockBits(); } }
/** * Renders the text data into painter paths. */ void RTextRenderer::render() { boundingBox = RBox(); painterPaths.clear(); richText = ""; QString text = textData.getEscapedText(); //RVector position = textData.getPosition(); RVector position = textData.getAlignmentPoint(); double textHeight = textData.getTextHeight(); RS::VAlign verticalAlignment = textData.getVAlign(); RS::HAlign horizontalAlignment = textData.getHAlign(); double lineSpacingFactor = textData.getLineSpacingFactor(); QString fontName = textData.getFontName(); bool bold = textData.isBold(); bool italic = textData.isItalic(); double angle = textData.getAngle(); //RColor color = textData.getColor(true); // split up text where separation is required due to line feed, // or any type of height change (\P, \H[0-9]*.?[0-9]+;, \S*/*;) // split up text at every formatting change: QRegExp regExpAll(rxAll); QStringList literals = text.split(regExpAll); // collect formatting change information for every literal: QStringList formattings; int pos = 0; while ((pos = regExpAll.indexIn(text, pos)) != -1) { formattings << regExpAll.cap(1); pos += regExpAll.matchedLength(); } // x position in real units: double xCursor = 0.0; // y position for next text line: double yCursor = 0.0; // painter paths for current text line: QList<RPainterPath> linePaths; // max ascent of current text line: double maxAscent = 0.0; // max descent of current line: double minDescent = 0.0; // max descent of _previous_ line: double minDescentPrevious = 0.0; // true for the first block of the current line: bool firstBlockInLine = true; // current line has leading spaces: bool leadingSpaces = false; // current line has trailing spaces: bool trailingSpaces = false; // text has leading empty lines: bool leadingEmptyLines = false; // text has trailing empty lines: bool trailingEmptyLines = false; int lineCounter = 0; QString textBlock; QList<QTextLayout::FormatRange> formats; bool blockChangedHeightOrFont = false; // implicit top level format block: QTextCharFormat f; f.setForeground(QBrush(QColor())); currentFormat.push(f); QTextLayout::FormatRange fr; fr.start = 0; fr.length = 0; fr.format = currentFormat.top(); formats.append(fr); blockHeight.push(textHeight); blockFont.push(fontName); blockBold.push(bold); blockItalic.push(italic); useCadFont.push(RFontList::isCadFont(fontName)); openTags.push(QStringList()); width = 0.0; height = 0.0; // iterate through all text blocks: for (int i=0; i<literals.size(); ++i) { // the literal text, e.g. "ABC": QString literal = literals.at(i); // the formatting _after_ the text, e.g. "\C1;" QString formatting; if (i<formattings.size()) { formatting = formattings.at(i); } // qDebug() << "block: " << i; // qDebug() << " literal: " << literal; // qDebug() << " literal length: " << literal.length(); // qDebug() << " formatting: " << formatting; // qDebug() << " font: " << blockFont.top(); // qDebug() << " height: " << blockHeight.top(); // qDebug() << " cad font: " << useCadFont.top(); // qDebug() << " xCursor: " << xCursor; // handle literal: textBlock.append(literal); if (firstBlockInLine) { if (!literal.isEmpty()) { if (literal.at(0).isSpace()) { leadingSpaces = true; } } else { if (formatting=="\\~") { leadingSpaces = true; } } firstBlockInLine = false; } bool lineFeed = false; bool paragraphFeed = false; bool heightChange = false; bool stackedText = false; bool fontChange = false; bool colorChange = false; bool blockEnd = false; // detect formatting that ends the current text block: if (!formatting.isEmpty()) { fontChange = QRegExp(rxFontChangeTtf).exactMatch(formatting) || QRegExp(rxFontChangeCad).exactMatch(formatting); colorChange = QRegExp(rxColorChangeCustom).exactMatch(formatting) || QRegExp(rxColorChangeIndex).exactMatch(formatting); heightChange = QRegExp(rxHeightChange).exactMatch(formatting); stackedText = QRegExp(rxStackedText).exactMatch(formatting); lineFeed = QRegExp(rxLineFeed).exactMatch(formatting); paragraphFeed = QRegExp(rxParagraphFeed).exactMatch(formatting); blockEnd = QRegExp(rxEndBlock).exactMatch(formatting); } bool start = (i==0); bool end = (i==literals.size()-1); // first line is empty: if (textBlock.trimmed().isEmpty() && (lineFeed || paragraphFeed || end)) { if (start) { leadingEmptyLines = true; } else if (end) { trailingEmptyLines = true; } } // reached a new text block that needs to be rendered separately // due to line feed, height change, font change, ...: if (target==RichText || lineFeed || paragraphFeed || heightChange || stackedText || fontChange || colorChange || end || (blockEnd && blockChangedHeightOrFont)) { // render block _before_ format change that requires new block: if (textBlock!="") { // fix format lengths to match up. each format stops where // the next one starts. formatting that is carried over is set // again for the new format. for (int i=0; i<formats.size(); i++) { int nextStart; if (i<formats.size()-1) { nextStart = formats[i+1].start; } else { nextStart = textBlock.length(); } formats[i].length = nextStart - formats[i].start; } if (target==RichText) { richText += getRichTextForBlock( textBlock, formats); } if (target==PainterPaths) { double horizontalAdvance = 0.0; double horizontalAdvanceNoSpacing = 0.0; double ascent = 0.0; double descent = 0.0; QList<RPainterPath> paths; // get painter paths for current text block at height 1.0: paths = getPainterPathsForBlock( textBlock, formats, horizontalAdvance, horizontalAdvanceNoSpacing, ascent, descent); // transform to scale text from 1.0 to current text height: QTransform sizeTransform; sizeTransform.scale(blockHeight.top(), blockHeight.top()); // transform for current block due to xCursor position: QTransform blockTransform; blockTransform.translate(xCursor, 0); // combine transforms for current text block: QTransform allTransforms = sizeTransform; allTransforms *= blockTransform; maxAscent = qMax(maxAscent, ascent * blockHeight.top()); minDescent = qMin(minDescent, descent * blockHeight.top()); // transform paths of current block and append to paths // of current text line: for (int i=0; i<paths.size(); ++i) { RPainterPath p = paths.at(i); p.transform(allTransforms); linePaths.append(p); } xCursor += horizontalAdvance * blockHeight.top(); } } // empty text, might be line feed, we need ascent, descent anyway: else if (lineFeed || paragraphFeed || end) { if (target==PainterPaths) { double horizontalAdvance = 0.0; double horizontalAdvanceNoSpacing = 0.0; double ascent = 0.0; double descent = 0.0; // get painter paths for current text block at height 1.0: getPainterPathsForBlock( "A", QList<QTextLayout::FormatRange>(), horizontalAdvance, horizontalAdvanceNoSpacing, ascent, descent); maxAscent = qMax(maxAscent, ascent * blockHeight.top()); minDescent = qMin(minDescent, descent * blockHeight.top()); } } // handle stacked text: if (stackedText) { QRegExp reg; reg.setPattern(rxStackedText); reg.exactMatch(formatting); if (target==PainterPaths) { double horizontalAdvance[2]; horizontalAdvance[0] = 0.0; horizontalAdvance[1] = 0.0; double horizontalAdvanceNoSpacing[2]; horizontalAdvanceNoSpacing[0] = 0.0; horizontalAdvanceNoSpacing[1] = 0.0; double heightFactor = 0.4; // s==0: superscript, s==1: subscript: for (int s=0; s<=1; ++s) { QString script = reg.cap(s+1); QList<RPainterPath> paths; double ascent = 0.0; double descent = 0.0; QList<QTextLayout::FormatRange> localFormats; QTextLayout::FormatRange fr; fr.start = 0; fr.length = script.length(); fr.format = currentFormat.top(); localFormats.append(fr); // get painter paths for superscript at height 1.0: paths = getPainterPathsForBlock( script, localFormats, horizontalAdvance[s], horizontalAdvanceNoSpacing[s], ascent, descent); if (s==0) { maxAscent = qMax(maxAscent, ascent * blockHeight.top() * heightFactor + blockHeight.top()*(1.0-heightFactor)); } else { minDescent = qMin(minDescent, descent * blockHeight.top() * heightFactor); } // transform to scale text from 1.0 to current text height * 0.4: QTransform sizeTransform; sizeTransform.scale(blockHeight.top()*heightFactor, blockHeight.top()*heightFactor); // move top text more to the right for italic texts: double xOffset = 0.0; if (s==0 && blockItalic.top()==true) { double y = blockHeight.top()*(1.0-heightFactor); // assume italic means roughly 12 degrees: xOffset = tan(RMath::deg2rad(12)) * y; } // transform for current block due to xCursor position // and top or bottom text position: QTransform blockTransform; blockTransform.translate(xCursor + xOffset, s==0 ? blockHeight.top()*(1.0-heightFactor) : 0.0); horizontalAdvance[s] += xOffset / (blockHeight.top() * heightFactor); // combine transforms for current text block: QTransform allTransforms = sizeTransform; allTransforms *= blockTransform; // transform paths of current block and append to paths // of current text line: for (int i=0; i<paths.size(); ++i) { RPainterPath p = paths.at(i); p.transform(allTransforms); linePaths.append(p); } } xCursor += qMax(horizontalAdvance[0], horizontalAdvance[1]) * blockHeight.top() * heightFactor; } if (target==RichText) { QString super = reg.cap(1); QString sub = reg.cap(2); if (!super.isEmpty()) { richText += QString("<span style=\"vertical-align:super;\">%1</span>").arg(super); } if (!sub.isEmpty()) { richText += QString("<span style=\"vertical-align:sub;\">%1</span>").arg(sub); } } } // prepare for next text block: if (lineFeed || paragraphFeed || end) { if (!textBlock.isEmpty()) { if (textBlock.at(textBlock.length()-1).isSpace()) { trailingSpaces = true; } } // else { // if (formatting=="\\~") { // trailingSpaces = true; // } // } } textBlock = ""; formats.clear(); QTextLayout::FormatRange fr; fr.start = 0; fr.length = 0; fr.format = currentFormat.top(); formats.append(fr); // handle text line. // add all painter paths of the current line to result set of // painter paths. apply line feed transformations. if (lineFeed || paragraphFeed || end) { // qDebug() << "lineFeed: adding text line:"; // qDebug() << " maxAscent: " << maxAscent; // qDebug() << " minDescent: " << minDescent; // qDebug() << " minDescentPrevious: " << minDescentPrevious; // qDebug() << "got line feed or end"; // qDebug() << " trailingSpaces: " << trailingSpaces; if (target==RichText) { if (lineFeed || paragraphFeed) { richText += "<br/>"; } } if (lineCounter!=0) { yCursor += (minDescentPrevious - maxAscent) * lineSpacingFactor; } // calculate line bounding box for alignment without spaces at borders: RBox lineBoundingBox; for (int i=0; i<linePaths.size(); ++i) { RPainterPath p = linePaths.at(i); lineBoundingBox.growToInclude(p.getBoundingBox()); } double featureSize = lineBoundingBox.getHeight(); QTransform lineTransform; switch (horizontalAlignment) { case RS::HAlignAlign: case RS::HAlignFit: case RS::HAlignLeft: if (!leadingSpaces) { // move completely to the left (left border is 0.0): lineTransform.translate( -lineBoundingBox.getMinimum().x, yCursor); } else { lineTransform.translate(0, yCursor); } break; case RS::HAlignMid: case RS::HAlignCenter: if (!leadingSpaces && !trailingSpaces) { lineTransform.translate( -(lineBoundingBox.getMinimum().x + lineBoundingBox.getMaximum().x)/2.0, yCursor); } else { lineTransform.translate(-xCursor/2.0, yCursor); } break; case RS::HAlignRight: if (!trailingSpaces) { lineTransform.translate(-lineBoundingBox.getMaximum().x, yCursor); } else { lineTransform.translate(-xCursor, yCursor); } break; } width = qMax(width, lineBoundingBox.getMaximum().x - qMin(0.0, lineBoundingBox.getMinimum().x)); // add current text line to result set: QPen pen; for (int i=0; i<linePaths.size(); ++i) { RPainterPath p = linePaths[i]; if (i==0) { pen = p.getPen(); if (pen.style()==Qt::NoPen) { pen = QPen(p.getBrush().color()); } } p.transform(lineTransform); p.setFeatureSize(featureSize); painterPaths.append(p); boundingBox.growToInclude(p.getBoundingBox()); } RPainterPath bbPath; bbPath.addBox(lineBoundingBox); bbPath.transform(lineTransform); bbPath.setFeatureSize(-featureSize); bbPath.setPen(pen); painterPaths.append(bbPath); lineCounter++; xCursor = 0.0; maxAscent = 0.0; minDescentPrevious = minDescent; minDescent = 0.0; linePaths.clear(); firstBlockInLine = true; leadingSpaces = false; trailingSpaces = false; } } // handle formatting after text block, that applies either // to the next text block(s) or the rest of the current text block: if (formatting.isEmpty()) { continue; } QRegExp reg; // unicode: reg.setPattern(rxUnicode); if (reg.exactMatch(formatting)) { textBlock += QChar(reg.cap(1).toInt(0, 16)); continue; } // curly braket open: reg.setPattern(rxCurlyOpen); if (reg.exactMatch(formatting)) { textBlock += "{"; continue; } // curly braket close: reg.setPattern(rxCurlyClose); if (reg.exactMatch(formatting)) { textBlock += "}"; continue; } // degree: reg.setPattern(rxDegree); if (reg.exactMatch(formatting)) { textBlock += chDegree; continue; } // plus/minus: reg.setPattern(rxPlusMinus); if (reg.exactMatch(formatting)) { textBlock += chPlusMinus; continue; } // diameter: reg.setPattern(rxDiameter); if (reg.exactMatch(formatting)) { textBlock += chDiameter; continue; } // backslash: reg.setPattern(rxBackslash); if (reg.exactMatch(formatting)) { textBlock += "\\"; continue; } // non-breaking space: reg.setPattern(rxNonBreakingSpace); if (reg.exactMatch(formatting)) { if (target==PainterPaths) { textBlock += QChar(Qt::Key_nobreakspace); } if (target==RichText) { textBlock += " "; } continue; } // font change (TTF): reg.setPattern(rxFontChangeTtf); if (reg.exactMatch(formatting)) { blockFont.top() = reg.cap(1); blockBold.top() = (reg.cap(2).toInt()!=0); blockItalic.top() = (reg.cap(3).toInt()!=0); useCadFont.top() = false; blockChangedHeightOrFont = true; if (target==RichText) { QString style; style += QString("font-family:%1;").arg(blockFont.top()); style += QString("font-weight:%1;").arg(blockBold.top() ? "bold" : "normal"); style += QString("font-style:%1;").arg(blockItalic.top() ? "italic" : "normal"); richText += QString("<span style=\"%1\">").arg(style); openTags.top().append("span"); } continue; } // font change (CAD): reg.setPattern(rxFontChangeCad); if (reg.exactMatch(formatting)) { blockFont.top() = reg.cap(1); useCadFont.top() = true; if (xCursor>RS::PointTolerance) { RFont* f = RFontList::get(blockFont.top()); if (f!=NULL && f->isValid()) { xCursor += f->getLetterSpacing() / 9.0; } } blockChangedHeightOrFont = true; if (target==RichText) { QString style; style += QString("font-family:%1;").arg(blockFont.top()); richText += QString("<span style=\"%1\">").arg(style); openTags.top().append("span"); } continue; } // height change: reg.setPattern(rxHeightChange); if (reg.exactMatch(formatting)) { bool factor = reg.cap(2)=="x"; if (factor) { blockHeight.top() *= reg.cap(1).toDouble(); } else { blockHeight.top() = reg.cap(1).toDouble(); } blockChangedHeightOrFont = true; if (target==RichText) { QString style; style += QString("font-size:%1pt;").arg(blockHeight.top() * fontHeightFactor); richText += QString("<span style=\"%1\">").arg(style); openTags.top().append("span"); } continue; } QTextLayout::FormatRange fr; fr.start = textBlock.length(); fr.length = 0; // start format block: reg.setPattern(rxBeginBlock); if (reg.exactMatch(formatting)) { currentFormat.push(currentFormat.top()); blockFont.push(blockFont.top()); blockBold.push(blockBold.top()); blockItalic.push(blockItalic.top()); blockHeight.push(blockHeight.top()); useCadFont.push(useCadFont.top()); if (target==RichText) { openTags.push(QStringList()); } blockChangedHeightOrFont = false; continue; } // end format block: reg.setPattern(rxEndBlock); if (reg.exactMatch(formatting)) { currentFormat.pop(); fr.format = currentFormat.top(); formats.append(fr); blockFont.pop(); blockBold.pop(); blockItalic.pop(); blockHeight.pop(); useCadFont.pop(); blockChangedHeightOrFont = false; if (target==RichText) { // close all tags that were opened in this block: for (int i=openTags.top().size()-1; i>=0; --i) { QString tag = openTags.top().at(i); richText += QString("</%1>").arg(tag); } openTags.pop(); } continue; } // color change (indexed): reg.setPattern(rxColorChangeIndex); if (reg.exactMatch(formatting)) { RColor blockColor = RColor::createFromCadIndex(reg.cap(1)); if (blockColor.isByLayer()) { currentFormat.top().setForeground(RColor::CompatByLayer); } else if (blockColor.isByBlock()) { currentFormat.top().setForeground(RColor::CompatByBlock); } else { currentFormat.top().setForeground(blockColor); } fr.format = currentFormat.top(); formats.append(fr); if (target==RichText) { QString style; style += QString("color:%1;").arg(blockColor.name()); richText += QString("<span style=\"%1\">").arg(style); openTags.top().append("span"); } continue; } // color change (custom): reg.setPattern(rxColorChangeCustom); if (reg.exactMatch(formatting)) { RColor blockColor = RColor::createFromCadCustom(reg.cap(1)); currentFormat.top().setForeground(blockColor); fr.format = currentFormat.top(); formats.append(fr); if (target==RichText) { QString style; style += QString("color:%1;").arg(blockColor.name()); richText += QString("<span style=\"%1\">").arg(style); openTags.top().append("span"); } continue; } } if (target==PainterPaths) { // at this point, the text is at 0/0 with the base line of the // first text line at y==0 // vertical alignment: double topLine = qMax(textHeight, boundingBox.getMaximum().y); double bottomLine = qMin(0.0, boundingBox.getMinimum().y); QTransform globalTransform; globalTransform.translate(position.x, position.y); globalTransform.rotate(RMath::rad2deg(angle)); switch (verticalAlignment) { case RS::VAlignTop: //if (!leadingEmptyLines) { globalTransform.translate(0.0, -topLine); //} break; case RS::VAlignMiddle: if (leadingEmptyLines || trailingEmptyLines) { globalTransform.translate(0.0, -(yCursor+textHeight)/2.0); } else { globalTransform.translate(0.0, -(bottomLine + topLine) / 2.0); } break; case RS::VAlignBottom: case RS::VAlignBase: if (trailingEmptyLines) { globalTransform.translate(0.0, -yCursor); } else { globalTransform.translate(0.0, -bottomLine); } break; } height = boundingBox.getHeight(); // apply global transform for position, angle and vertical alignment: boundingBox = RBox(); for (int i=0; i<painterPaths.size(); ++i) { painterPaths[i].transform(globalTransform); boundingBox.growToInclude(painterPaths[i].getBoundingBox()); } } if (target==RichText) { // close all tags that were opened: for (int i=openTags.top().size()-1; i>=0; --i) { QString tag = openTags.top().at(i); richText += QString("</%1>").arg(tag); } } }
//**************************************************************************** // // Function Name: FillData // // Description: Fills an HeadlineDataStruct with the Headline // depth effect data // // Returns: None // // Exceptions: None // //**************************************************************************** void RHeadlineDepthPage::FillData( RHeadlineInterface* pInterface, RComponentView* pComponentView ) { // // Set the depth effects // if (m_data.nDataType == kShadowType) { // Clear any depth effects pInterface->SetProjectionEffect( kNoProjection ) ; RSoftShadowSettings settings; settings.m_fShadowOn = TRUE; settings.m_fShadowOpacity = m_data.nOpacity / 100.0; settings.m_fShadowEdgeSoftness = m_data.nEdgeSoftness / 100.0; settings.m_fShadowOffset = m_data.nOffset / 65535.0; settings.m_fShadowAngle = -m_wndBlendAngle.GetAngle(); settings.m_fShadowColor = m_btnColor.GetColor().GetSolidColor(); pComponentView->SetShadowSettings( settings ); } else { if (pComponentView->HasShadow()) { // Clear any shadow settings RSoftShadowSettings settings; pComponentView->GetShadowSettings( settings ); settings.m_fShadowOn = FALSE; pComponentView->SetShadowSettings( settings ); } RIntPoint ptVanish( int(cos(m_angle) * m_data.nVanishPointX + 0.5), int(sin(m_angle) * m_data.nVanishPointY + 0.5) ) ; pInterface->SetNumStages( m_data.nNumStages ) ; pInterface->SetProjectionEffect( (EProjectionEffects) m_data.nSelProjection ) ; pInterface->SetProjectionDepth( m_data.flDepth ) ; pInterface->SetProjectionVanishPoint( ptVanish ) ; pInterface->SetProjectionFillColor( m_btnColor.GetColor() ) ; pInterface->SetShadowEffect( (EShadowEffects) m_data.nSelShadow ) ; pInterface->SetShadowDepth( m_data.flDepth ) ; pInterface->SetShadowVanishPoint( ptVanish ) ; pInterface->SetShadowFillColor( m_btnColor.GetColor() ) ; if (m_data.fBlend && m_data.nSelProjection > kNoProjection) { // EFramedEffects eFrameEffect ; // pInterface->GetBehindEffect( eFrameEffect ) ; RColor crBlendColor ; pInterface->GetBehindColor( crBlendColor ) ; if (RColor::kTransparent == crBlendColor.GetFillMethod()) { crBlendColor = RSolidColor( kWhite ) ; } RSolidColor crBlendArray[] = { m_btnColor.GetColor().GetSolidColor(), crBlendColor.GetSolidColor() } ; crBlendColor = RColor( crBlendArray, 2, m_angle ) ; pInterface->SetProjectionFillColor( crBlendColor ) ; } } if (m_data.nSelProjection > kNoProjection || m_data.nDataType == kShadowType) { EOutlineEffects eOutlineEffect ; pInterface->GetOutlineEffect( eOutlineEffect ) ; // // The user selected a depth option which is mutually exclusive // with the emboss and deboss outline options, so we need to clear // the emboss/deboss option if it is set. // switch (eOutlineEffect) { case kEmbossedOutline: case kDebossedOutline: case kBlurredOutline: { // RColor crBehindColor ; // pInterface->GetBehindColor( crBehindColor ) ; // EFramedEffects eFrameEffect = (RColor::kTransparent == // crBehindColor.GetFillMethod() ? kFrameNoFrame : kSimpleFrame) ; // Clear the outline effect pInterface->SetOutlineEffect( kSimpleFill ) ; // Set the appropriate behind effect. // pInterface->SetBehindEffect( eFrameEffect ) ; } } } }
//**************************************************************************** // // Function Name: ApplyData // // Description: Applies HeadlineDataStruct effect's data // to the Headline depth controls // // Returns: None // // Exceptions: None // //**************************************************************************** void RHeadlineDepthPage::ApplyData( RHeadlineInterface* pInterface, RComponentView* pComponentView ) { // Set the effects data ////////////////////////// EProjectionEffects eProjEffects ; EShadowEffects eShadowEffects ; RIntPoint ptVanish ; RColor crFillColor ; int nNumStages ; pInterface->GetNumStages( nNumStages ) ; pInterface->GetProjectionEffect( eProjEffects ) ; pInterface->GetProjectionDepth( m_data.flDepth ) ; pInterface->GetShadowEffect( eShadowEffects ) ; pInterface->GetProjectionFillColor( crFillColor ) ; pInterface->GetProjectionVanishPoint( ptVanish ) ; if (eShadowEffects > kNoShadow) { // Currently these options are shared, but in // pre-existing data they may not be. pInterface->GetShadowFillColor( crFillColor ) ; pInterface->GetShadowVanishPoint( ptVanish ) ; } if (pComponentView->HasShadow()) { RSoftShadowSettings settings; pComponentView->GetShadowSettings( settings ); m_data.nDataType = kShadowType; m_data.nOpacity = ::Round( settings.m_fShadowOpacity * 100 ); m_data.nEdgeSoftness = ::Round( settings.m_fShadowEdgeSoftness * 100 ); m_data.nOffset = ::Round( settings.m_fShadowOffset * 65535 ); m_wndBlendAngle.SetAngle( -settings.m_fShadowAngle ); m_angle = m_wndBlendAngle.GetAngle(); m_btnColor.SetColor( RColor( settings.m_fShadowColor ) ) ; } else { m_data.nDataType = kDepthType ; m_data.nNumStages = nNumStages ; m_data.nSelProjection = eProjEffects ; m_data.nSelShadow = eShadowEffects ; m_data.fBlend = sWORD( RColor::kGradient == crFillColor.GetFillMethod() ) ; m_wndBlendAngle.SetAngle( atan2( YRealDimension( ptVanish.m_y ), YRealDimension( ptVanish.m_x ) ) ) ; m_btnColor.SetColor( RColor(crFillColor.GetSolidColor()) ) ; m_angle = m_wndBlendAngle.GetAngle() ; YAngle angle = fmod((double)m_angle, (double)(2.0 * kPI)); if (angle < 0.0) angle += 2.0 * kPI; const YRealDimension kAngleDelta = 0.00001; if (::AreFloatsEqual(angle, kPI / 2.0, kAngleDelta) || ::AreFloatsEqual(angle, 3.0 * kPI / 2.0, kAngleDelta)) m_data.nVanishPointX = 0; else m_data.nVanishPointX = ptVanish.m_x / cos( m_angle ) ; if (::AreFloatsEqual(angle, 0.0, kAngleDelta) || ::AreFloatsEqual(angle, kPI, kAngleDelta)) m_data.nVanishPointY = 0; else m_data.nVanishPointY = ptVanish.m_y / sin( m_angle ) ; /* if (m_data.nSelShadow > kNoShadow) { pInterface->GetShadowDepth( m_data.flDepth ) ; m_data.nDataType = kShadowType; m_data.nOpacity = 100; m_data.nEdgeSoftness = 0; m_data.nOffset = 10; // TODO: determine from vanishing point FillData( pInterface, pComponentView ); } */ } if (GetSafeHwnd()) { // Set the image selection EnumResourceNames( AfxGetResourceHandle(), // resource-module handling cResourceType, // pointer to resource type (ENUMRESNAMEPROC) SelectResItem, // pointer to callback function (LONG) this ) ; // application-defined parameter m_btnColor.EnableWindow( m_gcImageList.GetCurSel() != 0 ) ; } }
/** * \return Highlighted color for the given color. */ RColor RColor::getHighlighted(const RColor& color, const QColor& bgColor, int minDist) { if (!color.isValid()) { return Qt::gray; } RColor ret = color; int vColor = color.value(); int vBgColor = bgColor.value(); // 0 vColor vBgColor 255 // |--------^----------------------------^------------------| // |<--d1-->|<------------d2------------>|<-------d3------->| int d1 = qMin(vColor, vBgColor); //int d2 = qAbs(vColor - vBgColor); int d3 = 255 - qMax(vColor, vBgColor); // d3 is big enough: set value to max (highlight): if (d3>=minDist) { ret.setHsv(color.hue(), color.saturation(), 255); } // d1 is big enough: set value to half (lowlight): else if (d1>=minDist) { ret.setHsv(color.hue(), color.saturation(), qMin(vColor, vBgColor)/2); } // black on white: else if (vColor<32 && vBgColor>224) { ret.setHsv(color.hue(), color.saturation(), 160); } // d2 is the only significant distance, set value to medium: else if (vColor<vBgColor) { ret.setHsv(color.hue(), color.saturation(), qMin(vColor+minDist, 255)); } else { ret.setHsv(color.hue(), color.saturation(), qMax(vColor-minDist, 0)); } return ret; }
bool RColor::operator<(const RColor & color) const { return getHash() < color.getHash(); }