    float x = KEp.v[0] / KEp.v[2];
    float y = KEp.v[1] / KEp.v[2];
  
    return out->x >= -margin && out->x <= s->fb_w + margin && out->y >= -margin && out->y <= s->fb_h + margin;
  }
  
  
  static void ui_draw_text(NVGcontext *vg, float x, float y, const char* string, float size, NVGcolor color, int font){
    nvgFontFaceId(vg, font);
 
</s> remove   out->x = KEp.v[0] / KEp.v[2];
  out->y = KEp.v[1] / KEp.v[2];
 </s> add   float x = KEp.v[0] / KEp.v[2];
  float y = KEp.v[1] / KEp.v[2]; </s> remove   vertex_data out;
  if (!car_space_to_full_frame(s, x_in, y_in, 0.0, &out)) return;
 </s> add   vertex_data out = {};
  car_space_to_full_frame(s, x_in, y_in, 0.0, &out); </s> remove   sz = std::clamp((sz * 30) / (x_in / 3 + 30), 15.0f, 30.0f);
 </s> add   sz = std::clamp((sz * 30) / (x_in / 3 + 30), 15.0f, 30.0f) * zoom;
  y = std::fmin(s->scene.viz_rect.bottom() - sz * .6,  y);
  x = std::clamp(x, 0.f, s->scene.viz_rect.right() - sz / 2); </s> remove   nvgRestore(s->vg);
 </s> add   nvgResetScissor(s->vg);
  nvgTransformPoint(&out->x, &out->y, s->car_space_transform, x, y);
    float x = KEp.v[0] / KEp.v[2];
    float y = KEp.v[1] / KEp.v[2];
  
  nvgTransformPoint(&out->x, &out->y, s->car_space_transform, x, y);
    return out->x >= -margin && out->x <= s->fb_w + margin && out->y >= -margin && out->y <= s->fb_h + margin;
  }
  
  
  static void ui_draw_text(NVGcontext *vg, float x, float y, const char* string, float size, NVGcolor color, int font){
    nvgFontFaceId(vg, font);
keep keep add keep keep keep keep keep keep
 UI: refactor transform (#19658)

* refactor transform

* always draw chevron if there is a lead

* remove nvgSave&nvgRestore

* keep one point outside the screen

* zoom chevron

* more size

* still use margin

* still use margin 
selfdrive/ui/paint.cc