void GBitmap::init(const GBitmap &ref, const GRect &rect, int border) { GMonitorLock lock(monitor()); // test bitmap physical equality if (this == &ref) { GBitmap tmp; tmp.grays = grays; tmp.border = border; tmp.bytes_per_row = bytes_per_row; tmp.ncolumns = ncolumns; tmp.nrows = nrows; tmp.bytes = bytes; tmp.gbytes_data.swap(gbytes_data); tmp.grle.swap(grle); bytes = 0 ; init(tmp, rect, border); } else { GMonitorLock lock(ref.monitor()); // create empty bitmap init(rect.height(), rect.width(), border); grays = ref.grays; // compute destination rectangle GRect rect2(0, 0, ref.columns(), ref.rows() ); rect2.intersect(rect2, rect); rect2.translate(-rect.xmin, -rect.ymin); // copy bits if (! rect2.isempty()) { for (int y=rect2.ymin; y<rect2.ymax; y++) { unsigned char *dst = (*this)[y]; const unsigned char *src = ref[y+rect.ymin] + rect.xmin; for (int x=rect2.xmin; x<rect2.xmax; x++) dst[x] = src[x]; } } } }
GP<GBitmap> JB2Image::get_bitmap(const GRect &rect, int subsample, int align, int dispy) const { if (width==0 || height==0) G_THROW( ERR_MSG("JB2Image.cant_create") ); int rxmin = rect.xmin * subsample; int rymin = rect.ymin * subsample; int swidth = rect.width(); int sheight = rect.height(); int border = ((swidth + align - 1) & ~(align - 1)) - swidth; GP<GBitmap> bm = GBitmap::create(sheight, swidth, border); bm->set_grays(1+subsample*subsample); for (int blitno = 0; blitno < get_blit_count(); blitno++) { const JB2Blit *pblit = get_blit(blitno); const JB2Shape &pshape = get_shape(pblit->shapeno); if (pshape.bits) bm->blit(pshape.bits, pblit->left-rxmin, pblit->bottom-rymin+dispy, subsample); } return bm; }
void MapArea::draw(const GRect & bm_rect, const GP<GBitmap> & bm_in, GRect & pm_rect, GP<GPixmap> & pm_out, DRAW_MODE draw_mode) // Draws itself into the specified bitmap. The bm_rect should be // in the pane's coordinates. Since GBitmap may not contain color // information, we will create a color GPixmap patch (pm_out), where we // will actually be drawing. The pm_rect is a rectangle in // pane coordinates where this pm_out should go to. { DEBUG_MSG("MapArea::draw(): Highlighting " << gmap_area->url << ":" << gmap_area->target << "\n"); DEBUG_MAKE_INDENT(3); if (pane) { GRect brect=gmap_area->get_bound_rect(); mapper->map(brect); brect.inflate(3, 3); GRect irect; if (irect.intersect(bm_rect, brect)) { pm_rect=irect; irect.translate(-bm_rect.xmin, -bm_rect.ymin); pm_out=GPixmap::create(*bm_in, GRect(irect.xmin, bm_in->rows()-irect.ymax, irect.width(), irect.height())); if (!isInactiveOutlineMode()) if (draw_mode==DRAW_INACTIVE || draw_mode==DRAW_ACTIVE) ma_drawInactive(pm_rect, pm_out); if (!isActiveOutlineMode()) if (draw_mode==APPLY_ACTIVE || draw_mode==DRAW_ACTIVE) ma_applyActive(pm_rect, pm_out); } } }
PrintingPathContur::PrintingPathContur(Path *sourcePath, double boardXSize, double boardYSize, double nozzleDiameter) :PathContur(boardXSize, boardYSize, nozzleDiameter), mLast(0) { mWarnings = 0; if(sourcePath==0) return; Path *nextPath = sourcePath; while(nextPath) { GShape *next = nextPath->firstElement; while(next) { switch(next->type()) { case GSHAPE_LINE: { GLine *line = (GLine*)next; if(fabs(line->width-nozzleDiameter)<0.0001L) { addShape(new GLine(line->p1, line->p2, nozzleDiameter, true)); } else if(line->width>nozzleDiameter) { GPoint a = line->p2 - line->p1; a.vectorNormalize(); GPoint o = GPoint(a.y, -a.x); o *= nozzleDiameter; int c = line->width/2.0L/nozzleDiameter+1.0L; const double edge = (line->width-nozzleDiameter)/2.0L; for(int i=0; i<=c; i++) { GPoint s = a*edgeDelta(nozzleDiameter, line->width, o*i); if((o*i).vectorLength()<=edge) { addShape(new GLine(line->p1+o*i-s, line->p2+o*i+s, nozzleDiameter, true)); if(i!=0) addShape(new GLine(line->p1-o*i-s, line->p2-o*i+s, nozzleDiameter, true)); } else { o.vectorNormalize(); GPoint s = a*edgeDelta(nozzleDiameter, line->width, o*edge); addShape(new GLine(line->p1+o*edge-s, line->p2+o*edge+s, nozzleDiameter, true)); addShape(new GLine(line->p1-o*edge-s, line->p2-o*edge+s, nozzleDiameter, true)); break; } } } else { mWarnings = ERROR_DIAMETER; } break; } case GSHAPE_CIRCLE: { GCircle *circle = (GCircle*)next; if(circle->radius >= nozzleDiameter) { int c = circle->radius/nozzleDiameter; for(int i=0; i<=c; i++) { double r = circle->radius - nozzleDiameter/2.0L - i*nozzleDiameter; if(r >= nozzleDiameter/2.0L) { GCircle *result = new GCircle(circle->center, r, nozzleDiameter); result->outer = i==0; addShape(result); } else { GCircle *result = new GCircle(circle->center, nozzleDiameter/2.0L, nozzleDiameter); result->outer = i==0; addShape(result); break; } } } else { mWarnings = ERROR_DIAMETER; } break; } case GSHAPE_RECT: { GRect *rect = (GRect*)next; if(rect->width()>=nozzleDiameter && rect->height()>=nozzleDiameter) { int c = rect->height()/nozzleDiameter; GPoint pl(rect->topLeft.x+nozzleDiameter/2.0L, rect->bottomRight.y); GPoint pr(rect->bottomRight.x-nozzleDiameter/2.0L,rect->bottomRight.y); double y =pl.y; for(int i=0; i<=c; i++) { pr.y = pl.y = y + nozzleDiameter*i+nozzleDiameter/2.0L; if(pr.y<rect->topLeft.y-nozzleDiameter/2.0L) { addShape(new GLine(pl, pr, nozzleDiameter, true)); } else { pr.y = pl.y = rect->topLeft.y-nozzleDiameter/2.0L; addShape(new GLine(pl, pr, nozzleDiameter, true)); break; } } addShape(new GLine(GPoint(rect->topLeft.x+nozzleDiameter/2.0L, rect->topLeft.y-nozzleDiameter/2.0L), \ GPoint(rect->topLeft.x+nozzleDiameter/2.0L, rect->bottomRight.y+nozzleDiameter/2.0L), nozzleDiameter, true)); addShape(new GLine(GPoint(rect->bottomRight.x-nozzleDiameter/2.0L, rect->topLeft.y-nozzleDiameter/2.0L), \ GPoint(rect->bottomRight.x-nozzleDiameter/2.0L, rect->bottomRight.y+nozzleDiameter/2.0L), nozzleDiameter, true)); } else { mWarnings = ERROR_DIAMETER; } break; } } next = next->next; } nextPath = nextPath->next; } }
void MapRect::makeFrame(const GRect & mod_rect, GPixmap * pm, const GRect & pm_rect, int top_margin, int right_margin, int bottom_margin, int left_margin) // pm_rect is the place in pane coordinates where pm is supposed // to go. mod_rect is the place in pane coordinates, which should // be modified (all or part of it) // margins define distances from mod_rect's sides to the sides of // the rectangular map area. If they're positive, it means, that // mod_rect is completely inside the map area. Otherwise part of // it is outside { int dst_x, dst_y; // TOP for(dst_y=mod_rect.height()-1;dst_y>mod_rect.height()-1-(gmap_area->border_width-top_margin) && dst_y>=0;dst_y--) { int distance=(mod_rect.height()-1-dst_y)+top_margin; int left=-left_margin+distance; int right=mod_rect.width()+right_margin-distance; if (left<0) left=0; if (right>mod_rect.width()) right=mod_rect.width(); for(dst_x=left;dst_x<right;dst_x++) { GPixel & pix=(*pm)[dst_y+pm_rect.ymax-mod_rect.ymax] [dst_x+mod_rect.xmin-pm_rect.xmin]; int inc=shadow_pattern[distance]; if (inc>0) { pix.r=pix.r<=255-inc ? pix.r+inc : 255; pix.g=pix.g<=255-inc ? pix.g+inc : 255; pix.b=pix.b<=255-inc ? pix.b+inc : 255; } else { pix.r=pix.r>=-inc ? pix.r+inc : 0; pix.g=pix.g>=-inc ? pix.g+inc : 0; pix.b=pix.b>=-inc ? pix.b+inc : 0; } } } // RIGHT for(dst_x=mod_rect.width()-1;dst_x>mod_rect.width()-1-(gmap_area->border_width-right_margin) && dst_x>=0;dst_x--) { int distance=(mod_rect.width()-1-dst_x)+right_margin; int bottom=-bottom_margin+distance; int top=mod_rect.height()+top_margin-distance; if (bottom<0) bottom=0; if (top>mod_rect.height()) top=mod_rect.height(); for(dst_y=bottom;dst_y<top;dst_y++) { GPixel & pix=(*pm)[dst_y+pm_rect.ymax-mod_rect.ymax] [dst_x+mod_rect.xmin-pm_rect.xmin]; int inc=-shadow_pattern[distance]; if (inc>0) { pix.r=pix.r<=255-inc ? pix.r+inc : 255; pix.g=pix.g<=255-inc ? pix.g+inc : 255; pix.b=pix.b<=255-inc ? pix.b+inc : 255; } else { pix.r=pix.r>=-inc ? pix.r+inc : 0; pix.g=pix.g>=-inc ? pix.g+inc : 0; pix.b=pix.b>=-inc ? pix.b+inc : 0; } } } // BOTTOM for(dst_y=0;dst_y<gmap_area->border_width-bottom_margin && dst_y<mod_rect.height();dst_y++) { int distance=dst_y+bottom_margin; int left=-left_margin+distance; int right=mod_rect.width()+right_margin-distance; if (left<0) left=0; if (right>mod_rect.width()) right=mod_rect.width(); for(dst_x=left;dst_x<right;dst_x++) { GPixel & pix=(*pm)[dst_y+pm_rect.ymax-mod_rect.ymax] [dst_x+mod_rect.xmin-pm_rect.xmin]; int inc=-shadow_pattern[distance]; if (inc>0) { pix.r=pix.r<=255-inc ? pix.r+inc : 255; pix.g=pix.g<=255-inc ? pix.g+inc : 255; pix.b=pix.b<=255-inc ? pix.b+inc : 255; } else { pix.r=pix.r>=-inc ? pix.r+inc : 0; pix.g=pix.g>=-inc ? pix.g+inc : 0; pix.b=pix.b>=-inc ? pix.b+inc : 0; } } } // LEFT for(dst_x=0;dst_x<gmap_area->border_width-left_margin && dst_x<mod_rect.width();dst_x++) { int distance=dst_x+left_margin; int bottom=-bottom_margin+distance; int top=mod_rect.height()+top_margin-distance; if (bottom<0) bottom=0; if (top>mod_rect.height()) top=mod_rect.height(); for(dst_y=bottom;dst_y<top;dst_y++) { GPixel & pix=(*pm)[dst_y+pm_rect.ymax-mod_rect.ymax] [dst_x+mod_rect.xmin-pm_rect.xmin]; int inc=shadow_pattern[distance]; if (inc>0) { pix.r=pix.r<=255-inc ? pix.r+inc : 255; pix.g=pix.g<=255-inc ? pix.g+inc : 255; pix.b=pix.b<=255-inc ? pix.b+inc : 255; } else { pix.r=pix.r>=-inc ? pix.r+inc : 0; pix.g=pix.g>=-inc ? pix.g+inc : 0; pix.b=pix.b>=-inc ? pix.b+inc : 0; } } } }
void MapArea::updateCache(const GRect & pm_rect, const GP<GPixmap> & pm, GRectMapper * sdoc_mapper) // Takes the passed pixmap and updated the internal cache. // The pixmap should already contain the hyperlink draw in the // INACTIVE state. We will copy it and apply ACTIVE part here. // pm_rect is a rectangle in pane's coordinates where pm is supposed // to go to. sdoc_mapper maps screen coordinates to the coordinates // of the scaled document (see qd_base_paint.cpp) { DEBUG_MSG("MapArea::updateCache(): updating caches\n"); DEBUG_MAKE_INDENT(3); if (!isCacheUsed() || !pm || !pane) return; GRect brect=gmap_area->get_bound_rect(); mapper->map(brect); brect.inflate(3, 3); // To take into account edit controls GRect urect; if (urect.intersect(pm_rect, brect)) { for(GPosition pos=pieces;pos;++pos) { GP<MapPiece> piece=pieces[pos]; GRect prect=*piece; mapper->map(prect); GRect irect; if (irect.intersect(prect, urect)) { if (piece->getOnPixmap().isNull() || piece->getOffPixmap().isNull()) piece->createPixmaps(); QPixmap & on_pix=piece->getOnPixmap(); QPixmap & off_pix=piece->getOffPixmap(); // Now I need to make a copy of the area to be cached. // The problem is that I'll need to draw into the GPixmap // and I don't want to spoil the original. GP<GPixmap> ipix_off; GRect pix_rect=irect; pix_rect.translate(-pm_rect.xmin, -pm_rect.ymin); ipix_off=GPixmap::create(*pm, GRect(pix_rect.xmin, pm->rows()-pix_rect.ymax, pix_rect.width(), pix_rect.height())); GP<GPixmap> ipix_on=GPixmap::create(*ipix_off); // Now ipix_off and ipix_on contains the data, which can be modified. // Draw the map area into them draw(irect, ipix_on, APPLY_ACTIVE); // Dither pix_off and pix_on GRect drect=irect; sdoc_mapper->map(drect); if (qxImager) qxImager->dither(*ipix_on, drect.xmin, drect.ymin); if (qxImager) qxImager->dither(*ipix_off, drect.xmin, drect.ymin); // Now copy the GPixmaps into QPixmaps to be used for caching QDPainter p_off(&off_pix); p_off.drawPixmap(GRect(irect.xmin-prect.xmin, irect.ymin-prect.ymin, irect.width(), irect.height()), ipix_off); p_off.end(); QDPainter p_on(&on_pix); p_on.drawPixmap(GRect(irect.xmin-prect.xmin, irect.ymin-prect.ymin, irect.width(), irect.height()), ipix_on); p_on.end(); } } } }
/** * Scale and translate the bitmap such that is fills the specific rectangle. * * Any area in the rectangle that is outside of the bounds of the canvas is ignored. * * If a given pixel in the bitmap is not opaque (e.g. GPixel_GetA() < 255) then blend it * using SRCOVER blend mode. */ void fillBitmapRect(const GBitmap& src, const GRect& dst) { // Store dimensions of dst rectangle int left = dst.left(); int top = dst.top(); int right = dst.right(); int bottom = dst.bottom(); int rW = dst.width(); int rH = dst.height(); // Store dimensions of src bitmap int bW = src.width(); int bH = src.height(); // Find necessary scale factor for both width and height float sx = (float)bW/(float)rW; float sy = (float)bH/(float)rH; float tx = 0 - left; float ty = 0 - top; // Create matrix for scaling float scale[6] = {sx, 0, 0, 0, sy, 0}; // Create matrix for translating float translate[6] = {1, 0, tx, 0, 1, ty}; // Combine the matrices float both[6] = {sx, 0, sx*tx, 0, sy, sy*ty}; // For loop that takes each point in dst and find corresponding point in src GPixel* d = draw.fPixels; d = (GPixel*)((char*)d + (int)top * draw.rowBytes()); for (int y = top; y < bottom; ++y) { for (int x = left; x < right; ++x) { // Only map pixels that are in the bitmap if ((x >= 0 && x < draw.width()) && (y >= 0 && y < draw.height())) { // Find corresponding point in src bitmap int xP; int yP; xP = both[0] * x + both[1] * y + both[2]; yP = both[3] * x + both[4] * y + both[5]; // Apply CTM to x and y int nX = (CTM[0] * x) + (CTM[1] * y) + (CTM[2]); int nY = (CTM[3] * x) + (CTM[4] * y) + (CTM[5]); // Prepare color to fill unsigned a = GPixel_GetA(*src.getAddr(xP, yP)); unsigned r = GPixel_GetR(*src.getAddr(xP, yP)); unsigned g = GPixel_GetG(*src.getAddr(xP, yP)); unsigned b = GPixel_GetB(*src.getAddr(xP, yP)); unsigned nA = a; unsigned nR = r; unsigned nG = g; unsigned nB = b; if (GPixel_GetA(*draw.getAddr(x, y)) > 0) { // blend float lA = GPixel_GetA(*src.getAddr(xP, yP)) / 255.99999; float lR = GPixel_GetR(*src.getAddr(xP, yP)) / 255.99999; float lG = GPixel_GetG(*src.getAddr(xP, yP)) / 255.99999; float lB = GPixel_GetB(*src.getAddr(xP, yP)) / 255.99999; float sA = lA + ((GPixel_GetA(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sR = lR + ((GPixel_GetR(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sG = lG + ((GPixel_GetG(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sB = lB + ((GPixel_GetB(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); /* float sA = lA + ((GPixel_GetA(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sR = lR + ((GPixel_GetR(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sG = lG + ((GPixel_GetG(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sB = lB + ((GPixel_GetB(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); */ nA = (int)(sA * 255.99999); nR = (int)(sR * 255.99999); nG = (int)(sG * 255.99999); nB = (int)(sB * 255.99999); d[x] = GPixel_PackARGB(nA, nR, nG, nB); //d = (GPixel*)((char*)d + (int)nY * draw.rowBytes()); //d[nX] = GPixel_PackARGB(nA, nR, nG, nB); //d = (GPixel*)((char*)d - (int)nY * draw.rowBytes()); } else { d[x] = GPixel_PackARGB(a, r, g, b); //d = (GPixel*)((char*)d + (int)nY * draw.rowBytes()); //d[nX] = GPixel_PackARGB(a, r, g, b); //d = (GPixel*)((char*)d - (int)nY * draw.rowBytes()); } } } d = (GPixel*)((char*)d + draw.rowBytes()); } }