NAMESPACE_UPP void BufferPainter::BeginOnPathOp(double q, bool abs) { if(onpath.GetCount() == 0) RenderPath(ONPATH, NULL, RGBAZero()); Begin(); if(pathlen > 0) { if(!abs) q *= pathlen; Pointf pos(0, 0); for(int i = 0; i < onpath.GetCount(); i++) { PathLine& l = onpath[i]; if(l.len > 0 && (l.len > q || q >= 1.0 && i == onpath.GetCount() - 1)) { Pointf v = l.p - pos; Translate(q / l.len * v + pos); Rotate(Bearing(v)); break; } q -= l.len; pos = l.p; } } attrstack.Top().onpath = true; onpathstack.Add() = onpath; pathlenstack.Add(pathlen); onpath.Clear(); pathlen = 0; }
void Painter::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts, int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor) { Image fill_img; if(pattern && !IsNull(color)) { ImageBuffer ibuf(8, 8); RGBA r[2] = { color, RGBAZero() }; for(RGBA *out = ibuf, *end = out + 64; out < end; pattern >>= 1) *out++ = r[(byte)pattern & 1]; fill_img = ibuf; }
virtual void Get(RGBA *span, int x, int y, unsigned len) { interpolator.Begin(x, y, len); fixed = hstyle && vstyle; while(len--) { Point h = interpolator.Get(); // h -= 128; Point l = h >> 8; if(hstyle == FILL_HREPEAT) l.x = (l.x + ax) % cx; if(vstyle == FILL_VREPEAT) l.y = (l.y + ay) % cy; if(fast) { if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) *span = Pixel(l.x, l.y); else if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy)) *span = RGBAZero(); else *span = GetPixel(l.x, l.y); } else { RGBAV v; v.Set(0); // v.Set(256 * 256 / 2); h.x &= 255; h.y &= 255; Point u = -h + 256; if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) { v.Put(u.x * u.y, Pixel(l.x, l.y)); v.Put(h.x * u.y, Pixel(l.x + 1, l.y)); v.Put(u.x * h.y, Pixel(l.x, l.y + 1)); v.Put(h.x * h.y, Pixel(l.x + 1, l.y + 1)); } else if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy)) v.Set(0); else { v.Put(u.x * u.y, GetPixel(l.x, l.y)); v.Put(h.x * u.y, GetPixel(l.x + 1, l.y)); v.Put(u.x * h.y, GetPixel(l.x, l.y + 1)); v.Put(h.x * h.y, GetPixel(l.x + 1, l.y + 1)); } span->r = byte(v.r >> 16); span->g = byte(v.g >> 16); span->b = byte(v.b >> 16); span->a = byte(v.a >> 16); } ++span; } }
RGBA GetPixel(int x, int y) { if(hstyle == FILL_HPAD) x = minmax(x, 0, maxx); else if(hstyle == FILL_HREFLECT) x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx; else if(hstyle == FILL_HREPEAT) x = (x + ax) % cx; if(vstyle == FILL_VPAD) y = minmax(y, 0, maxy); else if(vstyle == FILL_VREFLECT) y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy; else if(vstyle == FILL_VREPEAT) y = (y + ay) % cy; return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero(); }
Image IconDes::Copy(const Rect& r) { if(!IsCurrent() || r.IsEmpty()) return Image(); ImageBuffer ib(r.GetSize()); Slot& c = Current(); for(int y = r.top; y < r.bottom; y++) { const RGBA *s = c.image[y] + r.left; const RGBA *e = c.image[y] + r.right; const RGBA *k = c.selection[y] + r.left; RGBA *t = ib[y - r.top]; while(s < e) { *t = *s; if(!k->r) *t = RGBAZero(); t++; k++; s++; } } return ib; }
RGBA GetPixel(const Image& img, int x, int y) { if(x < 0 || x >= img.GetWidth() || y < 0 || y >= img.GetHeight()) return RGBAZero(); return img[y][x]; }
bool PNGRaster::Create() { data = new Data; data->soff = GetStream().GetPos(); if(!Init()) { data.Clear(); return false; } if (setjmp(png_jmpbuf(data->png_ptr))) { data.Clear(); return false; } png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_get_IHDR(data->png_ptr, data->info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if(height <= 0 || width <= 0) return false; data->size.cx = width; data->size.cy = height; png_uint_32 x_ppm = 0, y_ppm = 0; int unit_type = 0; png_get_pHYs(data->png_ptr, data->info_ptr, &x_ppm, &y_ppm, &unit_type); data->info.bpp = bit_depth; data->info.colors = (bit_depth < 8 ? 1 << bit_depth : 0); data->info.dots = GetDotSize(data->size, x_ppm, y_ppm, unit_type); data->info.hotspot = Point(0, 0); data->info.kind = IMAGE_OPAQUE; data->out_bpp = bit_depth; data->strip16 = (bit_depth > 8); if(data->strip16) { png_set_strip_16(data->png_ptr); data->out_bpp = 8; } if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { ASSERT(bit_depth >= 8); data->out_bpp = 24; png_set_bgr(data->png_ptr); if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) { data->out_bpp = 32; data->info.kind = IMAGE_ALPHA; } } png_bytep trans_colors = 0; png_color_16p trans_values = 0; int num_trans = 0; png_get_tRNS(data->png_ptr, data->info_ptr, &trans_colors, &num_trans, &trans_values); // bool has_mask = (num_trans > 0); // AlphaArray im(width, height, out_bpp, 4, NULL, Vector<Color>(), has_mask ? 8 : 0, 4); // im.SetDotSize(GetDotSize(im.GetSize(), x_ppm, y_ppm, unit_type)); // ASSERT(im.GetRowBytes() >= png_get_rowbytes(png_ptr, info_ptr)); // if((color_type & PNG_COLOR_MASK_PALETTE) || !(color_type & PNG_COLOR_MASK_COLOR)) Fill(data->palette, RGBAZero(), 256); if(color_type & PNG_COLOR_MASK_PALETTE) { png_colorp ppal = 0; int pal_count = 0; png_get_PLTE(data->png_ptr, data->info_ptr, &ppal, &pal_count); pal_count = min(pal_count, 1 << min(bit_depth, 8)); for(int i = 0; i < pal_count; i++) { png_color c = ppal[i]; RGBA rgba; rgba.r = c.red; rgba.g = c.green; rgba.b = c.blue; rgba.a = 255; data->palette[i] = rgba; } if(trans_colors) { data->info.kind = IMAGE_MASK; for(int i = 0; i < num_trans; i++) data->palette[(int)trans_colors[i]] = RGBAZero(); } } else if(!(color_type & PNG_COLOR_MASK_COLOR)) { // grayscale int colors = 1 << min(bit_depth, 8); for(int i = 0; i < colors; i++) { int level = i * 255 / (colors - 1); RGBA rgba; rgba.r = rgba.g = rgba.b = (byte)level; rgba.a = 255; data->palette[i] = rgba; } if(trans_colors) { data->info.kind = IMAGE_MASK; for(int i = 0; i < num_trans; i++) data->palette[(int)trans_colors[i]] = RGBAZero(); } } /* if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return out; } */ data->row_bytes = png_get_rowbytes(data->png_ptr, data->info_ptr); data->next_row = 0; data->preload = (interlace_type != PNG_INTERLACE_NONE); data->loaded = false; switch(data->out_bpp) { case 1: data->fmt.Set1mf(); break; case 2: data->fmt.Set2mf(); break; case 4: data->fmt.Set4mf(); break; case 8: if(color_type & PNG_COLOR_MASK_ALPHA) data->fmt.Set8A(); else data->fmt.Set8(); break; case 24: data->fmt.Set24le(0xFF0000, 0xFF00, 0xFF); break; case 32: data->fmt.SetRGBAStraight(); break; default: NEVER(); return false; // invalid bpp } return true; }
virtual Image Make() const { LTIMING("Render glyph"); Point at(font[chr], font.GetLineHeight()); if(IsNull(yy)) { int n = 2 * (at.x + at.y); return AutoCrop(WithHotSpot(draw->RenderGlyph(at, angle, chr, font, color, Size(n, n)), at.x, at.y), RGBAZero()); } else { int n = at.x + at.y; Size bandsz(2 * n, 32); return AutoCrop(WithHotSpot(draw->RenderGlyph(Point(0, -yy), angle, chr, font, color, bandsz), 0, 0), RGBAZero()); } }
NAMESPACE_UPP #include "bmphdr.h" Vector<Image> ReadIcon(String data) { Vector<Image> out; const byte *in = data; int count = Peek16le(in + OFFSETOF(BMP_ICONDIR, idCount)); out.SetCount(count); for(int i = 0; i < count; i++) { const byte *hdr = in + sizeof(BMP_ICONDIR) + i * sizeof(BMP_ICONDIRENTRY); dword offset = Peek32le(hdr + OFFSETOF(BMP_ICONDIRENTRY, dwImageOffset)); hdr = in + offset; int hdrsize = Peek32le(hdr + OFFSETOF(BMP_INFOHEADER, biSize)); Size bmpsz( Peek32le(hdr + OFFSETOF(BMP_INFOHEADER, biWidth)), Peek32le(hdr + OFFSETOF(BMP_INFOHEADER, biHeight))); Size size(bmpsz.cx, bmpsz.cy >> 1); int compression = Peek32le(hdr + OFFSETOF(BMP_INFOHEADER, biCompression)); int bitcount = Peek16le(hdr + OFFSETOF(BMP_INFOHEADER, biBitCount)); int clrused = Peek32le(hdr + OFFSETOF(BMP_INFOHEADER, biClrUsed)); int rowbytes = ((bmpsz.cx * bitcount + 31) >> 3) & -4; int maskbytes = ((size.cx + 31) >> 3) & -4; hdr += hdrsize; RasterFormat fmt; switch(bitcount) { case 1: fmt.Set1mf(); break; case 4: fmt.Set4mf(); break; case 8: fmt.Set8(); break; case 16: if(compression == 3 /* BI_BITFIELD */) { fmt.Set16le(Peek32le(hdr), Peek32le(hdr + 4), Peek32le(hdr + 8)); hdr += 12; } else fmt.Set16le(31 << 10, 31 << 5, 31); break; case 24: fmt.Set24le(0xff0000, 0x00ff00, 0x0000ff); break; case 32: if(compression == 3 /* BI_BITFIELD */) { fmt.Set32le(Peek32le(hdr), Peek32le(hdr + 4), Peek32le(hdr + 8)); hdr += 12; } else fmt.Set32le(0xff0000, 0x00ff00, 0x0000ff, 0xff000000); break; } if(clrused == 0 && bitcount <= 8) clrused = 1 << bitcount; Vector<RGBA> palette; if(bitcount <= 8) { palette.SetCount(clrused); for(int i = 0; i < clrused; i++, hdr += 4) { RGBA rgba; rgba.r = hdr[OFFSETOF(BMP_RGB, rgbRed)]; rgba.g = hdr[OFFSETOF(BMP_RGB, rgbGreen)]; rgba.b = hdr[OFFSETOF(BMP_RGB, rgbBlue)]; rgba.a = 255; palette[i] = rgba; } } ImageBuffer buffer(size); for(int y = 0; y < size.cy; y++, hdr += rowbytes) fmt.Read(buffer[size.cy - y - 1], hdr, size.cx, palette.Begin()); for(int y = 0; y < size.cy; y++, hdr += maskbytes) { const byte *in = hdr; RGBA *out = buffer[size.cy - y - 1]; int cx = size.cx; while(cx >= 8) { byte b = *in++; if(b & 0x80) out[0] = RGBAZero(); if(b & 0x40) out[1] = RGBAZero(); if(b & 0x20) out[2] = RGBAZero(); if(b & 0x10) out[3] = RGBAZero(); if(b & 0x08) out[4] = RGBAZero(); if(b & 0x04) out[5] = RGBAZero(); if(b & 0x02) out[6] = RGBAZero(); if(b & 0x01) out[7] = RGBAZero(); out += 8; cx -= 8; } if(cx) { byte b = *in++; do { if(b & 0x80) *out = RGBAZero(); out++; b <<= 1; } while(--cx); } } out[i] = buffer; } return out; }
void IconDes::DoDelete() { SetColor0(RGBAZero()); }
virtual Image Make() const { LTIMING("Render glyph"); Point at(font[chr], font.GetLineHeight()); int n = 2 * (at.x + at.y); return AutoCrop(WithHotSpot(draw->RenderGlyph(at, angle, chr, font, color, Size(n, n)), at.x, at.y), RGBAZero()); }