void Ship::draw(Painter &p) const { p.drawShip(0, 0, angel_ * 180 / M_PI, jet_); }
void Paint(Painter& Painter, Portfolio& Portfolio) { /*For this example, we'll move the origin to the center to make things a little easier to see. The most important thing to know is that by default Belle uses the bottom-left corner of the canvas as the origin and not the top-left corner (with reversed y) as many graphics libraries do. While this is a bit unconventional, it allows for the x and y dimensions to be treated the same and makes for clearer code.*/ Painter.Translate(Dimensions / 2.0); //Draw a silhouette of the untransformed shape. DrawShape(Painter, Colors::gray, Colors::lightgray); //For each page show a different example of using affine transformations. switch(Painter.GetPageNumber()) { case 0: //Page 1 //Just show the gray coordinate axis... break; case 1: //Page 2 //Show a translation over 1.3 and up 1.8. Painter.Translate(Vector(1.3, 1.8)); DrawShape(Painter); Painter.Revert(); break; case 2: //Page 3 //Show a rotation of 30 degrees. Painter.Rotate(30.0 * Deg); /*(Deg is just a unit that converts degrees to radians when multiplying and radians to degress when dividing).*/ DrawShape(Painter); Painter.Revert(); break; case 3: //Page 4 //Show a scaling of 1.5. Painter.Scale(1.5); DrawShape(Painter); Painter.Revert(); break; case 4: //Page 5 /*Scaling and translating is not the same as translating and scaling. This is related to the fact that matrix multiplication is not generally commutative.*/ Painter.Translate(Vector(1, 1)); //Translate-scale Painter.Scale(2.0); DrawShape(Painter, Colors::green); Painter.Revert(2); /*(Revert defaults to undoing one transformation, but you can specify any number of previous transformations to revert at once.)*/ Painter.Scale(2.0); //Scale-translate Painter.Translate(Vector(1, 1)); DrawShape(Painter, Colors::red); Painter.Revert(2); break; case 5: //Page 6 /*For the same underlying reason, rotating and translating is not the same as translating and rotating.*/ Painter.Translate(Vector(1, 1)); //Translate-rotate Painter.Rotate(30.0 * Deg); DrawShape(Painter, Colors::green); Painter.Revert(2); Painter.Rotate(30.0 * Deg); //Rotate-translate Painter.Translate(Vector(1, 1)); DrawShape(Painter, Colors::red); Painter.Revert(2); break; case 6: //Page 7 //However, scaling and rotation happen to be commutative. Painter.Scale(2.0); //Scale-rotate Painter.Rotate(30.0 * Deg); DrawShape(Painter, Colors::green); Painter.Revert(2); Painter.Rotate(30.0 * Deg); //Rotate-scale Painter.Scale(2.0); DrawShape(Painter, Colors::green); Painter.Revert(2); break; case 7: //Page 8 /*Occasionally, one may find a need to scale by different amounts in the x- and y- dimensions. This is typically done to create a mirror image.*/ Painter.Scale(Vector(-1.0, 1.0)); //Horizontal mirror DrawShape(Painter, Colors::lightgreen); Painter.Revert(); DrawShape(Painter, Colors::green); //Original break; case 8: //Page 9 { /*You can also create an affine transformation using the Affine object, and call Transform with the object. The TranslateScaleRotate method on Affine can be used to position an object at a given size and angle. It is equivalent to multiplying by a Translate, Scale, and Rotate in that order (though the scale and rotation order could be flipped per the result shown on page 7).*/ Affine a = Affine::TranslateScaleRotate(Vector(1, 1), 2.0, 30.0 * Deg); Painter.Transform(a); DrawShape(Painter, Colors::green); Painter.Revert(); Affine b = (Affine::Translate(Vector(1, 1)) * Affine::Scale(2.0)) * Affine::Rotate(30.0 * Deg); Painter.Transform(b); DrawShape(Painter, Colors::green); Painter.Revert(); Painter.Translate(Vector(1, 1)); Painter.Scale(2.0); Painter.Rotate(30.0 * Deg); DrawShape(Painter, Colors::green); Painter.Revert(3); } break; case 9: //Page 10 /*You can easily change units from the default inches to another unit. The following creates a horizontal unit-sized vector in Centimeters and converts that to Inches. The x-component is thus the relative scale.*/ Painter.Scale(Inches(Centimeters(1.0, 0.0)).x); DrawShape(Painter); Painter.Revert(); break; } Painter.Revert(); //Revert the page centering transformation. }
void LineBucket::render(Painter& painter, std::shared_ptr<StyleLayer> layer_desc, const Tile::ID& id) { painter.renderLine(*this, layer_desc, id); }
void HEMesh::paint(Painter& p) const { p.paint(*this); }
void Bullet::draw(Painter &p) const { p.drawBullet(x, y); }
int main() { glfwSetErrorCallback(error_callback); if(!glfwInit()) { printf("Error: cannot setup glfw.\n"); exit(EXIT_FAILURE); } glfwWindowHint(GLFW_SAMPLES, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* win = NULL; int w = 1280; int h = 720; win = glfwCreateWindow(w, h, "~`` Image Loader - Copy Images Into data/test/ ``~", NULL, NULL); if(!win) { glfwTerminate(); exit(EXIT_FAILURE); } glfwSetFramebufferSizeCallback(win, resize_callback); glfwSetKeyCallback(win, key_callback); glfwSetCharCallback(win, char_callback); glfwSetCursorPosCallback(win, cursor_callback); glfwSetMouseButtonCallback(win, button_callback); glfwMakeContextCurrent(win); glfwSwapInterval(1); if (!gladLoadGL()) { printf("Cannot load GL.\n"); exit(1); } // ---------------------------------------------------------------- // THIS IS WHERE YOU START CALLING OPENGL FUNCTIONS, NOT EARLIER!! // ---------------------------------------------------------------- rx_log_init(); mos::ImageLoader loader; if (0 != loader.init()) { exit(EXIT_FAILURE); } loader.on_loaded = on_loaded; mos::DirWatcher watcher; if (0 != watcher.init(rx_to_data_path("test"), on_dir_change, &loader)) { exit(EXIT_FAILURE); } Painter painter; while(!glfwWindowShouldClose(win)) { glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); watcher.update(); GLenum fmt = GL_NONE; if (must_recreate || must_update) { if (1 == tex_channels) { fmt = GL_RED; } else if (2 == tex_channels) { fmt = GL_RG; } else if (3 == tex_channels) { fmt = GL_RGB; } else if (4 == tex_channels) { fmt = GL_RGBA; } else { RX_ERROR("Unsupported number of channels: %d", tex_channels); } } if (must_recreate) { RX_VERBOSE("Create texture, width: %d, height: %d, channels: %d", tex_width, tex_height, tex_channels); if (0 != tex_id) { glDeleteTextures(1, &tex_id); } if (GL_NONE != fmt) { glGenTextures(1, &tex_id); glBindTexture(GL_TEXTURE_2D, tex_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, fmt, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } must_recreate = false; must_update = false; } if (must_update && GL_NONE != fmt) { RX_VERBOSE("Updating pixels"); glBindTexture(GL_TEXTURE_2D, tex_id); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, tex_width, tex_height, 0, fmt, GL_UNSIGNED_BYTE, pixels); must_update = false; } if (0 != tex_id) { int x = MAX(0, (w/2) - (tex_width/2)); int y = 0; painter.clear(); painter.texture(tex_id, x, y, tex_width, tex_height); painter.draw(); } glfwSwapBuffers(win); glfwPollEvents(); } loader.shutdown(); glfwTerminate(); return EXIT_SUCCESS; }
Manipulator* TextOvView::CreateManipulator ( Viewer* v, Event& e, Transformer* rel, Tool* tool ) { Manipulator* m = nil; Editor* ed = v->GetEditor(); int tabWidth = Math::round(.5*ivinch); if (tool->IsA(GRAPHIC_COMP_TOOL)) { FontVar* fontVar = (FontVar*) ed->GetState("FontVar"); ColorVar* colVar = (ColorVar*) ed->GetState("ColorVar"); PSFont* font = (fontVar == nil) ? psstdfont : fontVar->GetFont(); PSColor* fg = (colVar == nil) ? psblack : colVar->GetFgColor(); int lineHt = font->GetLineHt(); Painter* painter = new Painter; painter->FillBg(false); painter->SetFont(font); painter->SetColors(fg, nil); Orientation o = v->GetOrientation(); if (o!=Rotated) painter->SetTransformer(rel); else { rel = new Transformer(rel); rel->Rotate(90.0); painter->SetTransformer(rel); Unref(rel); } m = new TextManip(v, painter, lineHt, tabWidth, tool); } else if (tool->IsA(RESHAPE_TOOL)) { TextGraphic* textgr = (TextGraphic*) GetGraphic(); Painter* painter = new Painter; int lineHt = textgr->GetLineHeight(); Coord xpos, ypos; rel = new Transformer; const char* text = textgr->GetOriginal(); int size = strlen(text); textgr->TotalTransformation(*rel); rel->Transform(0, 0, xpos, ypos); painter->FillBg(false); painter->SetFont(textgr->GetFont()); painter->SetColors(textgr->GetFgColor(), nil); painter->SetTransformer(rel); Unref(rel); m = new TextManip( v, text, size, xpos, ypos, painter, lineHt, tabWidth, tool ); } else { m = OverlayView::CreateManipulator(v, e, rel, tool); } return m; }
void SymbolBucket::render(Painter& painter, const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderSymbol(*this, *layer.as<SymbolLayer>(), tileID, matrix); }
void LineBucket::render(Painter &painter, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) { painter.renderLine(*this, layer_desc, id, matrix); }
void HistoryVideo::draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const { if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return; _data->automaticLoad(_realParent->fullId(), _parent->data()); bool loaded = _data->loaded(), displayLoading = _data->displayLoading(); bool selected = (selection == FullSelection); auto paintx = 0, painty = 0, paintw = width(), painth = height(); bool bubble = _parent->hasBubble(); int captionw = paintw - st::msgPadding.left() - st::msgPadding.right(); if (displayLoading) { ensureAnimation(); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); } } updateStatusText(); bool radial = isRadialAnimation(ms); if (bubble) { if (!_caption.isEmpty()) { painth -= st::mediaCaptionSkip + _caption.countHeight(captionw); if (isBubbleBottom()) { painth -= st::msgPadding.bottom(); } } } else { App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } auto inWebPage = (_parent->media() != this); auto roundRadius = inWebPage ? ImageRoundRadius::Small : ImageRoundRadius::Large; auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) | ((isBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); QRect rthumb(rtlrect(paintx, painty, paintw, painth, width())); const auto good = _data->goodThumbnail(); if (good && good->loaded()) { p.drawPixmap(rthumb.topLeft(), good->pixSingle({}, _thumbw, _thumbh, paintw, painth, roundRadius, roundCorners)); } else { if (good) { good->load({}); } p.drawPixmap(rthumb.topLeft(), _data->thumb->pixBlurredSingle(_realParent->fullId(), _thumbw, _thumbh, paintw, painth, roundRadius, roundCorners)); } if (selected) { App::complexOverlayRect(p, rthumb, roundRadius, roundCorners); } QRect inner(rthumb.x() + (rthumb.width() - st::msgFileSize) / 2, rthumb.y() + (rthumb.height() - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); if (selected) { p.setBrush(st::msgDateImgBgSelected); } else if (isThumbAnimation(ms)) { auto over = _animation->a_thumbOver.current(); p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over)); } else { bool over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); } { PainterHighQualityEnabler hq(p); p.drawEllipse(inner); } if (!selected && _animation) { p.setOpacity(1); } auto icon = ([this, radial, selected, loaded]() -> const style::icon * { if (loaded && !radial) { return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay); } else if (radial || _data->loading()) { if (_parent->data()->id > 0 || _data->uploading()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); })(); if (icon) { icon->paintInCenter(p, inner); } if (radial) { QRect rinner(inner.marginsRemoved(QMargins(st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine, st::msgFileRadialLine))); _animation->radial.draw(p, rinner, st::msgFileRadialLine, selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg); } auto statusX = paintx + st::msgDateImgDelta + st::msgDateImgPadding.x(), statusY = painty + st::msgDateImgDelta + st::msgDateImgPadding.y(); auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x(); auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y(); App::roundRect(p, rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners); p.setFont(st::normalFont); p.setPen(st::msgDateImgFg); p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x()); // date if (!_caption.isEmpty()) { auto outbg = _parent->hasOutLayout(); p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); _caption.draw(p, st::msgPadding.left(), painty + painth + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection); } else if (_parent->media() == this) { auto fullRight = paintx + paintw, fullBottom = painty + painth; _parent->drawInfo(p, fullRight, fullBottom, 2 * paintx + paintw, selected, InfoDisplayType::Image); if (!bubble && _parent->displayRightAction()) { auto fastShareLeft = (fullRight + st::historyFastShareLeft); auto fastShareTop = (fullBottom - st::historyFastShareBottom - st::historyFastShareSize); _parent->drawRightAction(p, fastShareLeft, fastShareTop, 2 * paintx + paintw); } } }
void HistoryVideo::drawGrouped( Painter &p, const QRect &clip, TextSelection selection, TimeMs ms, const QRect &geometry, RectParts corners, not_null<uint64*> cacheKey, not_null<QPixmap*> cache) const { _data->automaticLoad(_realParent->fullId(), _parent->data()); validateGroupedCache(geometry, corners, cacheKey, cache); const auto selected = (selection == FullSelection); const auto loaded = _data->loaded(); const auto displayLoading = _data->displayLoading(); const auto bubble = _parent->hasBubble(); if (displayLoading) { ensureAnimation(); if (!_animation->radial.animating()) { _animation->radial.start(_data->progress()); } } const auto radial = isRadialAnimation(ms); if (!bubble) { // App::roundShadow(p, 0, 0, paintw, painth, selected ? st::msgInShadowSelected : st::msgInShadow, selected ? InSelectedShadowCorners : InShadowCorners); } p.drawPixmap(geometry.topLeft(), *cache); if (selected) { const auto roundRadius = ImageRoundRadius::Large; App::complexOverlayRect(p, geometry, roundRadius, corners); } const auto radialOpacity = radial ? _animation->radial.opacity() : 1.; const auto backOpacity = (loaded && !_data->uploading()) ? radialOpacity : 1.; const auto radialSize = st::historyGroupRadialSize; const auto inner = QRect( geometry.x() + (geometry.width() - radialSize) / 2, geometry.y() + (geometry.height() - radialSize) / 2, radialSize, radialSize); p.setPen(Qt::NoPen); if (selected) { p.setBrush(st::msgDateImgBgSelected); } else if (isThumbAnimation(ms)) { auto over = _animation->a_thumbOver.current(); p.setBrush(anim::brush(st::msgDateImgBg, st::msgDateImgBgOver, over)); } else { auto over = ClickHandler::showAsActive(_data->loading() ? _cancell : _savel); p.setBrush(over ? st::msgDateImgBgOver : st::msgDateImgBg); } p.setOpacity(backOpacity * p.opacity()); { PainterHighQualityEnabler hq(p); p.drawEllipse(inner); } auto icon = [&]() -> const style::icon * { if (_data->waitingForAlbum()) { return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting); } else if (loaded && !radial) { return &(selected ? st::historyFileThumbPlaySelected : st::historyFileThumbPlay); } else if (radial || _data->loading()) { if (_parent->data()->id > 0 || _data->uploading()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; } return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload); }(); const auto previous = [&]() -> const style::icon* { if (_data->waitingForAlbum()) { return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel); } return nullptr; }(); p.setOpacity(backOpacity); if (icon) { if (previous && radialOpacity > 0. && radialOpacity < 1.) { LOG(("INTERPOLATING: %1").arg(radialOpacity)); PaintInterpolatedIcon(p, *icon, *previous, radialOpacity, inner); } else { icon->paintInCenter(p, inner); } } p.setOpacity(1); if (radial) { const auto line = st::historyGroupRadialLine; const auto rinner = inner.marginsRemoved({ line, line, line, line }); const auto color = selected ? st::historyFileThumbRadialFgSelected : st::historyFileThumbRadialFg; _animation->radial.draw(p, rinner, line, color); } }
void RSSI::paint(Painter& painter) { const auto r = screen_rect(); constexpr int rssi_sample_range = 256; constexpr float rssi_voltage_min = 0.4; constexpr float rssi_voltage_max = 2.2; constexpr float adc_voltage_max = 3.3; constexpr int raw_min = rssi_sample_range * rssi_voltage_min / adc_voltage_max; constexpr int raw_max = rssi_sample_range * rssi_voltage_max / adc_voltage_max; constexpr int raw_delta = raw_max - raw_min; const range_t<int> x_avg_range { 0, r.width() - 1 }; const auto x_avg = x_avg_range.clip((avg_ - raw_min) * r.width() / raw_delta); const range_t<int> x_min_range { 0, x_avg }; const auto x_min = x_min_range.clip((min_ - raw_min) * r.width() / raw_delta); const range_t<int> x_max_range { x_avg + 1, r.width() }; const auto x_max = x_max_range.clip((max_ - raw_min) * r.width() / raw_delta); const Rect r0 { static_cast<ui::Coord>(r.left()), r.top(), static_cast<ui::Dim>(x_min), r.height() }; painter.fill_rectangle( r0, Color::blue() ); const Rect r1 { static_cast<ui::Coord>(r.left() + x_min), r.top(), static_cast<ui::Dim>(x_avg - x_min), r.height() }; painter.fill_rectangle( r1, Color::red() ); const Rect r2 { static_cast<ui::Coord>(r.left() + x_avg), r.top(), 1, r.height() }; painter.fill_rectangle( r2, Color::white() ); const Rect r3 { static_cast<ui::Coord>(r.left() + x_avg + 1), r.top(), static_cast<ui::Dim>(x_max - (x_avg + 1)), r.height() }; painter.fill_rectangle( r3, Color::red() ); const Rect r4 { static_cast<ui::Coord>(r.left() + x_max), r.top(), static_cast<ui::Dim>(r.width() - x_max), r.height() }; painter.fill_rectangle( r4, Color::black() ); if (pwmrssi_enabled) { const range_t<int> pwmrssi_avg_range { 0, 96 }; const auto pwmrssi_avg = pwmrssi_avg_range.clip((avg_ - raw_min) * 96 / raw_delta); baseband::set_pwmrssi(pwmrssi_avg, true); } }
/*! \fn wcurses::Application::Run() */ int Application::Run() { // Debug << " Launching app loop -- just writing message..."; Application::_curscreen->StartUpdatesThread(); //Application::_curscreen->Update(); Widget* R = Application::_curscreen->Root ( "" ); Painter* P = R->DCPainter(); P->CPosition ( 1,1 ); Event* E; KeyPressEvent* key; String S; MouseEvent* ME; xyCoords xy ( 1,1 ); do { E = Application::_terminal->WaitEvent(); // if(!E){ // E = &Event::nil; // continue; // } //PushEvent ( E ); //_doEvents(); switch ( E->Type() ) { case event::MouseEvent: ME = E->toEventType<MouseEvent>(); if ( !ME ) { Application::_textProc << " MouseEvent : cannot cast to MouseEvent!!" << StyledString::END; break; } S = String ( "" ); S << "<strong; bgcolor blue; fgcolor cyan;>"; S << ME->ToString(); //PStr pstr = Application::_textProc.Data(); P->WriteRT ( S.std().c_str() ); xy += xyCoords ( 0,1 ); P->CPosition ( xy ); R->Update(); break; case event::KeyEvent: key = E->toEventType<KeyPressEvent>(); switch ( key->KeyValue() ) { case 'q': if ( key->isMeta() ) key->SetEvent ( event::Quit ); else goto nk; break; default: nk: S = String ( "" ); S << '[' << ( key->isMeta() ? "M":"-" ) << ">"<< ( char ) key->KeyValue() << '|' << ( int ) key->KeyValue(); P->WriteStr ( S.std().c_str() ); xy += xyCoords ( 0,1 ); P->CPosition ( xy ); R->Update(); break; } break; } } while ( E->What() != event::Quit ); return 0; }
void RasterBucket::render(Painter& painter, const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderRaster(*this, *layer.as<RasterLayer>(), tileID, matrix); }
void SymbolBucket::render(Painter& painter, const StyleLayer& layer, const TileID& id, const mat4& matrix) { painter.renderSymbol(*this, *layer.as<SymbolLayer>(), id, matrix); }
bool RenderOutline(const FT_Outline& outline, Painter& path, double xx, double yy) { FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; FT_Vector* point; FT_Vector* limit; char* tags; int n; // index of contour in outline char tag; // current point's state int first = 0; // index of first point in contour for(n = 0; n < outline.n_contours; n++) { int last = outline.contours[n]; limit = outline.points + last; v_start = outline.points[first]; v_last = outline.points[last]; v_control = v_start; point = outline.points + first; tags = outline.tags + first; tag = FT_CURVE_TAG(tags[0]); if(tag == FT_CURVE_TAG_CUBIC) return false; if(tag == FT_CURVE_TAG_CONIC) { if(FT_CURVE_TAG(outline.tags[last]) == FT_CURVE_TAG_ON) { // start at last point if it is on the curve v_start = v_last; limit--; } else { // if both first and last points are conic, // start at their middle and record its position // for closure v_start.x = (v_start.x + v_last.x) / 2; v_start.y = (v_start.y + v_last.y) / 2; v_last = v_start; } point--; tags--; } path.Move(ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); while(point < limit) { point++; tags++; tag = FT_CURVE_TAG(tags[0]); switch(tag) { case FT_CURVE_TAG_ON: path.Line(ft_dbl(point->x) + xx, -ft_dbl(point->y) + yy); continue; case FT_CURVE_TAG_CONIC: v_control.x = point->x; v_control.y = point->y; Do_Conic: if(point < limit) { FT_Vector vec; FT_Vector v_middle; point++; tags++; tag = FT_CURVE_TAG(tags[0]); vec.x = point->x; vec.y = point->y; if(tag == FT_CURVE_TAG_ON) { path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); continue; } if(tag != FT_CURVE_TAG_CONIC) return false; v_middle.x = (v_control.x + vec.x) / 2; v_middle.y = (v_control.y + vec.y) / 2; path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, ft_dbl(v_middle.x) + xx, -ft_dbl(v_middle.y) + yy); v_control = vec; goto Do_Conic; } path.Quadratic(ft_dbl(v_control.x) + xx, -ft_dbl(v_control.y) + yy, ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); goto Close; default: FT_Vector vec1, vec2; if(point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC) return false; vec1.x = point[0].x; vec1.y = point[0].y; vec2.x = point[1].x; vec2.y = point[1].y; point += 2; tags += 2; if(point <= limit) { FT_Vector vec; vec.x = point->x; vec.y = point->y; path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, ft_dbl(vec.x) + xx, -ft_dbl(vec.y) + yy); continue; } path.Cubic(ft_dbl(vec1.x) + xx, -ft_dbl(vec1.y) + yy, ft_dbl(vec2.x) + xx, -ft_dbl(vec2.y) + yy, ft_dbl(v_start.x) + xx, -ft_dbl(v_start.y) + yy); goto Close; } } Close: path.Close(); first = last + 1; } return true; }
void RasterBucket::render(Painter &painter, util::ptr<StyleLayer> layer_desc, const Tile::ID &id, const mat4 &matrix) { painter.renderRaster(*this, layer_desc, id, matrix); }
virtual void Paint(Painter &pntr,Size &sz){ pntr.Move(0,0).Line(sz.cx,0).Line(sz.cx,sz.cy).Line(0,sz.cy).Close().Fill(White()).Stroke(5,Black()); pntr.Move(0,0).Line(sz.cx,sz.cy).Stroke(5,Black()); }