/*-- (StylePickerTool内で)LineとAreaを切り替えてPickできる。mode: 0=Area, 1=Line, 2=Line&Areas(default)  --*/
int StylePicker::pickStyleId(const TPointD &pos, double radius2, int mode) const
{
	int styleId = 0;
	if (TToonzImageP ti = m_image) {
		TRasterCM32P ras = ti->getRaster();
		TPoint point = getRasterPoint(pos);
		if (!ras->getBounds().contains(point))
			return -1;
		TPixelCM32 col = ras->pixels(point.y)[point.x];

		switch (mode) {
		case 0: //AREAS
			styleId = col.getPaint();
			break;
		case 1: //LINES
			styleId = col.getInk();
			break;
		case 2: //ALL (Line & Area)
		default:
			styleId = col.isPurePaint() ? col.getPaint() : col.getInk();
			break;
		}
	} else if (TRasterImageP ri = m_image) {
		const TPalette *palette = m_palette.getPointer();
		if (!palette)
			return -1;
		TRaster32P ras = ri->getRaster();
		if (!ras)
			return -1;
		TPoint point = getRasterPoint(pos);
		if (!ras->getBounds().contains(point))
			return -1;
		TPixel32 col = ras->pixels(point.y)[point.x];
		styleId = palette->getClosestStyle(col);
	} else if (TVectorImageP vi = m_image) {
		// prima cerca lo stile della regione piu' vicina
		TRegion *r = vi->getRegion(pos);
		if (r)
			styleId = r->getStyle();
		// poi cerca quello della stroke, ma se prima aveva trovato una regione, richiede che
		// il click sia proprio sopra la stroke, altrimenti cerca la stroke piu' vicina (max circa 10 pixel)
		const double maxDist2 = (styleId == 0) ? 100.0 * radius2 : 0;
		bool strokeFound;
		double dist2, w, thick;
		UINT index;
		//!funzionerebbe ancora meglio con un getNearestStroke che considera
		//la thickness, cioe' la min distance dalla outline e non dalla centerLine
		strokeFound = vi->getNearestStroke(pos, w, index, dist2);
		if (strokeFound) {
			TStroke *stroke = vi->getStroke(index);
			thick = stroke->getThickPoint(w).thick;
			if (dist2 - thick * thick < maxDist2) {
				assert(stroke);
				styleId = stroke->getStyle();
			}
		}
	}
	return styleId;
}
Exemple #2
0
void inkFill(const TRasterCM32P &r, const TPoint &pin, int ink, int searchRay,
			 TTileSaverCM32 *saver, TRect *insideRect)
{
	r->lock();
	TPixelCM32 *pixels = (TPixelCM32 *)r->getRawData();
	int oldInk;
	TPoint p = pin;

	if ((pixels + p.y * r->getWrap() + p.x)->isPurePaint() && (searchRay == 0 ||
															   (p = nearestInk(r, p, searchRay)) == TPoint(-1, -1))) {
		r->unlock();
		return;
	}
	TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);

	if (pix->getInk() == ink) {
		r->unlock();
		return;
	}

	oldInk = pix->getInk();

	std::stack<TPoint> seeds;
	seeds.push(p);

	while (!seeds.empty()) {
		p = seeds.top();
		seeds.pop();
		if (!r->getBounds().contains(p))
			continue;
		if (insideRect && !insideRect->contains(p))
			continue;

		TPixelCM32 *pix = pixels + (p.y * r->getWrap() + p.x);
		if (pix->isPurePaint() || pix->getInk() != oldInk)
			continue;

		if (saver)
			saver->save(p);

		pix->setInk(ink);

		seeds.push(TPoint(p.x - 1, p.y - 1));
		seeds.push(TPoint(p.x - 1, p.y));
		seeds.push(TPoint(p.x - 1, p.y + 1));
		seeds.push(TPoint(p.x, p.y - 1));
		seeds.push(TPoint(p.x, p.y + 1));
		seeds.push(TPoint(p.x + 1, p.y - 1));
		seeds.push(TPoint(p.x + 1, p.y));
		seeds.push(TPoint(p.x + 1, p.y + 1));
	}
	r->unlock();
}
  bool compute(const TPoint &pin, int ink, bool isSelective) {
    TPixelCM32 *pix;
    int distance;
    TPixelCM32 *master;
    TPoint mp, sp;
    TPixelCM32 *slave;
    TPixelCM32 *d11, *d12, *d21, *d22;
    TPoint d1p1, d1p2, d2p1, d2p2;
    TPoint p = pin;

    if (!m_bBox.contains(p)) return false;

    if ((m_buf + p.y * m_wrap + p.x)->isPurePaint() &&
        ((p = nearestInk(p, 2)) == TPoint(-1, -1)))
      return false;

    pix = m_buf + p.y * m_wrap + p.x;

    /*-- 同じインクの場合はreturn --*/
    if (pix->getInk() == ink) return false;

    if (!ConnectionTable[neighboursCode(pix, p)]) {
      master = slave = pix;
      mp = sp  = p;
      distance = 0;
    } else
      distance = findTwinPoints(pix, p, master, mp, slave, sp);

    if (distance == -1) return false;

    if (!findDam(master, mp, slave, sp, distance, d11, d1p1, d12, d1p2))
      d11 = d12 = d21 = d22 = 0;
    else
      findDamRev(master, mp, slave, sp, distance, d21, d2p1, d22, d2p2);

    // vector<pair<TPixelCM32*, int> > oldInks;

    drawSegment(d1p1, d1p2, damInk, m_saver);
    drawSegment(d2p1, d2p2, damInk, m_saver);

    inkSegmentFill(p, ink, isSelective, m_saver);

    // UINT i;

    drawSegment(d1p1, d1p2, ink, m_saver);
    drawSegment(d2p1, d2p2, ink, m_saver);

    /*	for (i=0; i<oldInks.size(); i++)
    (oldInks[i].first)->setInk(ink);*/

    return true;
  }
//-----------------------------------------------------------------------------
// questa funzione viene chiamata dopo il fill rect delle aree, e colora gli
// inchiostri di tipo "autoink"
// che confinano con le aree appena fillate con il rect. rbefore e' il rect del
// raster prima del rectfill.
void fillautoInks(TRasterCM32P &rin, TRect &rect, const TRasterCM32P &rbefore,
                  TPalette *plt) {
  assert(plt);
  TRasterCM32P r = rin->extract(rect);
  assert(r->getSize() == rbefore->getSize());
  int i, j;

  for (i = 0; i < r->getLy(); i++) {
    TPixelCM32 *pix  = r->pixels(i);
    TPixelCM32 *pixb = rbefore->pixels(i);
    for (j = 0; j < r->getLx(); j++, pix++, pixb++) {
      int paint = pix->getPaint();
      int tone  = pix->getTone();
      int ink   = pix->getInk();
      if (paint != pixb->getPaint() && tone > 0 && tone < 255 && ink != paint &&
          plt->getStyle(ink)->getFlags() != 0)
        inkFill(rin, TPoint(j, i) + rect.getP00(), paint, 0, NULL, &rect);
    }
  }
}