int draw_image_to_cairo_target (cairo_t *cairoTarget, gerbv_image_t *image, gdouble pixelWidth, enum draw_mode drawMode, gerbv_selection_info_t *selectionInfo, gerbv_render_info_t *renderInfo, gboolean allowOptimization, gerbv_user_transformation_t transform, gboolean pixelOutput) { const int hole_cross_inc_px = 8; struct gerbv_net *net, *polygonStartNet=NULL; double x1, y1, x2, y2, cp_x=0, cp_y=0; gdouble *p, p0, p1, dx, dy, lineWidth, r; gerbv_netstate_t *oldState; gerbv_layer_t *oldLayer; cairo_operator_t drawOperatorClear, drawOperatorDark; gboolean invertPolarity = FALSE, oddWidth = FALSE; gdouble minX=0, minY=0, maxX=0, maxY=0; gdouble criticalRadius; gdouble scaleX = transform.scaleX; gdouble scaleY = transform.scaleY; gboolean limitLineWidth = TRUE; gboolean displayPixel = TRUE; /* If we are scaling the image at all, ignore the line width checks * since scaled up lines can still be visible */ if ((scaleX != 1)||(scaleY != 1)){ limitLineWidth = FALSE; } if (transform.mirrorAroundX) scaleY *= -1; if (transform.mirrorAroundY) scaleX *= -1; cairo_translate (cairoTarget, transform.translateX, transform.translateY); cairo_scale (cairoTarget, scaleX, scaleY); cairo_rotate (cairoTarget, transform.rotation); gboolean useOptimizations = allowOptimization; /* If the user is using any transformations for this layer, then don't * bother using rendering optimizations */ if ((fabs(transform.translateX) > 0.00001) || (fabs(transform.translateY) > 0.00001) || (fabs(transform.scaleX - 1) > 0.00001) || (fabs(transform.scaleY - 1) > 0.00001) || (fabs(transform.rotation) > 0.00001) || transform.mirrorAroundX || transform.mirrorAroundY) useOptimizations = FALSE; if (useOptimizations && pixelOutput) { minX = renderInfo->lowerLeftX; minY = renderInfo->lowerLeftY; maxX = renderInfo->lowerLeftX + (renderInfo->displayWidth / renderInfo->scaleFactorX); maxY = renderInfo->lowerLeftY + (renderInfo->displayHeight / renderInfo->scaleFactorY); } /* do initial justify */ cairo_translate (cairoTarget, image->info->imageJustifyOffsetActualA, image->info->imageJustifyOffsetActualB); /* set the fill rule so aperture holes are cleared correctly */ cairo_set_fill_rule (cairoTarget, CAIRO_FILL_RULE_EVEN_ODD); /* offset image */ cairo_translate (cairoTarget, image->info->offsetA, image->info->offsetB); /* do image rotation */ cairo_rotate (cairoTarget, image->info->imageRotation); /* load in polarity operators depending on the image polarity */ invertPolarity = transform.inverted; if (image->info->polarity == GERBV_POLARITY_NEGATIVE) invertPolarity = !invertPolarity; if (drawMode == DRAW_SELECTIONS) invertPolarity = FALSE; if (invertPolarity) { drawOperatorClear = CAIRO_OPERATOR_OVER; drawOperatorDark = CAIRO_OPERATOR_CLEAR; cairo_set_operator (cairoTarget, CAIRO_OPERATOR_OVER); cairo_paint (cairoTarget); cairo_set_operator (cairoTarget, CAIRO_OPERATOR_CLEAR); } else { drawOperatorClear = CAIRO_OPERATOR_CLEAR; drawOperatorDark = CAIRO_OPERATOR_OVER; } /* next, push two cairo states to simulate the first layer and netstate translations (these will be popped when another layer or netstate is started */ cairo_save (cairoTarget); cairo_save (cairoTarget); /* store the current layer and netstate so we know when they change */ oldLayer = image->layers; oldState = image->states; for (net = image->netlist->next; net != NULL; net = gerbv_image_return_next_renderable_object(net)) { /* check if this is a new layer */ if (net->layer != oldLayer){ /* it's a new layer, so recalculate the new transformation matrix for it */ cairo_restore (cairoTarget); cairo_restore (cairoTarget); cairo_save (cairoTarget); /* do any rotations */ cairo_rotate (cairoTarget, net->layer->rotation); /* handle the layer polarity */ if ((net->layer->polarity == GERBV_POLARITY_CLEAR)^invertPolarity) { cairo_set_operator (cairoTarget, CAIRO_OPERATOR_CLEAR); drawOperatorClear = CAIRO_OPERATOR_OVER; drawOperatorDark = CAIRO_OPERATOR_CLEAR; } else { cairo_set_operator (cairoTarget, CAIRO_OPERATOR_OVER); drawOperatorClear = CAIRO_OPERATOR_CLEAR; drawOperatorDark = CAIRO_OPERATOR_OVER; } /* Draw any knockout areas */ gerbv_knockout_t *ko = &net->layer->knockout; if (ko->firstInstance == TRUE) { cairo_operator_t oldOperator = cairo_get_operator (cairoTarget); if (ko->polarity == GERBV_POLARITY_CLEAR) { cairo_set_operator (cairoTarget, drawOperatorClear); } else { cairo_set_operator (cairoTarget, drawOperatorDark); } cairo_new_path (cairoTarget); cairo_rectangle (cairoTarget, ko->lowerLeftX - ko->border, ko->lowerLeftY - ko->border, ko->width + 2*ko->border, ko->height + 2*ko->border); draw_fill (cairoTarget, drawMode, selectionInfo, image, net); cairo_set_operator (cairoTarget, oldOperator); } /* Finally, reapply old netstate transformation */ cairo_save (cairoTarget); draw_apply_netstate_transformation (cairoTarget, net->state); oldLayer = net->layer; } /* check if this is a new netstate */ if (net->state != oldState){ /* pop the transformation matrix back to the "pre-state" state and resave it */ cairo_restore (cairoTarget); cairo_save (cairoTarget); /* it's a new state, so recalculate the new transformation matrix for it */ draw_apply_netstate_transformation (cairoTarget, net->state); oldState = net->state; } /* if we are only drawing from the selection buffer, search if this net is in the buffer */ if (drawMode == DRAW_SELECTIONS) { /* this flag makes sure we don't draw any unintentional polygons... if we've successfully entered a polygon (the first net matches, and we don't want to check the nets inside the polygon) then polygonStartNet will be set */ if (!polygonStartNet) { if (!draw_net_is_in_selection_buffer_remove (net, selectionInfo, FALSE)) continue; } } /* step and repeat */ gerbv_step_and_repeat_t *sr = &net->layer->stepAndRepeat; int ix, iy; for (ix = 0; ix < sr->X; ix++) { for (iy = 0; iy < sr->Y; iy++) { double sr_x = ix * sr->dist_X; double sr_y = iy * sr->dist_Y; if (useOptimizations && pixelOutput && ((net->boundingBox.right+sr_x < minX) || (net->boundingBox.left+sr_x > maxX) || (net->boundingBox.top+sr_y < minY) || (net->boundingBox.bottom+sr_y > maxY))) { continue; } x1 = net->start_x + sr_x; y1 = net->start_y + sr_y; x2 = net->stop_x + sr_x; y2 = net->stop_y + sr_y; /* translate circular x,y data as well */ if (net->cirseg) { cp_x = net->cirseg->cp_x + sr_x; cp_y = net->cirseg->cp_y + sr_y; } /* render any labels attached to this net */ /* NOTE: this is currently only used on PNP files, so we may make some assumptions here... */ if (net->label) { cairo_set_font_size (cairoTarget, 0.05); cairo_save (cairoTarget); cairo_move_to (cairoTarget, x1, y1); cairo_scale (cairoTarget, 1, -1); cairo_show_text (cairoTarget, net->label->str); cairo_restore (cairoTarget); } /* Polygon area fill routines */ switch (net->interpolation) { case GERBV_INTERPOLATION_PAREA_START : draw_render_polygon_object (net, cairoTarget, sr_x, sr_y, image, drawMode, selectionInfo, pixelOutput); continue; case GERBV_INTERPOLATION_DELETED: continue; default : break; } /* * If aperture state is off we allow use of undefined apertures. * This happens when gerber files starts, but hasn't decided on * which aperture to use. */ if (image->aperture[net->aperture] == NULL) continue; switch (net->aperture_state) { case GERBV_APERTURE_STATE_ON : /* if the aperture width is truly 0, then render as a 1 pixel width line. 0 diameter apertures are used by some programs to draw labels, etc, and they are rendered by other programs as 1 pixel wide */ /* NOTE: also, make sure all lines are at least 1 pixel wide, so they always show up at low zoom levels */ if (limitLineWidth&&((image->aperture[net->aperture]->parameter[0] < pixelWidth)&& (pixelOutput))) criticalRadius = pixelWidth/2.0; else criticalRadius = image->aperture[net->aperture]->parameter[0]/2.0; lineWidth = criticalRadius*2.0; // convert to a pixel integer cairo_user_to_device_distance (cairoTarget, &lineWidth, &x1); if (pixelOutput) { lineWidth = round(lineWidth); if ((int)lineWidth % 2) { oddWidth = TRUE; } else { oddWidth = FALSE; } } cairo_device_to_user_distance (cairoTarget, &lineWidth, &x1); cairo_set_line_width (cairoTarget, lineWidth); switch (net->interpolation) { case GERBV_INTERPOLATION_x10 : case GERBV_INTERPOLATION_LINEARx01 : case GERBV_INTERPOLATION_LINEARx001 : case GERBV_INTERPOLATION_LINEARx1 : cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_ROUND); /* weed out any lines that are * obviously not going to * render on the visible screen */ switch (image->aperture[net->aperture]->type) { case GERBV_APTYPE_CIRCLE : if (renderInfo->show_cross_on_drill_holes && image->layertype == GERBV_LAYERTYPE_DRILL) { /* Draw center crosses on slot hole */ cairo_set_line_width (cairoTarget, pixelWidth); cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_SQUARE); r = image->aperture[net->aperture]->parameter[0]/2.0 + hole_cross_inc_px*pixelWidth; draw_cairo_cross (cairoTarget, x1, y1, r); draw_cairo_cross (cairoTarget, x2, y2, r); cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_ROUND); cairo_set_line_width (cairoTarget, lineWidth); } draw_cairo_move_to (cairoTarget, x1, y1, oddWidth, pixelOutput); draw_cairo_line_to (cairoTarget, x2, y2, oddWidth, pixelOutput); draw_stroke (cairoTarget, drawMode, selectionInfo, image, net); break; case GERBV_APTYPE_RECTANGLE : dx = image->aperture[net->aperture]->parameter[0]/2; dy = image->aperture[net->aperture]->parameter[1]/2; if(x1 > x2) dx = -dx; if(y1 > y2) dy = -dy; cairo_new_path(cairoTarget); draw_cairo_move_to (cairoTarget, x1 - dx, y1 - dy, FALSE, pixelOutput); draw_cairo_line_to (cairoTarget, x1 - dx, y1 + dy, FALSE, pixelOutput); draw_cairo_line_to (cairoTarget, x2 - dx, y2 + dy, FALSE, pixelOutput); draw_cairo_line_to (cairoTarget, x2 + dx, y2 + dy, FALSE, pixelOutput); draw_cairo_line_to (cairoTarget, x2 + dx, y2 - dy, FALSE, pixelOutput); draw_cairo_line_to (cairoTarget, x1 + dx, y1 - dy, FALSE, pixelOutput); draw_fill (cairoTarget, drawMode, selectionInfo, image, net); break; /* TODO: for now, just render ovals or polygons like a circle */ case GERBV_APTYPE_OVAL : case GERBV_APTYPE_POLYGON : draw_cairo_move_to (cairoTarget, x1,y1, oddWidth, pixelOutput); draw_cairo_line_to (cairoTarget, x2,y2, oddWidth, pixelOutput); draw_stroke (cairoTarget, drawMode, selectionInfo, image, net); break; /* macros can only be flashed, so ignore any that might be here */ default: GERB_COMPILE_WARNING(_("Skipped aperture type \"%s\""), _(aperture_names[image->aperture[net->aperture]->type])); break; } break; case GERBV_INTERPOLATION_CW_CIRCULAR : case GERBV_INTERPOLATION_CCW_CIRCULAR : /* cairo doesn't have a function to draw oval arcs, so we must * draw an arc and stretch it by scaling different x and y values */ cairo_new_path(cairoTarget); if (image->aperture[net->aperture]->type == GERBV_APTYPE_RECTANGLE) { cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_SQUARE); } else { cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_ROUND); } cairo_save (cairoTarget); cairo_translate(cairoTarget, cp_x, cp_y); cairo_scale (cairoTarget, net->cirseg->width, net->cirseg->height); if (net->cirseg->angle2 > net->cirseg->angle1) { cairo_arc (cairoTarget, 0.0, 0.0, 0.5, DEG2RAD(net->cirseg->angle1), DEG2RAD(net->cirseg->angle2)); } else { cairo_arc_negative (cairoTarget, 0.0, 0.0, 0.5, DEG2RAD(net->cirseg->angle1), DEG2RAD(net->cirseg->angle2)); } cairo_restore (cairoTarget); draw_stroke (cairoTarget, drawMode, selectionInfo, image, net); break; default : GERB_COMPILE_WARNING(_("Skipped interpolation type %d"), net->interpolation); break; } break; case GERBV_APERTURE_STATE_OFF : break; case GERBV_APERTURE_STATE_FLASH : p = image->aperture[net->aperture]->parameter; cairo_save (cairoTarget); draw_cairo_translate_adjust(cairoTarget, x2, y2, pixelOutput); switch (image->aperture[net->aperture]->type) { case GERBV_APTYPE_CIRCLE : if (renderInfo->show_cross_on_drill_holes && image->layertype == GERBV_LAYERTYPE_DRILL) { /* Draw center cross on drill hole */ cairo_set_line_width (cairoTarget, pixelWidth); cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_SQUARE); r = p[0]/2.0 + hole_cross_inc_px*pixelWidth; draw_cairo_cross (cairoTarget, 0, 0, r); cairo_set_line_width (cairoTarget, lineWidth); cairo_set_line_cap (cairoTarget, CAIRO_LINE_CAP_ROUND); } gerbv_draw_circle(cairoTarget, p[0]); gerbv_draw_aperture_hole (cairoTarget, p[1], p[2], pixelOutput); break; case GERBV_APTYPE_RECTANGLE : // some CAD programs use very thin flashed rectangles to compose // logos/images, so we must make sure those display here displayPixel = pixelOutput; p0 = p[0]; p1 = p[1]; if (limitLineWidth && (p[0] < pixelWidth) && pixelOutput) { p0 = pixelWidth; displayPixel = FALSE; } if (limitLineWidth && (p[1] < pixelWidth) && pixelOutput) { p1 = pixelWidth; displayPixel = FALSE; } gerbv_draw_rectangle(cairoTarget, p0, p1, displayPixel); gerbv_draw_aperture_hole (cairoTarget, p[2], p[3], displayPixel); break; case GERBV_APTYPE_OVAL : gerbv_draw_oblong(cairoTarget, p[0], p[1]); gerbv_draw_aperture_hole (cairoTarget, p[2], p[3], pixelOutput); break; case GERBV_APTYPE_POLYGON : gerbv_draw_polygon(cairoTarget, p[0], p[1], p[2]); gerbv_draw_aperture_hole (cairoTarget, p[3], p[4], pixelOutput); break; case GERBV_APTYPE_MACRO : gerbv_draw_amacro(cairoTarget, drawOperatorClear, drawOperatorDark, image->aperture[net->aperture]->simplified, (gint)p[0], pixelWidth, drawMode, selectionInfo, image, net); break; default : GERB_MESSAGE(_("Unknown aperture type")); return 0; } /* and finally fill the path */ draw_fill (cairoTarget, drawMode, selectionInfo, image, net); cairo_restore (cairoTarget); break; default: GERB_MESSAGE(_("Unknown aperture state")); return 0; } } } } /* restore the initial two state saves (one for layer, one for netstate)*/ cairo_restore (cairoTarget); cairo_restore (cairoTarget); return 1; }
/* * Convert a gerber image to a GDK clip mask to be used when creating pixmap */ int draw_gdk_image_to_pixmap(GdkPixmap **pixmap, gerbv_image_t *image, double scale, double trans_x, double trans_y, gchar drawMode, gerbv_selection_info_t *selectionInfo, gerbv_render_info_t *renderInfo, gerbv_user_transformation_t transform) { GdkGC *gc = gdk_gc_new(*pixmap); GdkGC *pgc = gdk_gc_new(*pixmap); GdkGCValues gc_values; struct gerbv_net *net; gerbv_netstate_t *oldState; gerbv_layer_t *oldLayer; gint x1, y1, x2, y2; glong xlong1, ylong1, xlong2, ylong2; int p1, p2; int cir_width = 0, cir_height = 0; int cp_x = 0, cp_y = 0; GdkColor transparent, opaque; gerbv_polarity_t polarity; gdouble tempX,tempY; gdouble minX=0,minY=0,maxX=0,maxY=0; if (transform.inverted) { if (image->info->polarity == GERBV_POLARITY_POSITIVE) polarity = GERBV_POLARITY_NEGATIVE; else polarity = GERBV_POLARITY_POSITIVE; } else { polarity = image->info->polarity; } if (drawMode == DRAW_SELECTIONS) polarity = GERBV_POLARITY_POSITIVE; gboolean useOptimizations = TRUE; // if the user is using any transformations for this layer, then don't bother using rendering // optimizations if ((fabs(transform.translateX) > 0.00001) || (fabs(transform.translateY) > 0.00001) || (fabs(transform.scaleX - 1) > 0.00001) || (fabs(transform.scaleY - 1) > 0.00001) || (fabs(transform.rotation) > 0.00001) || transform.mirrorAroundX || transform.mirrorAroundY) useOptimizations = FALSE; // calculate the transformation matrix for the user_transformation options cairo_matrix_t fullMatrix, scaleMatrix; cairo_matrix_init (&fullMatrix, 1, 0, 0, 1, 0, 0); cairo_matrix_init (&scaleMatrix, 1, 0, 0, 1, 0, 0); cairo_matrix_translate (&fullMatrix, trans_x, trans_y); cairo_matrix_scale (&fullMatrix, scale, scale); cairo_matrix_scale (&scaleMatrix, scale, scale); /* offset image */ cairo_matrix_translate (&fullMatrix, transform.translateX, -1*transform.translateY); // don't use mirroring for the scale matrix gdouble scaleX = transform.scaleX; gdouble scaleY = -1*transform.scaleY; cairo_matrix_scale (&scaleMatrix, scaleX, -1*scaleY); if (transform.mirrorAroundX) scaleY *= -1; if (transform.mirrorAroundY) scaleX *= -1; cairo_matrix_scale (&fullMatrix, scaleX, scaleY); /* do image rotation */ cairo_matrix_rotate (&fullMatrix, transform.rotation); //cairo_matrix_rotate (&scaleMatrix, transform.rotation); /* do image rotation */ cairo_matrix_rotate (&fullMatrix, image->info->imageRotation); if (useOptimizations) { minX = renderInfo->lowerLeftX; minY = renderInfo->lowerLeftY; maxX = renderInfo->lowerLeftX + (renderInfo->displayWidth / renderInfo->scaleFactorX); maxY = renderInfo->lowerLeftY + (renderInfo->displayHeight / renderInfo->scaleFactorY); } if (image == NULL || image->netlist == NULL) { /* * Destroy GCs before exiting */ gdk_gc_unref(gc); gdk_gc_unref(pgc); return 0; } /* Set up the two "colors" we have */ opaque.pixel = 0; /* opaque will not let color through */ transparent.pixel = 1; /* transparent will let color through */ /* * Clear clipmask and set draw color depending image on image polarity */ if (polarity == GERBV_POLARITY_NEGATIVE) { gdk_gc_set_foreground(gc, &transparent); gdk_draw_rectangle(*pixmap, gc, TRUE, 0, 0, -1, -1); gdk_gc_set_foreground(gc, &opaque); } else { gdk_gc_set_foreground(gc, &opaque); gdk_draw_rectangle(*pixmap, gc, TRUE, 0, 0, -1, -1); gdk_gc_set_foreground(gc, &transparent); } oldLayer = image->layers; oldState = image->states; for (net = image->netlist->next ; net != NULL; net = gerbv_image_return_next_renderable_object(net)) { int repeat_X=1, repeat_Y=1; double repeat_dist_X=0.0, repeat_dist_Y=0.0; int repeat_i, repeat_j; /* * If step_and_repeat (%SR%) used, repeat the drawing; */ repeat_X = net->layer->stepAndRepeat.X; repeat_Y = net->layer->stepAndRepeat.Y; repeat_dist_X = net->layer->stepAndRepeat.dist_X; repeat_dist_Y = net->layer->stepAndRepeat.dist_Y; /* check if this is a new netstate */ if (net->state != oldState){ /* it's a new state, so recalculate the new transformation matrix for it */ draw_gdk_apply_netstate_transformation (&fullMatrix, &scaleMatrix, net->state); oldState = net->state; } /* check if this is a new layer */ /* for now, only do layer rotations in GDK rendering */ if (net->layer != oldLayer){ cairo_matrix_rotate (&fullMatrix, net->layer->rotation); oldLayer = net->layer; } if (drawMode == DRAW_SELECTIONS) { int i; gboolean foundNet = FALSE; for (i=0; i<selectionInfo->selectedNodeArray->len; i++){ gerbv_selection_item_t sItem = g_array_index (selectionInfo->selectedNodeArray, gerbv_selection_item_t, i); if (sItem.net == net) foundNet = TRUE; } if (!foundNet) continue; } for(repeat_i = 0; repeat_i < repeat_X; repeat_i++) { for(repeat_j = 0; repeat_j < repeat_Y; repeat_j++) { double sr_x = repeat_i * repeat_dist_X; double sr_y = repeat_j * repeat_dist_Y; if ((useOptimizations)&&((net->boundingBox.right+sr_x < minX) || (net->boundingBox.left+sr_x > maxX) || (net->boundingBox.top+sr_y < minY) || (net->boundingBox.bottom+sr_y > maxY))) { continue; } /* * If circle segment, scale and translate that one too */ if (net->cirseg) { tempX = net->cirseg->width; tempY = net->cirseg->height; cairo_matrix_transform_point (&scaleMatrix, &tempX, &tempY); cir_width = (int)round(tempX); cir_height = (int)round(tempY); tempX = net->cirseg->cp_x; tempY = net->cirseg->cp_y; cairo_matrix_transform_point (&fullMatrix, &tempX, &tempY); cp_x = (int)round(tempX); cp_y = (int)round(tempY); } /* * Set GdkFunction depending on if this (gerber) layer is inverted * and allow for the photoplot being negative. */ gdk_gc_set_function(gc, GDK_COPY); if ((net->layer->polarity == GERBV_POLARITY_CLEAR) != (polarity == GERBV_POLARITY_NEGATIVE)) gdk_gc_set_foreground(gc, &opaque); else gdk_gc_set_foreground(gc, &transparent); /* * Polygon Area Fill routines */ switch (net->interpolation) { case GERBV_INTERPOLATION_PAREA_START : draw_gdk_render_polygon_object (net,image,sr_x,sr_y,&fullMatrix, &scaleMatrix,gc,pgc,pixmap); continue; /* make sure we completely skip over any deleted nodes */ case GERBV_INTERPOLATION_DELETED: continue; default : break; } /* * If aperture state is off we allow use of undefined apertures. * This happens when gerber files starts, but hasn't decided on * which aperture to use. */ if (image->aperture[net->aperture] == NULL) { /* Commenting this out since it gets emitted every time you click on the screen if (net->aperture_state != GERBV_APERTURE_STATE_OFF) GERB_MESSAGE("Aperture D%d is not defined\n", net->aperture); */ continue; } /* * Scale points with window scaling and translate them */ tempX = net->start_x + sr_x; tempY = net->start_y + sr_y; cairo_matrix_transform_point (&fullMatrix, &tempX, &tempY); xlong1 = (int)round(tempX); ylong1 = (int)round(tempY); tempX = net->stop_x + sr_x; tempY = net->stop_y + sr_y; cairo_matrix_transform_point (&fullMatrix, &tempX, &tempY); xlong2 = (int)round(tempX); ylong2 = (int)round(tempY); /* if the object is way outside our view window, just skip over it in order to eliminate some GDK clipping problems at high zoom levels */ if ((xlong1 < -10000) && (xlong2 < -10000)) continue; if ((ylong1 < -10000) && (ylong2 < -10000)) continue; if ((xlong1 > 10000) && (xlong2 > 10000)) continue; if ((ylong1 > 10000) && (ylong2 > 10000)) continue; if (xlong1 > G_MAXINT) x1 = G_MAXINT; else if (xlong1 < G_MININT) x1 = G_MININT; else x1 = (int)xlong1; if (xlong2 > G_MAXINT) x2 = G_MAXINT; else if (xlong2 < G_MININT) x2 = G_MININT; else x2 = (int)xlong2; if (ylong1 > G_MAXINT) y1 = G_MAXINT; else if (ylong1 < G_MININT) y1 = G_MININT; else y1 = (int)ylong1; if (ylong2 > G_MAXINT) y2 = G_MAXINT; else if (ylong2 < G_MININT) y2 = G_MININT; else y2 = (int)ylong2; switch (net->aperture_state) { case GERBV_APERTURE_STATE_ON : tempX = image->aperture[net->aperture]->parameter[0]; cairo_matrix_transform_point (&scaleMatrix, &tempX, &tempY); p1 = (int)round(tempX); // p1 = (int)round(image->aperture[net->aperture]->parameter[0] * scale); if (image->aperture[net->aperture]->type == GERBV_APTYPE_RECTANGLE) gdk_gc_set_line_attributes(gc, p1, GDK_LINE_SOLID, GDK_CAP_PROJECTING, GDK_JOIN_MITER); else gdk_gc_set_line_attributes(gc, p1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_MITER); switch (net->interpolation) { case GERBV_INTERPOLATION_x10 : case GERBV_INTERPOLATION_LINEARx01 : case GERBV_INTERPOLATION_LINEARx001 : GERB_MESSAGE(_("Linear != x1\n")); gdk_gc_set_line_attributes(gc, p1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_MITER); gdk_draw_line(*pixmap, gc, x1, y1, x2, y2); gdk_gc_set_line_attributes(gc, p1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_MITER); break; case GERBV_INTERPOLATION_LINEARx1 : if (image->aperture[net->aperture]->type != GERBV_APTYPE_RECTANGLE) gdk_draw_line(*pixmap, gc, x1, y1, x2, y2); else { gint dx, dy; GdkPoint poly[6]; tempX = image->aperture[net->aperture]->parameter[0]/2; tempY = image->aperture[net->aperture]->parameter[1]/2; cairo_matrix_transform_point (&scaleMatrix, &tempX, &tempY); dx = (int)round(tempX); dy = (int)round(tempY); if(x1 > x2) dx = -dx; if(y1 > y2) dy = -dy; poly[0].x = x1 - dx; poly[0].y = y1 - dy; poly[1].x = x1 - dx; poly[1].y = y1 + dy; poly[2].x = x2 - dx; poly[2].y = y2 + dy; poly[3].x = x2 + dx; poly[3].y = y2 + dy; poly[4].x = x2 + dx; poly[4].y = y2 - dy; poly[5].x = x1 + dx; poly[5].y = y1 - dy; gdk_draw_polygon(*pixmap, gc, 1, poly, 6); } break; case GERBV_INTERPOLATION_CW_CIRCULAR : case GERBV_INTERPOLATION_CCW_CIRCULAR : gerbv_gdk_draw_arc(*pixmap, gc, cp_x, cp_y, cir_width, cir_height, net->cirseg->angle1, net->cirseg->angle2); break; default : break; } break; case GERBV_APERTURE_STATE_OFF : break; case GERBV_APERTURE_STATE_FLASH : tempX = image->aperture[net->aperture]->parameter[0]; tempY = image->aperture[net->aperture]->parameter[1]; cairo_matrix_transform_point (&scaleMatrix, &tempX, &tempY); p1 = (int)round(tempX); p2 = (int)round(tempY); tempX = image->aperture[net->aperture]->parameter[2]; cairo_matrix_transform_point (&scaleMatrix, &tempX, &tempY); switch (image->aperture[net->aperture]->type) { case GERBV_APTYPE_CIRCLE : gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p1); /* * If circle has an inner diameter we must remove * that part of the circle to make a hole in it. * We should actually support square holes too, * but due to laziness I don't. */ if (p2) { gdk_gc_get_values(gc, &gc_values); if (gc_values.foreground.pixel == opaque.pixel) { gdk_gc_set_foreground(gc, &transparent); gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p2); gdk_gc_set_foreground(gc, &opaque); } else { gdk_gc_set_foreground(gc, &opaque); gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p2); gdk_gc_set_foreground(gc, &transparent); } } break; case GERBV_APTYPE_RECTANGLE: gerbv_gdk_draw_rectangle(*pixmap, gc, TRUE, x2, y2, p1, p2); break; case GERBV_APTYPE_OVAL : gerbv_gdk_draw_oval(*pixmap, gc, TRUE, x2, y2, p1, p2); break; case GERBV_APTYPE_POLYGON : gerbv_gdk_draw_circle(*pixmap, gc, TRUE, x2, y2, p1); break; case GERBV_APTYPE_MACRO : gerbv_gdk_draw_amacro(*pixmap, gc, image->aperture[net->aperture]->simplified, scale, x2, y2); break; default : GERB_MESSAGE(_("Unknown aperture type\n")); return 0; } break; default : GERB_MESSAGE(_("Unknown aperture state\n")); return 0; } } } } /* * Destroy GCs before exiting */ gdk_gc_unref(gc); gdk_gc_unref(pgc); return 1; } /* image2pixmap */