Module: Emfsvg::Translation::Handlers::SharedGdi
- Includes:
- Emf::Emr::Binary::TypeCodes
- Included in:
- EllipseHandler, ImageHandler, LineHandler, PathHandler, PolylineHandler, RectHandler, TextHandler
- Defined in:
- lib/emfsvg/translation/handlers/shared_gdi.rb
Overview
Mixed into element handlers. Provides the per-element GDI object lifecycle: Create+Select before the block, Delete after.
Strategy (v1): always emit CreatePen + CreateBrushIndirect + SelectObject + (draw) + DeleteObject, even when the SVG value is "none". This produces a literal 1:1 mapping of the SVG tree to EMF records and is what the round-trip test exercises.
If the element has a rectangular clip-path, the entire draw is wrapped in SaveDC + IntersectClipRect + RestoreDC so the clip is scoped to this element only.
Instance Method Summary collapse
- #clip_bounds_for(element, context) ⇒ Object
- #emit_create_brush(context, paint) ⇒ Object
- #emit_create_pen(context, stroke) ⇒ Object
- #emit_delete(context, handle) ⇒ Object
- #emit_restore_dc(context) ⇒ Object
- #emit_save_dc(context) ⇒ Object
- #with_gdi_state(element, context) ⇒ Object
Instance Method Details
#clip_bounds_for(element, context) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 40 def clip_bounds_for(element, context) return nil if context.clip_path_registry.nil? attr = element.clip_path return nil if attr.nil? clip = context.clip_path_registry.lookup(attr) return nil unless clip clip.clip_bounds end |
#emit_create_brush(context, paint) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 75 def emit_create_brush(context, paint) handle = context.allocate_handle context.emit(Emf::Emr::Binary::Records::CreateBrushIndirect, i_type: CREATEBRUSHINDIRECT, ih_brush: handle, brush_style: paint.style, color: paint.color.to_emf_wire.to_wire, brush_hatch: 0) context.emit(Emf::Emr::Binary::Records::SelectObject, i_type: SELECTOBJECT, ih_object: handle) handle end |
#emit_create_pen(context, stroke) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 61 def emit_create_pen(context, stroke) handle = context.allocate_handle context.emit(Emf::Emr::Binary::Records::CreatePen, i_type: CREATEPEN, ih_pen: handle, pen_style: stroke.pen_style, width: context.point_l(stroke.width, 0), color: stroke.paint.color.to_emf_wire.to_wire) context.emit(Emf::Emr::Binary::Records::SelectObject, i_type: SELECTOBJECT, ih_object: handle) handle end |
#emit_delete(context, handle) ⇒ Object
89 90 91 92 93 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 89 def emit_delete(context, handle) context.emit(Emf::Emr::Binary::Records::DeleteObject, i_type: DELETEOBJECT, ih_object: handle) end |
#emit_restore_dc(context) ⇒ Object
56 57 58 59 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 56 def emit_restore_dc(context) context.emit(Emf::Emr::Binary::Records::RestoreDc, i_type: RESTOREDC, saved_dc: -1) end |
#emit_save_dc(context) ⇒ Object
52 53 54 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 52 def emit_save_dc(context) context.emit(Emf::Emr::Binary::Records::SaveDc, i_type: SAVEDC) end |
#with_gdi_state(element, context) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/emfsvg/translation/handlers/shared_gdi.rb', line 22 def with_gdi_state(element, context) clip_bounds = clip_bounds_for(element, context) wrap_with_clip = !clip_bounds.nil? emit_save_dc(context) if wrap_with_clip pen_handle = emit_create_pen(context, element.stroke) if element.stroke brush_handle = emit_create_brush(context, element.fill) if element.fill if wrap_with_clip context.emit(Emf::Emr::Binary::Records::IntersectClipRect, i_type: INTERSECTCLIPRECT, rcl_clip: context.rect_l(*clip_bounds)) end yield emit_delete(context, pen_handle) if pen_handle emit_delete(context, brush_handle) if brush_handle emit_restore_dc(context) if wrap_with_clip end |