void WPainter::drawImage(double x, double y, const Image& image, double sx, double sy, double sw, double sh) { if (sw <= 0) sw = image.width() - sx; if (sh <= 0) sh = image.height() - sy; device_->drawImage(WRectF(x, y, sw, sh), image.uri(), image.width(), image.height(), WRectF(sx, sy, sw, sh)); }
void WPainter::drawImage(const WPointF& point, const Image& image, const WRectF& sourceRect) { drawImage(WRectF(point.x(), point.y(), sourceRect.width(), sourceRect.height()), image, sourceRect); }
void WPainter::drawText(double x, double y, double width, double height, WFlags<AlignmentFlag> alignmentFlags, TextFlag textFlag, const WString& text) { drawText(WRectF(x, y, width, height), alignmentFlags, textFlag, text); }
void WMeasurePaintDevice::drawText(const WRectF& rect, WFlags<AlignmentFlag> flags, TextFlag textFlag, const WString& text, const WPointF *clipPoint) { if (clipPoint && painter()) { if (!painter()->clipPathTransform().map(painter()->clipPath()) .isPointInPath(painter()->worldTransform().map(*clipPoint))) return; } double w = 0, h = 0; WString line = text; WFontMetrics fm = fontMetrics(); for (;;) { WTextItem t = measureText(line, rect.width(), textFlag == TextWordWrap ? true : false); h += fm.height(); w = std::max(w, t.width()); if (t.text() == line) break; else line = WString ::fromUTF8(line.toUTF8().substr(t.text().toUTF8().length())); } AlignmentFlag horizontalAlign = flags & AlignHorizontalMask; AlignmentFlag verticalAlign = flags & AlignVerticalMask; double x, y; switch (horizontalAlign) { case AlignLeft: x = rect.left(); break; case AlignCenter: x = rect.left() + (rect.width() - w) / 2; break; case AlignRight: default: x = rect.right() - w; break; } switch (verticalAlign) { case AlignTop: y = rect.top(); break; case AlignMiddle: y = rect.top() + (rect.height() - h) / 2; break; case AlignBottom: default: y = rect.bottom() - h; break; } expandBounds(WRectF(x, y, w, h)); }
void WCartesianChart::initLayout(const WRectF& rectangle) { WRectF rect = rectangle; if (rect.isEmpty()) rect = WRectF(0, 0, width().toPixels(), height().toPixels()); WPainter painter; WChart2DRenderer *renderer = createRenderer(painter, rect); renderer->initLayout(); delete renderer; }
WRectF WRunwayGlyph::boundingRect() const { /*const WRectItemData& d = data()->m_rectData; const WRectF& r = d.rect; WWorldPointF p = r.bottomLeft(); const double genericScaleLength = data()->m_dProlongLength / 20.0; const double dy = std::max(genericScaleLength - r.height() / 2.0, 0.0); WMatrix m = WMatrix().translate(-p) * WMatrix().rotate(d.angle) * WMatrix().translate(p); return m.mapRect(data()->m_bShowProlong ? r.adjusted(0.0, -dy, data()->m_dProlongLength, dy) : r);*/ return WRectF(-20000, -20000, 40000, 40000); }
void WFrozenFrameGlyph::paint(WPainter* painter) { static const size_t BLOCK_COUNT = 20; static const double BLOCK_WIDTH = 30.0; static const double X_LEFT= 0.0; const data_type& d = *data(); WSizeF size = painter->deviceSize(); const double BLOCK_HEIGHT = size.height() / BLOCK_COUNT; const double X_RIGHT = size.width() - X_LEFT - BLOCK_WIDTH; WPainterProxy proxy(painter); painter->setWorldTransform(WMatrix()); painter->setPen(d.m_pen); for (size_t i = 0; i < BLOCK_COUNT; ++i) { double y = BLOCK_HEIGHT * i; painter->setBrush((i & 1) ? d.m_brushEnd : d.m_brushBegin); painter->drawRect(WRectF(X_LEFT, y, BLOCK_WIDTH, BLOCK_HEIGHT)); painter->drawRect(WRectF(X_RIGHT, y, BLOCK_WIDTH, BLOCK_HEIGHT)); } }
void WAzimuthRectGlyph::paint(WPainter* painter) { static const size_t SCALE_COUNT = 20; static const size_t SCALE_COUNT_2 = SCALE_COUNT / 2; static const double SCALE_LENGTH = 30.0; WSizeF size = painter->deviceSize(); const double WIDTH = size.width(); const double HEIGHT = size.height(); const double CELL_WIDTH = WIDTH / SCALE_COUNT; const double CELL_HEIGHT = HEIGHT / SCALE_COUNT; const WPointF C(WIDTH / 2.0, HEIGHT / 2.0); WPainterProxy proxy(painter); painter->setWorldTransform(WMatrix()); painter->setPen(data()->m_pen); painter->setBrush(WBrush(Ws::NoBrush)); painter->drawRect(WRectF(1.0, 1.0, WIDTH - 2.0, HEIGHT - 2.0)); WPointF pts[4]; pts[0].ry() = 0.0; pts[1].rx() = WIDTH; pts[2].ry() = HEIGHT; pts[3].rx() = 0.0; for (size_t i = 0; i < SCALE_COUNT; ++i) { pts[0].rx() = CELL_WIDTH * i; pts[1].ry() = CELL_HEIGHT * i; pts[2].rx() = pts[0].x(); pts[3].ry() = pts[1].y(); bool drawAngle = (i == SCALE_COUNT_2); size_t count = 0; BOOST_FOREACH(const WPointF& p, pts) { WLineF line(p, C); line.setLength(SCALE_LENGTH); painter->drawLine(line); if (drawAngle) { painter->drawText(line.p2(), boost::lexical_cast<std::string>(90 * (count++)) + char(0xb0)); } } }
void WCartesianChart::drawMarker(const WDataSeries& series, WPainterPath& result) const { const double size = 6.0; const double hsize = size/2; switch (series.marker()) { case CircleMarker: result.addEllipse(-hsize, -hsize, size, size); break; case SquareMarker: result.addRect(WRectF(-hsize, -hsize, size, size)); break; case CrossMarker: result.moveTo(-1.3 * hsize, 0); result.lineTo(1.3 * hsize, 0); result.moveTo(0, -1.3 * hsize); result.lineTo(0, 1.3 * hsize); break; case XCrossMarker: result.moveTo(-hsize, -hsize); result.lineTo(hsize, hsize); result.moveTo(-hsize, hsize); result.lineTo(hsize, -hsize); break; case TriangleMarker: result.moveTo( 0, 0.6 * hsize); result.lineTo(-hsize, 0.6 * hsize); result.lineTo(0, -hsize); result.lineTo(hsize, 0.6 * hsize); result.closeSubPath(); break; case CustomMarker: result = series.customMarker(); break; default: ; } }
void WRunwayGlyph::paint(WPainter* painter) { data_type& d = *data(); WPointF c = d.m_line.center(); double w = d.m_size.width(); //double h = d.m_size.height(); double h = d.m_line.length(); d.m_dProlongLength = h / 2; WPainterProxy proxy(painter); painter->setPen(d.m_pen); painter->setBrush(WBrush(Ws::NoBrush)); painter->setWorldTransform(WMatrix().translate(c).rotate(90 - d.m_angle).translate(-c), true); painter->drawRect(WRectF(c.x() - h / 2, c.y() - w / 2, h, w)); if (data()->m_bShowProlong) { WPointF s(c.x() + h / 2, c.y()); //line start point WLineF line(s, WPointF(s.x() + data()->m_dProlongLength, s.y())); painter->drawLine(line); const size_t scaleCount = data()->m_genericScaleCount * data()->m_detailScaleCount; const double genericScaleLength = data()->m_dProlongLength / 20.0; const double detailScaleLength = data()->m_dProlongLength / 40.0; const double scaleDistance = data()->m_dProlongLength / scaleCount; for (size_t i = 1; i < scaleCount + 1; ++i) { WPointF p(s.x() + i * scaleDistance, s.y()); WPointF p1(p); WPointF p2(p); const double& scaleLength = (i % data()->m_detailScaleCount == 0 ? genericScaleLength : detailScaleLength); p1.ry() -= scaleLength; p2.ry() += scaleLength; painter->drawLine(WLineF(p1, p2)); } } }
void WPainter::drawPie(double x, double y, double width, double height, int startAngle, int spanAngle) { drawPie(WRectF(x, y, width, height), startAngle, spanAngle); }
void WPainter::drawImage(const WRectF& rect, const Image& image) { drawImage(rect, image, WRectF(0, 0, image.width(), image.height())); }
WRectF WAzimuthCircleGlyph::boundingRect() const { static const double INFINITE_RADIUS = 1.0e10; return WRectF(-INFINITE_RADIUS, -INFINITE_RADIUS, INFINITE_RADIUS * 2, INFINITE_RADIUS * 2); }
void WPainter::drawImage(const WPointF& point, const Image& image) { drawImage(WRectF(point.x(), point.y(), image.width(), image.height()), image, WRectF(0, 0, image.width(), image.height())); }
void WPainter::setWindow(double x, double y, double width, double height) { setWindow(WRectF(x, y, width, height)); }
void WPainter::fillRect(double x, double y, double width, double height, const WBrush& brush) { fillRect(WRectF(x, y, width, height), brush); }
/** \brief boundingRect \Access virtual public \retval WRectF \remark */ WRectF WRandomPointGlyph::boundingRect() const { const WPointF& p = data()->m_pos; return WRectF(p.x() - POINTRADIUS, p.y() - POINTRADIUS, POINTRADIUS * 2, POINTRADIUS * 2); }
void FontSupport::drawText(const WFont& font, const WRectF& rect, WFlags<AlignmentFlag> flags, const WString& text) { PANGO_LOCK; enabledFontFormats = enabledFontFormats_; std::string utf8 = text.toUTF8(); std::vector<PangoGlyphString *> glyphs; int width; GList *items = layoutText(font, utf8, glyphs, width); AlignmentFlag hAlign = flags & AlignHorizontalMask; AlignmentFlag vAlign = flags & AlignVerticalMask; /* FIXME handle bidi ! */ double x; switch (hAlign) { case AlignmentFlag::Left: x = rect.left(); break; case AlignmentFlag::Right: x = rect.right() - pangoUnitsToDouble(width); break; case AlignmentFlag::Center: x = rect.center().x() - pangoUnitsToDouble(width/2); break; default: x = 0; } unsigned i = 0; for (GList *elem = items; elem; elem = elem->next) { PangoItem *item = (PangoItem *)elem->data; PangoAnalysis *analysis = &item->analysis; PangoGlyphString *gl = glyphs[i++]; currentFont_ = analysis->font; /* * Note, we are actually ignoring the selected glyphs here, which * is a pitty and possibly wrong if the device does not make the * same selection ! */ WString s = WString::fromUTF8(utf8.substr(item->offset, item->length)); device_->drawText(WRectF(x, rect.y(), 1000, rect.height()), AlignmentFlag::Left | vAlign, TextFlag::SingleLine, s, nullptr); WTextItem textItem = device_->measureText(s, -1, false); x += textItem.width(); pango_item_free(item); pango_glyph_string_free(gl); } g_list_free(items); currentFont_ = nullptr; }
void WLegend3D::renderLegend(WPainter* painter, const std::vector<WAbstractDataSeries3D*> &dataseries) { if (!legendEnabled_) return; painter->save(); int nbItems = 0; for (unsigned i = 0; i < dataseries.size(); i++) { WAbstractDataSeries3D *series = dataseries[i]; if (series->isLegendEnabled() && !series->isHidden()) nbItems++; } double textHeight = legendFont_.sizeLength().toPixels(); double labelWidth = textHeight * 0.618; double lineHeight = textHeight * 1.5; double offset = (lineHeight-textHeight)/2; painter->setPen(legendBorder_); painter->setFont(legendFont_); painter->setBrush(legendBackground_); int nbRows = nbItems/legendColumns_; if (nbItems % legendColumns_) nbRows++; painter->drawRect(0, 0, legendColumns_*legendColumnWidth_.value() + 2*boxPadding, nbRows*lineHeight + 2*boxPadding); painter->translate(boxPadding, boxPadding); int count = 0; for (unsigned i = 0; i < dataseries.size(); i++) { WAbstractDataSeries3D *series = dataseries[i]; if (!series->isLegendEnabled() || series->isHidden()) continue; count++; // paint icon if (series->colorMap() == 0) { // if chartpalette WColor seriesColor = series->chartpaletteColor(); painter->fillRect(0, offset, labelWidth, textHeight, WBrush(seriesColor)); } else { // else colormap series->colorMap()->createStrip(painter, WRectF(0, offset, labelWidth, textHeight)); } // draw label painter->drawText( labelWidth + 10, 0, 100, lineHeight, AlignLeft | AlignMiddle, series->title() ); // offset painter if (count == legendColumns_) { painter->translate(-(legendColumns_-1)*legendColumnWidth_.value(), lineHeight); count = 0; } else { painter->translate(legendColumnWidth_.value(), 0); } } painter->restore(); }
void WAircraftGlyph::paint(WPainter* painter) { data_type& d = *data(); painter->setBrush(WBrush(Ws::NoBrush)); m_cd.aircraftMatrix = painter->worldTransform(); m_cd.labelMatrix_1 = m_cd.aircraftMatrix.inverted(); const WMatrix& mapToView = m_cd.aircraftMatrix; painter->setWorldTransform(WMatrix()); WColor symbolColor = d.m_SymbolColor; WPointF view_aircraft_pos_f = mapToView.map(d.m_pos); static const double R = 10.0; static const double RS = 15.0; //draw a bigger circle around, when aircraft is selected double x = view_aircraft_pos_f.x(); double y = view_aircraft_pos_f.y(); if (d.m_eSymbolType == SYMBOL_COMBINED/*AIRCRAFT_NOR*/) { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } //tmp painter->drawEllipse(WRectF(x - R, y - R, R * 2, R * 2)); painter->drawLine(WLineF(x - R, y, x + R, y)); painter->drawLine(WLineF(x, y - R, x, y + R)); //DrawAircraft(painter, view_aircraft_pos); } else if (d.m_eSymbolType == SYMBOL_PRIMARY)//一次雷达 { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } painter->drawLine(WLineF(x - R, y, x + R, y)); painter->drawLine(WLineF(x, y - R, x, y + R)); } else if (d.m_eSymbolType == SYMBOL_SECONDARY)//二次雷达 { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } painter->drawEllipse(WRectF(x - R, y - R, R * 2, R * 2)); } else if (d.m_eSymbolType == SYMBOL_PLAN)//计划航迹 { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } painter->drawRect(WRectF(x - R, y - R, R * 2, R * 2)); } else if (d.m_eSymbolType == SYMBOL_COAST)//进入盲区 { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } WPen pen; pen.setWidth(4); pen.setColor(WColor(255, 255, 255)); painter->setPen(pen); painter->drawLine(WWorldLineF(x - R, y, x - R / 2, y)); painter->drawLine(WWorldLineF(x + R, y, x + R / 2, y)); painter->drawLine(WWorldLineF(x, y - R, x, y - R / 2)); painter->drawLine(WWorldLineF(x, y + R, x, y + R / 2)); pen.setWidth(1); pen.setColor(symbolColor); painter->setPen(pen); } else if (d.m_eSymbolType == SYMBOL_SPI)//处于SPI告警状态 { painter->setPen(WPen(symbolColor)); if (isSelected()) { painter->drawEllipse(WRectF(x - RS, y - RS, RS * 2, RS * 2)); } painter->drawLine(WLineF(x - R, y, x + R, y)); painter->drawLine(WLineF(x, y - R, x, y + R)); WPen pen; pen.setStyle(Ws::DashLine); pen.setColor(WColor(255, 255, 255)); painter->setPen(pen); painter->drawEllipse(WRectF(x - R, y - R, R * 2, R * 2)); pen.setStyle(Ws::SolidLine); pen.setColor(symbolColor); painter->setPen(pen); } else if (d.m_eSymbolType == SYMBOL_VEHICLE)//车辆航迹(实心三角) { painter->setPen(WPen(symbolColor)); painter->setBrush(WBrush(symbolColor, Ws::SolidPattern)); WPointF Tmppoint; std::vector<WPointF> vPoints; Tmppoint.setXY(x, y - 5); vPoints.push_back(Tmppoint); Tmppoint.setXY(x - 5, y + 5); vPoints.push_back(Tmppoint); Tmppoint.setXY(x + 5, y + 5); vPoints.push_back(Tmppoint); painter->drawPolygon(WWorldPolygonF(vPoints)); painter->setBrush(WBrush(Ws::NoBrush)); if (isSelected()) { painter->drawEllipse(WRectF(x - R, y - R, R * 2, R * 2)); } } else if (d.m_eSymbolType == SYMBOL_ADSB) // ADSB暂定符号(参考Indra手册)实心菱形 { painter->setPen(WPen(symbolColor)); painter->setBrush(WBrush(symbolColor, Ws::SolidPattern)); WPointF Tmppoint; std::vector<WPointF> vPoints; Tmppoint.setXY(x, y - 5); vPoints.push_back(Tmppoint); Tmppoint.setXY(x - 5, y); vPoints.push_back(Tmppoint); Tmppoint.setXY(x, y + 5); vPoints.push_back(Tmppoint); Tmppoint.setXY(x + 5, y); vPoints.push_back(Tmppoint); painter->drawPolygon(WWorldPolygonF(vPoints)); painter->setBrush(WBrush(Ws::NoBrush)); if (isSelected()) { painter->drawEllipse(WRectF(x - R, y - R, R * 2, R * 2)); } } else if (d.m_eSymbolType == SYMBOL_PIC_AIRCRAFT || d.m_eSymbolType == SYMBOL_PIC_HELICOPTER) { painter->setPen(WPen(symbolColor)); painter->setBrush(WBrush(symbolColor, Ws::SolidPattern)); painter->setBrush(WBrush(Ws::NoBrush)); painter->setRenderHint(Ws::SmoothPixmapTransform); WPixmap pixmap(d.m_eSymbolType == SYMBOL_PIC_AIRCRAFT ? ":/plane.png" : ":/helicopter.png"); WPixmap newPixmap = pixmap.xrotated(-90 + d.m_nHeading, Ws::SmoothTransformation); painter->drawPixmap(view_aircraft_pos_f-WPointF(newPixmap.width()/2, newPixmap.height()/2), newPixmap); } WLineF line(WPointF(), d.m_boundingRect.center()); if (line.length() > m_sLineMaxLength) { line.setLength(m_sLineMaxLength); WPointF offPoint = line.p2() - d.m_boundingRect.center(); d.m_boundingRect.translate(offPoint); d.m_showRect.translate(offPoint); } WPointF view_label_pos_f = d.m_boundingRect.bottomLeft() + view_aircraft_pos_f;// aircraft pos + label offset pos WPointF offset_f = d.m_showRect.bottomLeft() - d.m_boundingRect.bottomLeft(); WRectF view_label_rect(WRectF(view_label_pos_f, WSizeF(d.m_boundingRect.width(), d.m_boundingRect.height()))); //标牌避让 if (m_sLabelAvoidance) { const WRectF& r = view_label_rect; Mosaic::Instance().Allocate(reinterpret_cast<int>(this), r.left(), r.bottom(), r.right(), r.top()); } // label show rect指标牌边框显示区域,标牌有时候需要显示边框,边框与内容区域可能不一致,如C显示 WRectF label_show_rect(WRectF(view_label_rect.bottomLeft(), WSizeF(d.m_showRect.width(), d.m_showRect.height()))); label_show_rect.translate(offset_f); //show history // 尾迹点访问外部数据,本应该加锁,由于外部默认分配了很大数据存在,且点数据一致增加到默认最大值 // 内部通过下标访问不存在问题 // 如外部数据容器变小,就必须得加锁保护 if (m_sShowHistoryPoint && d.m_vHistory != NULL && d.m_vHistory->size() > 1) { size_t n = d.m_vHistory->size() - 1; size_t count = (m_sHstNum < n) ? m_sHstNum : n; size_t pos = n - 1; for (size_t i = 0; i < count; ++i, --pos) { static const double R = 0.8; double dx = 0.00; double dy = 0.00; mapToView.map((*d.m_vHistory)[pos]->x(), (*d.m_vHistory)[pos]->y(), &dx, &dy); painter->drawEllipse(WRectF(dx - R, dy - R, R * 2, R * 2)); //尾迹点 } } //show preline if (m_sShowPreLine) { painter->drawLine(WLineF(view_aircraft_pos_f, mapToView.map(d.m_PRLPos))); //预计线 } if (d.m_bShowLabel) { //show linkline (内部包含了外一点与一矩形中心点连线只绘制外一点到矩形边框的算法) DrawLabelLine(painter, view_aircraft_pos_f, label_show_rect); WPainterProxy proxy(painter); painter->setRenderHint(Ws::Antialiasing, false); // 绘制矩形的时候去掉反锯齿,效果更好 painter->setRenderHint(Ws::TextAntialiasing, false); if (d.m_bShowBounding) { painter->setPen(d.m_penBounding); // 标牌边框颜色与航迹符号与文本是分开的 painter->drawRect(label_show_rect); } //show label painter->setFont(m_sLabelFont); m_cache_locker.lock(); // 对访问d.m_blocks进行加锁,网络线程在FormatLable的时候会重新组织m_blocks数据,数据需要同步操作 BOOST_FOREACH(const WBlockData& block, m_blocks) { painter->setPen(block.m_penText); WRectF r = block.m_boundingRect.translated(view_label_pos_f); painter->drawText(r, Ws::AlignCenter, block.m_text); }
void WPainter::setViewPort(double x, double y, double width, double height) { setViewPort(WRectF(x, y, width, height)); }
void WMeasurePaintDevice::drawLine(double x1, double y1, double x2, double y2) { expandBounds(WRectF(x1, y1, x2-x1, y2-y1)); }
WRectF WPainterPath::controlPointRect(const WTransform& transform) const { if (isEmpty()) return WRectF(); else { bool identity = transform.isIdentity(); double minX, minY, maxX, maxY; minX = minY = std::numeric_limits<double>::max(); maxX = maxY = std::numeric_limits<double>::min(); for (unsigned i = 0; i < segments_.size(); ++i) { const Segment& s = segments_[i]; switch (s.type()) { case Segment::MoveTo: case Segment::LineTo: case Segment::CubicC1: case Segment::CubicC2: case Segment::CubicEnd: case Segment::QuadC: case Segment::QuadEnd: { if (identity) { minX = std::min(s.x(), minX); minY = std::min(s.y(), minY); maxX = std::max(s.x(), maxX); maxY = std::max(s.y(), maxY); } else { WPointF p = transform.map(WPointF(s.x(), s.y())); minX = std::min(p.x(), minX); minY = std::min(p.y(), minY); maxX = std::max(p.x(), maxX); maxY = std::max(p.y(), maxY); } break; } case Segment::ArcC: { const Segment& s2 = segments_[i+1]; if (identity) { WPointF tl(s.x() - s2.x(), s.y() - s2.y()); minX = std::min(tl.x(), minX); minY = std::min(tl.y(), minY); WPointF br(s.x() + s2.x(), s.y() + s2.y()); maxX = std::max(br.x(), maxX); maxY = std::max(br.y(), maxY); } else { WPointF p1 = transform.map(WPointF(s.x(), s.y())); WPointF p2 = transform.map(WPointF(s2.x(), s2.y())); WPointF tl(p1.x() - p2.x(), p1.y() - p2.y()); minX = std::min(tl.x(), minX); minY = std::min(tl.y(), minY); WPointF br(p1.x() + p2.x(), p1.y() + p2.y()); maxX = std::max(br.x(), maxX); maxY = std::max(br.y(), maxY); } i += 2; break; } default: assert(false); } } return WRectF(minX, minY, maxX - minX, maxY - minY); } }
void WPainter::drawEllipse(double x, double y, double width, double height) { drawEllipse(WRectF(x, y, width, height)); }
WRectF WFrozenFrameGlyph::boundingRect() const { static const double INFINITE_RADIUS = 1.0e10; return WRectF(-INFINITE_RADIUS, -INFINITE_RADIUS, INFINITE_RADIUS * 2, INFINITE_RADIUS * 2); }
void WStandardColorMap::paintLegend(WPainter *painter, const WRectF& area) const { painter->save(); WPainterPath clipPath; painter->setRenderHint(WPainter::Antialiasing, false); painter->setFont(labelFont_); int height; if (area.isNull()) { height = (int)painter->device()->height().value(); } else { clipPath.addRect(area); painter->setClipPath(clipPath); painter->setClipping(true); painter->translate(area.x(), area.y()); height = (int)area.height(); } int textHeight = (int)painter->font().sizeLength().toPixels(); // draw the colormap with a box around it int stripWidth = 50; createStrip(painter, WRectF(0, (int)(textHeight/2+0.5), (int)stripWidth, (int)(height-textHeight))); painter->setPen(WPen()); painter->setBrush(WBrush()); painter->drawRect(WRectF(0.5, (int)(textHeight/2) + 0.5, stripWidth, height-textHeight)); // draw the ticks + labels painter->translate(stripWidth, textHeight/2); if (continuous_) { int lineHeights = (int)(height/textHeight); int lhPerTick = 1 + tickSpacing_; int nbTicks = lineHeights % lhPerTick == 0 ? lineHeights/lhPerTick : lineHeights/lhPerTick + 1; int interval = (height-textHeight)/(nbTicks-1); int rest = (height-textHeight) % (nbTicks-1); int adjustedInterval = interval; double value = max_; double valDiff = (max_-min_)/(nbTicks-1); for (int i=0; i < nbTicks; i++) { painter->drawLine(0, 0.5, 4, 0.5); painter->drawText(10, -textHeight/2, 40, textHeight, AlignLeft | AlignMiddle, Wt::asString(value, format_)); value -= valDiff; if (rest > 0) { adjustedInterval = interval + 1; rest--; } else { adjustedInterval = interval; } painter->translate(0, adjustedInterval); } } else { // first paint tick for maximum value painter->drawLine(0, 0.5, 4, 0.5); painter->drawText(10, -textHeight/2, 100, textHeight, AlignLeft | AlignMiddle, Wt::asString(max_, format_)); // paint the rest of the ticks int nbTicks = colors_.size(); int prevDiff = 0; for (int i=nbTicks-1; i >= 0; i--) { double relPos = -(colors_[i].value()-max_)/(max_-min_); double diff = relPos*(height-textHeight); int roundedDiff = (int)(diff + 0.5); painter->translate(0, roundedDiff-prevDiff); painter->drawLine(0, 0.5, 4, 0.5); painter->drawText(10, -textHeight/2, 40, textHeight, AlignLeft | AlignMiddle, Wt::asString(colors_[i].value(), format_)); prevDiff = roundedDiff; } } painter->restore(); }