//----------------------------------------------------------------------------- void CGDrawContext::drawLines (const CPoint* points, const int32_t& numLines) { CGContextRef context = beginCGContext (true, currentState.drawMode.integralMode ()); if (context) { applyLineStyle (context); if ((((int32_t)currentState.frameWidth) % 2)) CGContextTranslateCTM (context, 0.5f, -0.5f); CGPoint* cgPoints = new CGPoint[numLines*2]; for (int32_t i = 0; i < numLines * 2; i += 2) { if (currentState.drawMode.integralMode ()) { cgPoints[i].x = round (points[i].x); cgPoints[i+1].x = round (points[i+1].x); cgPoints[i].y = round (points[i].y); cgPoints[i+1].y = round (points[i+1].y); } else { cgPoints[i].x = points[i].x; cgPoints[i+1].x = points[i+1].x; cgPoints[i].y = points[i].y; cgPoints[i+1].y = points[i+1].y; } } CGContextStrokeLineSegments (context, cgPoints, numLines*2); delete [] cgPoints; releaseCGContext (context); } }
//----------------------------------------------------------------------------- void CGDrawContext::drawLines (const LineList& lines) { if (lines.size () == 0) return; CGContextRef context = beginCGContext (true, getDrawMode ().integralMode ()); if (context) { applyLineStyle (context); CGPoint* cgPoints = new CGPoint[lines.size () * 2]; uint32_t index = 0; VSTGUI_RANGE_BASED_FOR_LOOP(LineList, lines, LinePair, line) cgPoints[index] = CGPointFromCPoint (line.first); cgPoints[index+1] = CGPointFromCPoint (line.second); if (getDrawMode ().integralMode ()) { cgPoints[index] = pixelAlligned (cgPoints[index]); cgPoints[index+1] = pixelAlligned (cgPoints[index+1]); } index += 2; VSTGUI_RANGE_BASED_FOR_LOOP_END if (getDrawMode ().integralMode ()) { int32_t frameWidth = static_cast<int32_t> (currentState.frameWidth); if (frameWidth % 2) CGContextTranslateCTM (context, 0.5, 0.5); } CGContextStrokeLineSegments (context, cgPoints, lines.size () * 2); delete [] cgPoints; releaseCGContext (context); } }
void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool printing) { if (paintingDisabled()) return; // Note: This function assumes that point.x and point.y are integers (and that's currently always the case). float x = point.x(); float y = point.y(); float thickness = strokeThickness(); if (printing) { // When printing, use a minimum thickness of 0.5 in user space. // See bugzilla bug 4255 for details of why 0.5 is the right minimum thickness to use while printing. if (thickness < 0.5) thickness = 0.5; // When printing, use antialiasing instead of putting things on integral pixel boundaries. } else { // On screen, use a minimum thickness of 1.0 in user space (later rounded to an integral number in device space). if (thickness < 1) thickness = 1; // On screen, round all parameters to integer boundaries in device space. CGRect lineRect = roundToDevicePixels(FloatRect(x, y, width, thickness)); x = lineRect.origin.x; y = lineRect.origin.y; width = (int)(lineRect.size.width); thickness = lineRect.size.height; } // FIXME: How about using a rectangle fill instead of drawing a line? CGContextSaveGState(platformContext()); CGContextSetLineWidth(platformContext(), thickness); CGContextSetShouldAntialias(platformContext(), printing); float halfThickness = thickness / 2; CGPoint linePoints[2]; linePoints[0].x = x + halfThickness; linePoints[0].y = y + halfThickness; linePoints[1].x = x + width - halfThickness; linePoints[1].y = y + halfThickness; CGContextStrokeLineSegments(platformContext(), linePoints, 2); CGContextRestoreGState(platformContext()); }
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar) { if (paintingDisabled()) return; // These are the same for misspelling or bad grammar const int patternHeight = 3; // 3 rows ASSERT(cMisspellingLineThickness == patternHeight); const int patternWidth = 4; // 4 pixels ASSERT(patternWidth == cMisspellingLinePatternWidth); // Make sure to draw only complete dots. // NOTE: Code here used to shift the underline to the left and increase the width // to make sure everything gets underlined, but that results in drawing out of // bounds (e.g. when at the edge of a view) and could make it appear that the // space between adjacent misspelled words was underlined. // allow slightly more considering that the pattern ends with a transparent pixel int widthMod = width % patternWidth; if (patternWidth - widthMod > cMisspellingLinePatternGapWidth) width -= widthMod; // Draw the underline CGContextRef context = platformContext(); CGContextSaveGState(context); const Color& patternColor = grammar ? grammarPatternColor() : spellingPatternColor(); setCGStrokeColor(context, patternColor); wkSetPatternPhaseInUserSpace(context, point); CGContextSetBlendMode(context, kCGBlendModeNormal); // 3 rows, each offset by half a pixel for blending purposes const CGPoint upperPoints [] = {{point.x(), point.y() + patternHeight - 2.5 }, {point.x() + width, point.y() + patternHeight - 2.5}}; const CGPoint middlePoints [] = {{point.x(), point.y() + patternHeight - 1.5 }, {point.x() + width, point.y() + patternHeight - 1.5}}; const CGPoint lowerPoints [] = {{point.x(), point.y() + patternHeight - 0.5 }, {point.x() + width, point.y() + patternHeight - 0.5 }}; // Dash lengths for the top and bottom of the error underline are the same. // These are magic. static const float edge_dash_lengths[] = {2.0f, 2.0f}; static const float middle_dash_lengths[] = {2.76f, 1.24f}; static const float edge_offset = -(edge_dash_lengths[1] - 1.0f) / 2.0f; static const float middle_offset = -(middle_dash_lengths[1] - 1.0f) / 2.0f; // Line opacities. Once again, these are magic. const float upperOpacity = 0.33f; const float middleOpacity = 0.75f; const float lowerOpacity = 0.88f; //Top line CGContextSetLineDash(context, edge_offset, edge_dash_lengths, sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0])); CGContextSetAlpha(context, upperOpacity); CGContextStrokeLineSegments(context, upperPoints, 2); // Middle line CGContextSetLineDash(context, middle_offset, middle_dash_lengths, sizeof(middle_dash_lengths) / sizeof(middle_dash_lengths[0])); CGContextSetAlpha(context, middleOpacity); CGContextStrokeLineSegments(context, middlePoints, 2); // Bottom line CGContextSetLineDash(context, edge_offset, edge_dash_lengths, sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0])); CGContextSetAlpha(context, lowerOpacity); CGContextStrokeLineSegments(context, lowerPoints, 2); CGContextRestoreGState(context); }