void WMeasurePaintDevice::drawPath(const WPainterPath& path) { if (path.isEmpty()) return; expandBounds(path.controlPointRect()); }
void WPainterPath::connectPath(const WPainterPath& path) { if (currentPosition() != path.beginPosition()) lineTo(path.beginPosition()); addPath(path); }
WPainterPath WTransform::map(const WPainterPath& path) const { if (isIdentity()) return path; WPainterPath result; if (isJavaScriptBound() || path.isJavaScriptBound()) { const WJavaScriptExposableObject *o = this; if (!isJavaScriptBound()) o = &path; result.assignBinding(*o, WT_CLASS ".gfxUtils.transform_apply(" + jsRef() + ',' + path.jsRef() + ')'); } const std::vector<WPainterPath::Segment> &sourceSegments = path.segments(); for (std::size_t i = 0; i < sourceSegments.size(); ++i) { double tx, ty; if (sourceSegments[i].type() == WPainterPath::Segment::ArcR || sourceSegments[i].type() == WPainterPath::Segment::ArcAngleSweep) { result.segments_.push_back(sourceSegments[i]); } else { map(sourceSegments[i].x(), sourceSegments[i].y(), &tx, &ty); result.segments_.push_back(WPainterPath::Segment(tx, ty, sourceSegments[i].type())); } } return result; }
void WPainterPath::addPath(const WPainterPath& path) { if (currentPosition() != path.beginPosition()) moveTo(path.beginPosition()); Utils::insert(segments_, path.segments_); }
void WMeasurePaintDevice::drawArc(const WRectF& rect, double startAngle, double spanAngle) { WPainterPath p; double r = std::max(rect.width(), rect.height()) / 2; double cx = rect.center().x(); double cy = rect.center().y(); p.arcMoveTo(cx, cy, r, startAngle); p.arcTo(cx, cy, r, startAngle, spanAngle); expandBounds(p.controlPointRect()); }
void WPainter::drawPolyline(const WT_ARRAY WPointF *points, int pointCount) { if (pointCount < 2) return; WPainterPath path; path.moveTo(points[0]); for (int i = 1; i < pointCount; ++i) path.lineTo(points[i]); WBrush oldBrush = WBrush(brush()); setBrush(WBrush()); drawPath(path); setBrush(oldBrush); }
void WPainter::drawPolygon(const WT_ARRAY WPointF *points, int pointCount /*, FillRule fillRule */) { if (pointCount < 2) return; WPainterPath path; path.moveTo(points[0]); for (int i = 1; i < pointCount; ++i) path.lineTo(points[i]); path.closeSubPath(); drawPath(path); }
void WPdfImage::drawPath(const WPainterPath& path) { if (path.isEmpty()) return; drawPlainPath(path); paintPath(); }
void WPainter::drawChord(const WRectF& rectangle, int startAngle, int spanAngle) { WTransform oldTransform = WTransform(worldTransform()); translate(rectangle.center().x(), rectangle.center().y()); scale(1., rectangle.height() / rectangle.width()); double start = startAngle / 16.; double span = spanAngle / 16.; WPainterPath path; path.arcMoveTo(0, 0, rectangle.width()/2., start); path.arcTo(0, 0, rectangle.width()/2., start, span); path.closeSubPath(); drawPath(path); setWorldTransform(oldTransform); }
void WRasterImage::drawPath(const WPainterPath& path) { if (!path.isEmpty()) { SkPath p; impl_->drawPlainPath(p, path); if (painter()->brush().style() != NoBrush) { impl_->canvas_->drawPath(p, impl_->fillPaint_); } if (painter()->pen().style() != NoPen) { impl_->canvas_->drawPath(p, impl_->strokePaint_); } } }
void WCartesianChart::renderLegendIcon(WPainter& painter, const WPointF& pos, const WDataSeries& series) const { switch (series.type()) { case BarSeries: { WPainterPath path; path.moveTo(-6, 8); path.lineTo(-6, -8); path.lineTo(6, -8); path.lineTo(6, 8); painter.setPen(series.pen()); painter.setBrush(series.brush()); painter.translate(pos.x() + 7.5, pos.y()); painter.drawPath(path); painter.translate(-(pos.x() + 7.5), -pos.y()); break; } case LineSeries: case CurveSeries: { painter.setPen(series.pen()); double offset = (series.pen().width() == 0 ? 0.5 : 0); painter.drawLine(pos.x(), pos.y() + offset, pos.x() + 16, pos.y() + offset); } // no break; case PointSeries: { WPainterPath path; drawMarker(series, path); if (!path.isEmpty()) { painter.translate(pos.x() + 8, pos.y()); painter.setPen(series.markerPen()); painter.setBrush(series.markerBrush()); painter.drawPath(path); painter.translate(- (pos.x() + 8), -pos.y()); } break; } } }
void WPainter::drawText(const WRectF& rectangle, WFlags<AlignmentFlag> alignmentFlags, TextFlag textFlag, const WString& text) { if (textFlag == TextSingleLine) drawText(rectangle, alignmentFlags, text); else { if (!(alignmentFlags & AlignVerticalMask)) alignmentFlags |= AlignTop; if (!(alignmentFlags & AlignHorizontalMask)) alignmentFlags |= AlignLeft; if (device_->features() & WPaintDevice::CanWordWrap) device_->drawText(rectangle.normalized(), alignmentFlags, textFlag, text); else if (device_->features() & WPaintDevice::HasFontMetrics) { #ifndef WT_TARGET_JAVA MultiLineTextRenderer renderer(*this, rectangle); AlignmentFlag horizontalAlign = alignmentFlags & AlignHorizontalMask; AlignmentFlag verticalAlign = alignmentFlags & AlignVerticalMask; /* * Oh irony: after all these years of hating CSS, we now * implemented an XHTML renderer for which we need to use the * same silly workarounds to render the text with all possible * alignment options */ WStringStream s; s << "<table style=\"width:" << (int)rectangle.width() << "px;\"" "cellspacing=\"0\"><tr>" "<td style=\"padding:0px;height:" << (int)rectangle.height() << "px;color:" << pen().color().cssText() << ";text-align:"; switch (horizontalAlign) { case AlignLeft: s << "left"; break; case AlignRight: s << "right"; break; case AlignCenter: s << "center"; break; default: break; } s << ";vertical-align:"; switch (verticalAlign) { case AlignTop: s << "top"; break; case AlignBottom: s << "bottom"; break; case AlignMiddle: s << "middle"; break; default: break; } s << ";" << font().cssText(false); s << "\">" << WWebWidget::escapeText(text, true).toUTF8() << "</td></tr></table>"; save(); /* * FIXME: what if there was already a clip path? We need to combine * them ... */ WPainterPath p; p.addRect(rectangle.x() + 1, rectangle.y() + 1, rectangle.width() - 2, rectangle.height() - 2); setClipPath(p); setClipping(true); renderer.render(WString::fromUTF8(s.str())); restore(); #endif // WT_TARGET_JAVA } else throw WException("WPainter::drawText(): device does not support " "TextWordWrap or FontMetrics"); } }
void WMeasurePaintDevice::drawPath(const WPainterPath& path) { expandBounds(path.controlPointRect()); }
void DrawShape::paintMap(WPaintDevice *paintDevice) { WPainter painter(paintDevice); painter.setRenderHint(WPainter::LowQualityShadows); painter.save(); if(!sfile.empty()) { vector<LABELS> label_list; OGRDataSource *poDS,*PointDS; string dfile = sfile + ".shp"; string shp = "g_4326/" + sfile + ".shp"; poDS = OGRSFDriverRegistrar::Open(shp.c_str(), FALSE ); //comment till here if(poDS==NULL) { printf( "Open failed.\n" ); exit( 1 ); } OGRLayer *poLayer; poLayer = poDS->GetLayerByName( sfile.c_str() ); // comment here OGRFeature *poFeature; OGREnvelope * psExtent = new OGREnvelope(); poLayer->GetExtent(psExtent); double xMin = psExtent->MinX; double yMin = psExtent->MinY; double xMax = psExtent->MaxX; double yMax = psExtent->MaxY; stringstream strm; strm << xMin; string exp; double scaleFactor; string bound_string = strm.str(); int size = bound_string.size(); size_t found=bound_string.find("+"); if (found!=string::npos) { exp = bound_string.substr(found+1,size); } if(exp.empty()) { stringstream strExtent; strExtent << yMin; bound_string = strExtent.str(); size = bound_string.size(); found = bound_string.find("+"); if(found!=string::npos) { exp = bound_string.substr(found+1,size); } } if(exp.empty()) { stringstream strExtent; strExtent << xMax; bound_string = strExtent.str(); size = bound_string.size(); found = bound_string.find("+"); if(found!=string::npos) { exp = bound_string.substr(found+1,size); } } if(exp.empty()) { stringstream strExtent; strExtent << yMax; bound_string = strExtent.str(); size = bound_string.size(); found = bound_string.find("+"); if(found!=string::npos) { exp = bound_string.substr(found+1,size); } } //cout << "EXXP: " << exp << endl; if(!exp.empty()) { int exponent = boost::lexical_cast<int>(exp); exponent-=3; scaleFactor = pow (10,exponent); } else { //cout << "EXXP is empty " << exp << endl; scaleFactor = 1; } xMin/=scaleFactor; xMax/=scaleFactor; yMin/=scaleFactor; yMax/=scaleFactor; double gWidth = xMax - xMin; double gHeight = yMax - yMin; double widthFactor = 1; double pwidth = abs(gWidth-gHeight); double s = gWidth - gHeight; if(s<0.16) gWidth = gHeight + 0.16; double ratio=gWidth/gHeight; //for zoom n pan if(increase_width<100 && increase_height<100){ painter.setWindow(xMin +(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor, yMax+(y_pos_shift-increase_height/2)/100*gHeight * widthFactor, gWidth* widthFactor*(100-increase_width)/100, gHeight * widthFactor*(-1+increase_height/100)); brush.setStyle(SolidPattern); brush.setColor(backcolor); painter.setBrush(brush); painter.drawRect(xMin +(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor, yMax+(y_pos_shift-increase_height/2)/100*gHeight * widthFactor, gWidth* widthFactor*(100-increase_width)/100, gHeight * widthFactor*(-1+increase_height/100)); } else{ painter.setWindow(xMin +x_pos_shift, yMax-y_pos_shift, 0, 0); } // for normal picture //painter.setWindow(xMin , yMax, gWidth* widthFactor, -gHeight * widthFactor); pwidth/=480; pwidth*=4; //if(iwidth<0.06) // iwidth=0.06; if(iwidth == 0.0015){ pen.setWidth(pwidth); } else { pen.setWidth(iwidth); } //std::cerr<<pwidth<<" "<<iwidth<<"\n"; pen.setColor(bordercolor); brush.setStyle(SolidPattern); brush.setColor(fillcolor); font= new WFont(); font->setSize(WLength(labelpercentage*gWidth*widthFactor)); painter.setFont(*font); painter.setPen(pen); painter.setBrush(brush); WPainterPath path; poLayer->ResetReading(); OGRPoint *centroid = new OGRPoint(); char label[100]; while( (poFeature = poLayer->GetNextFeature()) != NULL ) { centroid->empty(); label[0]=0; if(labelindex>0) { OGRFeatureDefn *PointFDefn = poLayer->GetLayerDefn(); OGRFieldDefn *PointFieldDefn = PointFDefn->GetFieldDefn(labelindex-1); if( PointFieldDefn->GetType() == OFTInteger ) sprintf(label, "%d", poFeature->GetFieldAsInteger(labelindex-1) ); else if( PointFieldDefn->GetType() == OFTReal ) sprintf(label, "%.3f", poFeature->GetFieldAsDouble(labelindex-1) ); else if( PointFieldDefn->GetType() == OFTString ) sprintf(label, "%s", poFeature->GetFieldAsString(labelindex-1) ); else sprintf(label, "%s", poFeature->GetFieldAsString(labelindex-1) ); } OGRGeometry *poGeometry; poGeometry = poFeature->GetGeometryRef(); if( poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) { OGRPoint *poPoint = (OGRPoint *) poGeometry; double x = poPoint->getX(); double y = poPoint->getY(); //painter.drawPoint(x/scaleFactor,y/scaleFactor); painter.drawEllipse(x/scaleFactor-0.005*gWidth*widthFactor,y/scaleFactor-0.005*gWidth*widthFactor,0.01*gWidth*widthFactor,0.01*gWidth*widthFactor); poGeometry->Centroid(centroid); } //end wkbpoint else if( poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbLineString ) { OGRLineString *poPoint = (OGRLineString *) poGeometry; for(int i=0;i<poPoint->getNumPoints();i++) { double x=poPoint->getX(i) ; double y = poPoint->getY(i); x/=scaleFactor; y/=scaleFactor; if(i==0) path = WPainterPath( WPointF(x, y)); else path.lineTo( x , y); } painter.drawPath(path); poGeometry->Centroid(centroid); } else if( (poGeometry != NULL) && wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon) { OGRPolygon *poPoint = (OGRPolygon *) poGeometry; OGRLinearRing *extring = poPoint->getExteriorRing(); int n = extring->getNumPoints(); double x, y; for(int i=0;i<n;i++) { x = extring->getX(i); y = extring->getY(i); x/=scaleFactor; y/=scaleFactor; if(i==0) path = WPainterPath( WPointF(x , y)); else path.lineTo( x , y); } painter.drawPath(path); poGeometry->Centroid(centroid); } else if( (poGeometry != NULL) && wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon) { double x, y; OGRMultiPolygon *poPoint = (OGRMultiPolygon *) poGeometry; int p = poPoint->getNumGeometries(); for(int k=0;k<p;k++) { OGRGeometry* geom = poPoint->getGeometryRef(k); OGRPolygon *poly = (OGRPolygon *) geom; OGRLinearRing *ring = poly->getExteriorRing(); for(int i=0;i<ring->getNumPoints();i++) { x = ring->getX(i); y = ring->getY(i); x/=scaleFactor; y/=scaleFactor; if(i==0) path = WPainterPath( WPointF(x , y)); else path.lineTo( x , y); } painter.drawPath(path); poGeometry->Centroid(centroid); } } if(labelindex>0 && !centroid->IsEmpty()){ LABELS l={centroid->getX(),centroid->getY(),label}; label_list.push_back(l); } } painter.restore(); //labelling the contents if(increase_width<100 && increase_height<100){ painter.setWindow(0.0, 0.0, (paintDevice->width()).value(),(paintDevice->height()).value()); font= new WFont(WFont::SansSerif); font->setSize(WLength(10*labelpercentage)); painter.setFont(*font); pen.setColor(labelcolor); painter.setPen(pen); std::vector<LABELS>::iterator the_iterator = label_list.begin(); double x, y, minx=(xMin+(-x_pos_shift+increase_width/2)/100*gWidth* widthFactor),miny=(yMax+(y_pos_shift-increase_height/2)/100*gHeight*widthFactor); double multx=(paintDevice->width().value())/(gWidth* widthFactor*(100-increase_width)/100); double multy=(paintDevice->height().value())/(gHeight*widthFactor*(-1+increase_height/100)); while( the_iterator != label_list.end() ) { x=((*the_iterator).x/scaleFactor-minx)*multx; y=((*the_iterator).y/scaleFactor-miny)*multy; painter.drawText(WRectF( x-(*the_iterator).label.size()*5*labelpercentage, y-5*labelpercentage, (*the_iterator).label.size() *10*labelpercentage,10*labelpercentage),AlignCenter,(*the_iterator).label); ++the_iterator; } pen.setColor(red); painter.setPen(pen); painter.setFont(*font); //painter.drawText(WRectF(paintDevice->width().value()-dfile.size()*10*labelpercentage,paintDevice->height().value()-10*labelpercentage*(paintDevice->height()).value(), dfile.size()*10*labelpercentage,10*labelpercentage ),AlignCenter,dfile); //this text is not seen in the picture when painted. } } }
void ShapesWidget::drawEmwebE(WPainter& painter) { WPainterPath p; /* Path copied from our SVG for half of the E */ p.moveTo(46.835084,58.783624); p.cubicTo(45.700172,58.783624,35.350098,58.911502,24.656354,63.283309); p.cubicTo(8.7595992,69.78907,0,82.38499,0,98.809238); p.cubicTo(0,115.20152,08.7595992,127.82141,24.656354,134.31119); p.cubicTo(35.350098,138.69099,45.700172,138.81088,46.835084,138.81088); p.lineTo(94.509362,138.81088); p.lineTo(94.509362,117.58323); p.lineTo(46.835084,117.58323); p.cubicTo(46.811106,117.58323,39.466151,117.47134,32.608727,114.53815); p.cubicTo(25.095932,111.34122,21.747144,106.47389,21.747144,98.809238); p.cubicTo(21.747144,91.120612,25.095932,86.269265,32.608727,83.064338); p.cubicTo(39.466151,80.123159,46.811106,80.027251,46.89103,80.027251); p.lineTo(94.509362,80.027251); p.lineTo(94.509362,58.783624); p.lineTo(46.835084,58.783624); painter.drawPath(p); painter.save(); painter.translate(0,-58.783624); painter.drawPath(p); painter.restore(); }
void WPdfImage::drawPlainPath(const WPainterPath& path) { if (path.isEmpty()) return; const std::vector<WPainterPath::Segment>& segments = path.segments(); if (segments.size() > 0 && segments[0].type() != SegmentType::MoveTo) HPDF_Page_MoveTo(page_, 0, 0); for (unsigned i = 0; i < segments.size(); ++i) { const WPainterPath::Segment s = segments[i]; switch (s.type()) { case SegmentType::MoveTo: HPDF_Page_MoveTo(page_, s.x(), s.y()); break; case SegmentType::LineTo: HPDF_Page_LineTo(page_, s.x(), s.y()); break; case SegmentType::CubicC1: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); const double x3 = segments[i+2].x(); const double y3 = segments[i+2].y(); HPDF_Page_CurveTo(page_, x1, y1, x2, y2, x3, y3); i += 2; break; } case SegmentType::CubicC2: case SegmentType::CubicEnd: assert(false); case SegmentType::ArcC: { const double x = s.x(); const double y = s.y(); const double radius = segments[i+1].x(); double ang1 = segments[i+2].x(); double ang2 = ang1 + segments[i+2].y(); HPDF_Page_Arc(page_, x, y, radius, ang1 + 90, ang2 + 90); i += 2; break; } case SegmentType::ArcR: case SegmentType::ArcAngleSweep: assert(false); case SegmentType::QuadC: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); // or CurveTo3 ?? Are these any different ?? HPDF_Page_CurveTo2(page_, x1, y1, x2, y2); i += 1; break; } case SegmentType::QuadEnd: assert(false); } } }
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 WRasterImage::Impl::drawPlainPath(SkPath &p, const WPainterPath& path) { const std::vector<WPainterPath::Segment>& segments = path.segments(); if (segments.size() > 0 && segments[0].type() != WPainterPath::Segment::MoveTo) p.moveTo(SkDoubleToScalar(0), SkDoubleToScalar(0)); for (unsigned i = 0; i < segments.size(); ++i) { const WPainterPath::Segment s = segments[i]; switch (s.type()) { case WPainterPath::Segment::MoveTo: p.moveTo(SkDoubleToScalar(s.x()), SkDoubleToScalar(s.y())); break; case WPainterPath::Segment::LineTo: p.lineTo(SkDoubleToScalar(s.x()), SkDoubleToScalar(s.y())); break; case WPainterPath::Segment::CubicC1: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); const double x3 = segments[i+2].x(); const double y3 = segments[i+2].y(); p.cubicTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2), SkDoubleToScalar(x3), SkDoubleToScalar(y3)); i += 2; break; } case WPainterPath::Segment::CubicC2: case WPainterPath::Segment::CubicEnd: assert(false); case WPainterPath::Segment::ArcC: { const double x = s.x(); const double y = s.y(); const double width = segments[i+1].x(); const double height = segments[i+1].y(); const double startAngle = segments[i+2].x(); const double sweepAngle = segments[i+2].y(); SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(x - width), SkDoubleToScalar(y - height), SkDoubleToScalar(width * 2.0), SkDoubleToScalar(height * 2.0)); if (sweepAngle != 360) p.arcTo(rect, SkDoubleToScalar(-startAngle), SkDoubleToScalar(-sweepAngle), false); else p.addOval(rect, SkPath::kCCW_Direction); i += 2; break; } case WPainterPath::Segment::ArcR: case WPainterPath::Segment::ArcAngleSweep: assert(false); case WPainterPath::Segment::QuadC: { const double x1 = s.x(); const double y1 = s.y(); const double x2 = segments[i+1].x(); const double y2 = segments[i+1].y(); p.quadTo(SkDoubleToScalar(x1), SkDoubleToScalar(y1), SkDoubleToScalar(x2), SkDoubleToScalar(y2)); i += 1; break; } case WPainterPath::Segment::QuadEnd: assert(false); } } }
void ShapesWidget::drawEmwebMW(WPainter& painter) { WPainterPath p; /* Path copied from our SVG for one fourth of the MW */ p.moveTo(120.59634,24.072913); p.cubicTo(116.12064,34.518895,115.98477,44.605222,115.98477,45.732141); p.lineTo(115.98477,138.81088); p.lineTo(137.7399,138.81088); p.lineTo(137.7399,45.732141); p.cubicTo(137.7399,45.708164,137.83581,38.53904,140.84892,31.841463); p.cubicTo(144.14176,24.512492,149.113,21.235634,156.98545,21.235634); p.cubicTo(164.8499,21.235634,169.81314,24.512492,173.10599,31.841463); p.cubicTo(176.10311,38.53904,176.215,45.708164,176.215,45.780095); p.lineTo(176.215,70.41343); p.lineTo(197.97014,70.41343); p.lineTo(197.97014,45.732141); p.cubicTo(197.97014,44.605222,197.83427,34.518895,193.35057,24.072913); p.cubicTo(186.70894,8.5517985,173.77734,0,156.99344,0); p.cubicTo(140.17756,0,127.25396,8.5517985,120.59634,24.072913); /* * Paint it four times, translated and inverted */ painter.drawPath(p); const double dx = 176. - 115.98477; painter.save(); painter.translate(dx, 0); painter.drawPath(p); painter.translate(dx, 0); painter.scale(-1, -1); painter.translate(0, -138.81088); painter.translate(-115.98477 - 197.95 - dx, 0); painter.drawPath(p); painter.translate(dx, 0); painter.drawPath(p); painter.restore(); }
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(); }