CGContext iOS এবং macOS এ 2D অঙ্কন কমান্ড কার্যকর করার জন্য Core Graphics এর প্রধান অবজেক্ট। এটি একটি গ্রাফিকাল কনটেক্সট প্রতিনিধিত্ব করে যা বর্তমান অবস্থা সংরক্ষণ করে: ফিল রঙ, লাইনের পুরুত্ব, রূপান্তর, ক্লিপিং এলাকা এবং ফন্ট। সমস্ত অঙ্কন কার্যক্রম — লাইন, আয়তক্ষেত্র, টেক্সট, ছবি — CGContext এর মাধ্যমে সম্পাদিত হয়। Apple Developer Documentation, 2026 অনুসারে, CGContext হল Apple ইকোসিস্টেমের সমস্ত রাস্টার এবং ভেক্টর গ্রাফিক্সের ভিত্তি।
মূল পয়েন্ট
CGContext Core Graphics ফ্রেমওয়ার্ক থেকে একটি অস্বচ্ছ টাইপ (opaque type) যা 2D রেন্ডারিং কমান্ড কার্যকর করার জন্য পরিবেশ প্রতিনিধিত্ব করে। এটি অবস্থা স্ট্যাক, বর্তমান রঙের স্থান, স্থানাঙ্ক রূপান্তর এবং ক্লিপিং এলাকা পরিচালনা করে। CGContext হল একমাত্র অবজেক্ট যার সাথে সমস্ত Quartz 2D অঙ্কন ফাংশন ইন্টারঅ্যাক্ট করে — যেকোনো গ্রাফিকাল অপারেশন এর মাধ্যমে যায়।
CGContext তার উদ্দেশ্যের উপর নির্ভর করে বিভিন্ন প্রকারে বিদ্যমান: bitmap context মেমরিতে রাস্টার ইমেজ নিয়ে কাজ করার জন্য, PDF context PDF ডকুমেন্ট তৈরির জন্য, window context স্ক্রিনে অঙ্কনের জন্য (UIView দ্বারা draw(_:) এ প্রদান করা হয়েছে)। iOS ডেভেলপাররা প্রায়শই draw(_:) পদ্ধতির ভিতরে UIGraphicsGetCurrentContext() থেকে বা অফলাইন রেন্ডারিংয়ের জন্য UIGraphicsBeginImageContextWithOptions থেকে প্রাপ্ত কনটেক্সট নিয়ে কাজ করেন।
কনটেক্সট অবস্থা স্ট্যাকের মাধ্যমে সমস্ত সেটিংস প্রয়োগ করে — ডেভেলপার বর্তমান অবস্থা সংরক্ষণ (saveGState), প্যারামিটার পরিবর্তন এবং পূর্ববর্তী অবস্থা পুনরুদ্ধার (restoreGState) করতে পারেন। জটিল দৃশ্য অঙ্কন করার সময় এটি অত্যন্ত গুরুত্বপূর্ণ যেখানে বিভিন্ন উপাদানের বিভিন্ন রঙ, লাইনের পুরুত্ব এবং রূপান্তর প্রয়োজন। Apple WWDC 2023 অনুসারে, অবস্থা স্ট্যাকের সঠিক ব্যবহার কোড পঠনযোগ্যতা উন্নত করে এবং ভিজ্যুয়াল আর্টিফ্যাক্ট প্রতিরোধ করে।
CGContextSaveGState কনটেক্সটের বর্তমান অবস্থার একটি কপি স্ট্যাকের উপর রাখে। এই অবস্থায় সমস্ত সেটিংস অন্তর্ভুক্ত: রঙ, লাইনের পুরুত্ব, রূপান্তর, ছায়া, ক্লিপিং এলাকা, ফন্ট। প্যারামিটার পরিবর্তন করার পর, CGContextRestoreGState কল করলে কনটেক্সট সংরক্ষিত অবস্থায় ফিরে আসে, সমস্ত মধ্যবর্তী পরিবর্তন বাতিল করে। স্ট্যাক iOS এ 32টি অবস্থা পর্যন্ত ধারণ করতে পারে।
বিভিন্ন শৈলীর উপাদানের গ্রুপ অঙ্কন করার সময় (যেমন বহু-রঙের চার্ট সেক্টর), অবস্থা স্ট্যাক ম্যানুয়ালি প্রতিটি প্যারামিটার মনে রাখার এবং পুনরুদ্ধার করার প্রয়োজনীয়তা দূর করে। saveGState/restoreGState ছাড়া, ডেভেলপারকে প্রতিটি উপাদানের পরে রঙ, ছায়া এবং রূপান্তর রিসেট করতে হত। স্ট্যাক ব্যবহার কোড হ্রাস করে এবং পুনরুদ্ধার ত্রুটি প্রতিরোধ করে।
সংরক্ষণ এবং পুনরুদ্ধারের সামঞ্জস্য বজায় রাখা গুরুত্বপূর্ণ — প্রতিটি saveGState এর একটি মিলিত restoreGState থাকতে হবে। সামঞ্জস্য ভাঙলে অবস্থা লিক বা অকাল পুনরুদ্ধার ঘটে, যা অপ্রত্যাশিত রেন্ডারিং সৃষ্টি করে। Xcode এর স্ট্যাটিক বিশ্লেষক CGContext স্ট্যাক সামঞ্জস্য পরীক্ষা করে না, তাই সঠিকতার দায়িত্ব ডেভেলপারের উপর। do/finally ব্লকে জোড়া গ্রুপ করার সুপারিশ করা হয়।
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.saveGState()
ctx.setStrokeColor(UIColor.red.cgColor)
ctx.setLineWidth(3)
ctx.addRect(CGRect(x: 50, y: 50, width: 200, height: 100))
ctx.strokePath()
ctx.restoreGState()
}
CGContextSetFillColorWithColor পরবর্তী কার্যক্রমের জন্য ফিল রঙ সেট করে। রঙ CGColorRef হিসাবে পাস করা হয়, যাতে রঙের স্থান এবং রঙের উপাদান সম্পর্কে তথ্য থাকে। CGContextSetStrokeColorWithColor স্ট্রোক রঙের জন্য একইভাবে কাজ করে। Apple ভালো পারফরম্যান্সের জন্য ঘন ঘন ব্যবহৃত CGColorRef মান ক্যাশ করার সুপারিশ করে।
CGContextDrawLinearGradient নির্দিষ্ট রঙ সহ দুটি বিন্দুর মধ্যে একটি লিনিয়ার গ্রেডিয়েন্ট আঁকে। CGContextDrawRadialGradient একটি বৃত্ত থেকে অন্য বৃত্তে স্থানান্তরিত একটি রেডিয়াল গ্রেডিয়েন্ট তৈরি করে। গ্রেডিয়েন্ট নিয়ে কাজ করার জন্য, প্রথমে CGGradientRef অবজেক্ট তৈরি করা হয় যাতে রঙের একটি অ্যারে এবং স্টপ অবস্থান থাকে। CGContext এ গ্রেডিয়েন্টগুলি RGB এবং Grayscale উভয় রঙের স্থান সমর্থন করে।
গ্রেডিয়েন্ট দিয়ে এলাকা পূরণ করতে প্রথমে ক্লিপিং এলাকা সেট করা প্রয়োজন। clip ছাড়া, গ্রেডিয়েন্ট সম্পূর্ণ কনটেক্সট পূরণ করবে, শুধু কাঙ্ক্ষিত আকৃতি নয়। সাধারণ প্যাটার্ন: কনটেক্সটে পাথ যোগ করুন, এলাকা সীমাবদ্ধ করতে clip কল করুন, তারপর গ্রেডিয়েন্ট আঁকুন। এই প্যাটার্নটি সমস্ত অ্যাপ্লিকেশনে ব্যবহৃত হয় যেখানে জটিল আকারের গ্রেডিয়েন্ট ফিল প্রয়োজন, বাটন থেকে ব্যাকগ্রাউন্ড পর্যন্ত।
| ফাংশন | উদ্দেশ্য | রঙের স্থান |
|---|---|---|
| setFillColor | ফিল রঙ সেট করে | যেকোনো (CGColor এর মাধ্যমে) |
| setStrokeColor | স্ট্রোক রঙ সেট করে | যেকোনো (CGColor এর মাধ্যমে) |
| drawLinearGradient | লিনিয়ার গ্রেডিয়েন্ট আঁকে | RGB বা Grayscale |
| drawRadialGradient | রেডিয়াল গ্রেডিয়েন্ট আঁকে | RGB বা Grayscale |
CGContextAddPath পরবর্তী রেন্ডারিংয়ের জন্য পূর্বে তৈরি CGPathRef কনটেক্সটে যোগ করে। পাথ যোগ করার পরে, এটি স্ট্রোক (strokePath), ফিল (fillPath) বা উভয়ই করা যেতে পারে। CGContextBeginPath পূর্ববর্তী পাথ পরিষ্কার করে একটি নতুন পাথ শুরু করে। কনটেক্সট একবারে শুধুমাত্র একটি সক্রিয় পাথ সমর্থন করে।
CGContextMoveToPoint বর্তমান কনট্যুর বিন্দুকে নির্দিষ্ট স্থানাঙ্কে সরিয়ে নেয়। CGContextAddLineToPoint বর্তমান বিন্দু থেকে প্রদত্ত বিন্দু পর্যন্ত একটি সরল রেখা আঁকে। CGContextAddCurveToPoint একটি কিউবিক বেজিয়ার বক্ররেখা যোগ করে, CGContextAddQuadCurveToPoint একটি কোয়াড্রাটিক বক্ররেখা যোগ করে। CGContextClosePath শেষ এবং প্রথম বিন্দুর মধ্যে একটি সরল রেখা দিয়ে কনট্যুর বন্ধ করে।
UIBezierPath এর বিপরীতে, যেখানে এই সমস্ত পদ্ধতি পাথ অবজেক্টে কল করা হয়, CGContext এ এগুলি সরাসরি কনটেক্সটে কল করা হয়। এই পার্থক্য পদ্ধতি নির্বাচনের সময় গুরুত্বপূর্ণ: UIBezierPath পাথ পুনরায় ব্যবহারের জন্য বেশি সুবিধাজনক, CGContext ন্যূনতম ওভারহেড সহ এককালীন অঙ্কনের জন্য ভাল। CGContext CGContextSetLineDash এর মাধ্যমে ড্যাশ করা লাইন, CGContextSetLineCap এর মাধ্যমে নমনীয় প্রান্ত এবং CGContextSetLineJoin এর মাধ্যমে জয়েন্ট সমর্থন করে।
let ctx = UIGraphicsGetCurrentContext()!
ctx.beginPath()
ctx.moveTo(x: 50, y: 100)
ctx.addLineTo(x: 200, y: 100)
ctx.addCurveTo(x1: 250, y1: 50, x2: 300, y2: 150, x3: 350, y3: 100)
ctx.setStrokeColor(UIColor.blue.cgColor)
ctx.setLineWidth(5)
ctx.strokePath()
CGContextClip অঙ্কন এলাকাকে বর্তমান পাথ পর্যন্ত সীমাবদ্ধ করে। সমস্ত পরবর্তী অঙ্কন কার্যক্রম শুধুমাত্র এই এলাকার ভিতরে দৃশ্যমান হবে। এটি মাস্কিং, কোণ গোল করা এবং উপাদানের কাস্টম সীমানা তৈরির জন্য মৌলিক প্রক্রিয়া। ক্লিপিং এলাকা saveGState/restoreGState এর মাধ্যমেও সংরক্ষণ এবং পুনরুদ্ধার করা হয়।
CGContextTranslateCTM কনটেক্সট স্থানাঙ্ক সিস্টেমের মূল বিন্দু স্থানান্তর করে। CGContextScaleCTM X এবং Y অক্ষ স্কেল করে। CGContextRotateCTM বর্তমান মূল বিন্দুর চারপাশে স্থানাঙ্ক সিস্টেম ঘোরায়। রূপান্তরগুলি সঞ্চিত হয় — প্রতিটি পরবর্তীটি বর্তমান স্থানাঙ্ক সিস্টেমের সাপেক্ষে প্রয়োগ করা হয়। মিশ্র রূপান্তর (স্থানান্তর + ঘূর্ণন + স্কেল) অ্যানিমেশন এবং উপাদান অবস্থানের জন্য ব্যবহৃত হয়।
ক্লিপিং এবং রূপান্তরের সম্মিলিত ব্যবহার শক্তিশালী ক্ষমতা প্রদান করে: ক্লিপিংয়ের মাধ্যমে একটি জটিল মাস্ক আঁকা যায়, তারপর সম্পূর্ণ বিষয়বস্তুতে রূপান্তর প্রয়োগ করা যায়। একটি সাধারণ উদাহরণ — গোলাকার কোণ সহ একটি কোণে ছবির অংশ প্রদর্শন করা। অপারেশনের ক্রম গুরুত্বপূর্ণ: প্রথমে ক্লিপিং এলাকা সেট করুন, তারপর রূপান্তর প্রয়োগ করুন, তারপর বিষয়বস্তু আঁকুন। Apple অঙ্কন লুপে CTM (বর্তমান রূপান্তর ম্যাট্রিক্স) পরিবর্তন কমানোর সুপারিশ করে।
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.saveGState()
// clipping region - circle
ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 200, height: 200))
ctx.clip()
// content transformation
ctx.translateBy(x: 150, y: 150)
ctx.rotate(by: .pi / 4)
ctx.translateBy(x: -150, y: -150)
UIImage(named: "photo")?.draw(at: CGPoint(x: 50, y: 50))
ctx.restoreGState()
}
CGContext ব্যবহার করে গ্রেডিয়েন্ট চার্ট তৈরির একটি সম্পূর্ণ উদাহরণ দেখি। চার্টে অন্তর্ভুক্ত গ্রেডিয়েন্ট ফিল এবং টেক্সট লেবেল সহ তিনটি ভিন্ন রঙের সেক্টর। কোড একই কনটেক্সটে saveGState, clip, গ্রেডিয়েন্ট এবং টেক্সট রেন্ডারিংয়ের সমন্বয় প্রদর্শন করে।
class PieChartView: UIView {
private struct Slice {
let color: UIColor
let value: CGFloat
let label: String
}
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
let slices = [
Slice(color: .systemRed, value: 0.4, label: "iOS"),
Slice(color: .systemGreen, value: 0.35, label: "Android"),
Slice(color: .systemBlue, value: 0.25, label: "Other")
]
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = bounds.width * 0.35
var startAngle: CGFloat = -.pi / 2
for slice in slices {
let endAngle = startAngle + .pi * 2 * slice.value
ctx.saveGState()
ctx.moveTo(x: center.x, y: center.y)
ctx.addArc(center: center, radius: radius,
startAngle: startAngle, endAngle: endAngle, clockwise: false)
ctx.closePath()
ctx.setFillColor(slice.color.cgColor)
ctx.fillPath()
// text label
let midAngle = startAngle + endAngle / 2
let labelPos = CGPoint(
x: center.x + radius * 0.7 * cos(midAngle),
y: center.y + radius * 0.7 * sin(midAngle)
)
slice.label.draw(at: labelPos, withAttributes: [
.foregroundColor: UIColor.white,
.font: UIFont.boldSystemFont(ofSize: 14)
])
ctx.restoreGState()
startAngle = endAngle
}
}
}
এই উদাহরণে, চার্টের প্রতিটি সেক্টর তার নিজস্ব saveGState/restoreGState ব্লকে আঁকা হয়েছে। এই পদ্ধতি নিশ্চিত করে যে একটি সেক্টরের রঙ এবং পাথ সেটিংস অন্যগুলোকে প্রভাবিত করে না। addArc পদ্ধতি শুরু থেকে শেষ কোণ পর্যন্ত একটি চাপ তৈরি করে, এবং closePath সেক্টরটিকে কেন্দ্রের দিকে বন্ধ করে। লেবেল টেক্সট অবস্থান গণনার জন্য ত্রিকোণমিতিক ফাংশন cos এবং sin ব্যবহার করে সেক্টরের মধ্যকোণে স্থাপন করা হয়।
ঘন ঘন পুনঃঅঙ্কনের সময় কর্মক্ষমতা উন্নত করতে, কোণ এবং অবস্থান গণনা একটি পৃথক অ্যারেতে ক্যাশ করার সুপারিশ করা হয়। CGContext সমস্ত অপারেশন CPU তে সম্পাদন করে, তাই ডজনখানেক সেক্টরযুক্ত জটিল দৃশ্যে অপ্টিমাইজেশনের প্রয়োজন হতে পারে — উদাহরণস্বরূপ, CGLayer এ পূর্ব-রেন্ডারিং বা GPU ত্বরণের জন্য Metal ব্যবহার। 5–10 উপাদানযুক্ত বেশিরভাগ UI কাজের জন্য, CGContext এর কর্মক্ষমতা গ্রহণযোগ্য থাকে।
সচরাচর জিজ্ঞাসিত প্রশ্ন
UIView এর draw(_:) পদ্ধতির ভিতরে বা UIGraphicsBeginImageContextWithOptions ব্লকের ভিতরে UIGraphicsGetCurrentContext() কল করুন। CALayer স্তরগুলির জন্য, CALayerDelegate এর draw(in:) পদ্ধতি ব্যবহার করুন, যা একটি প্রস্তুত কনটেক্সট গ্রহণ করে।
fillPath বর্তমান পাথের অভ্যন্তরীণ অংশ setFillColor এর রঙ দিয়ে পূর্ণ করে। strokePath setStrokeColor, setLineWidth এবং setLineCap এর প্যারামিটার সহ পাথ বরাবর একটি রেখা আঁকে। উভয় অপারেশন ক্রমিকভাবে সম্পাদিত হয়: প্রথমে ফিল, তারপর প্রয়োজন হলে স্ট্রোক।
Bitmap CGContext CGBitmapContextCreate এর মাধ্যমে তৈরি একটি কনটেক্সট যা স্ক্রিনের পরিবর্তে মেমরি বাফারে আঁকে। এটি ব্যাকগ্রাউন্ড ইমেজ জেনারেশন, প্রদর্শন ছাড়া গ্রাফিক্স প্রক্রিয়াকরণ এবং Metal বা OpenGL এর জন্য টেক্সচার তৈরিতে ব্যবহৃত হয়।
Core Graphics সমস্ত সেটিংস রিসেট করার পদ্ধতি প্রদান করে না। পরিবর্তনের আগে saveGState এবং মূল অবস্থায় ফিরতে restoreGState ব্যবহার করুন। বিকল্পভাবে, একই প্যারামিটার সহ একটি নতুন কনটেক্সট তৈরি করুন।
drawLinearGradient কল করার আগে, পছন্দসই পাথে clip এর মাধ্যমে ক্লিপিং এলাকা সেট করুন। clip ছাড়া, গ্রেডিয়েন্ট সম্পূর্ণ কনটেক্সট পূর্ণ করে। ক্রম: addPath → clip → drawLinearGradient — আকৃতির ভিতরে গ্রেডিয়েন্ট নিশ্চিত করে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন