- (void) render: (EVDRenderContext &) aCtx : (DoRenderedPara) aDoRendered : (DoPageEnded) aPageEnded
{
EVDRenderedPara *l_Para = nil;
@try {
CFAttributedStringRef l_Text = self.Text;
int vTextLength = 0;
if (l_Text)
vTextLength = CFAttributedStringGetLength(l_Text);
if (vTextLength <= 0) {
// - пустые строки надо как-то отдельно обрабатывать
//aOffsetInParaRenderingNow = 0;
if (aCtx.rParaAdded)
aCtx.rRect.size.height -= 10;
l_Para = [[EVDRenderedPara alloc] initWithFrame: nil andPara: self];
aDoRendered(l_Para);
}
else {
CTFramesetterRef l_Framesetter = CTFramesetterCreateWithAttributedString(l_Text);
@try {
#ifdef UseHoles
CGMutablePathRef l_Path = CGPathCreateMutable();
CGPathAddRect(l_Path, NULL, aCtx.rRect);
CGFloat vHeight = 30;
vHeight = MIN(vHeight, aCtx.rRect.size.height - 10);
vHeight = MAX(0, vHeight);
// CGFloat vDelta = 20;
CGFloat vDelta = 0;
vDelta = -vDelta;
{
// CGFloat vIndent = 40;
CGFloat vIndent = 0;
// CGFloat vWidth = 50;
CGFloat vWidth = 80;
CGRect vHole;
vHole.origin.x = aCtx.rRect.origin.x + vIndent;
vHole.origin.y = aCtx.rRect.size.height - vHeight + vDelta;
vHole.size.width = vWidth;
vHole.size.height = vHeight + 10/* - vDelta*/;
if (vHole.origin.y >= 0) {
// CGPathAddEllipseInRect(l_Path, NULL, vHole);
CGPathAddRect(l_Path, NULL, vHole);
}
}
#else
CGPathRef l_Path = CGPathCreateWithRect(aCtx.rRect, NULL);
#endif // UseHoles
@try {
// CGMutablePathRef l_Path = CGPathCreateMutable();
// CGPathAddRect(l_Path, NULL, aRect);
CTFrameRef l_Frame = CTFramesetterCreateFrame(l_Framesetter,
CFRangeMake(aCtx.rCursor.rOffset, 0), l_Path, NULL);
@try {
l_Para = [[EVDRenderedPara alloc] initWithFrame: l_Frame andPara: self];
}
@finally {
if (l_Frame)
CFRelease(l_Frame);
}
}
@finally {
CFRelease(l_Path);
}
}
@finally {
CFRelease(l_Framesetter);
l_Framesetter = NULL;
}
aDoRendered(l_Para);
aCtx.rParaAdded = YES;
if ([l_Para CheckPageIsEnded: vTextLength : aCtx.rRect : aCtx.rCursor]) {
// - тут закончилась страница
aPageEnded();
}
}
}
@finally {
DESTROY(l_Para);
}
aCtx.rWasTableRow = NO;
}
- (void) render: (EVDRenderContext &) aCtx : (DoRenderedPara) aDoRendered : (DoPageEnded) aPageEnded
{
[self renderParas: aCtx : ^(id<IevdPara> vPara) {
[vPara render: aCtx : aDoRendered : ^() {
if ([self canBreak])
aPageEnded();
}];
}];
}
@implementation EVDHorzParaList
- (void) render: (EVDRenderContext &) aCtx : (DoRenderedPara) aDoRendered : (DoPageEnded) aPageEnded
{
CGRect vPrevRect = aCtx.rRect;
__block CGFloat vRowWidth = 0;
{
__block CGRect vRect = vPrevRect;
__block EVDParaIndexEx vCursor;
__block EVDRenderContext vCtx (vCursor, vRect, aCtx.rParaAdded);
[self renderParas: vCtx : ^(id<IevdPara> vPara) {
vRowWidth += [vPara width];
}];
}
__block CGFloat vHeight = std::numeric_limits<int>::max();
__block BOOL vPageEnded = NO;
__block EVDParaIndexEx::InnerCursors vInner;
__block EVDParaIndexEx::InnerCursors::const_iterator vIt = aCtx.rCursor.rInnerCursors.begin();
{
__block CGRect vRect = vPrevRect;
__block EVDParaIndexEx vCursor;
__block EVDRenderContext vCtx (vCursor, vRect, aCtx.rParaAdded);
[self renderParas: vCtx : ^(id<IevdPara> vPara) {
CGFloat vCellWidth = (vPrevRect.size.width * [vPara width]) / vRowWidth;
CGRect vParaRect = vRect;
vParaRect.size.width = vCellWidth - 8;
if ([vPara hasFrame]) {
vParaRect.origin.x += 3;
vParaRect.size.width -= 3;
}
vParaRect.origin.y = aCtx.rRect.origin.y;
vParaRect.size.height = aCtx.rRect.size.height;
EVDParaIndexEx vParaCursor;
if (vIt != aCtx.rCursor.rInnerCursors.end()) {
vParaCursor = *vIt;
vIt++;
}
EVDRenderContext vParaCtx (vParaCursor, vParaRect, vCtx.rParaAdded);
[vPara render: vParaCtx : aDoRendered : ^() {
vPageEnded = YES;
}];
vInner.push_back(vParaCursor);
vRect.origin.x += vCellWidth;
vHeight = MIN(vHeight, vParaRect.size.height);
}];
}
EVDTableRowFrame *vRowFrame = [[EVDTableRowFrame alloc] initWithFrame: NULL andPara: self];
@try {
CGFloat vDH = vPrevRect.size.height - vHeight;
__block CGRect vRect = vPrevRect;
vRect.origin.x -= 4;
__block EVDParaIndexEx vCursor;
__block EVDRenderContext vCtx (vCursor, vPrevRect, aCtx.rParaAdded);
__block BOOL vIsFirst = YES;
[self renderParas: vCtx : ^(id<IevdPara> vPara) {
CGFloat vCellWidth = (vPrevRect.size.width * [vPara width]) / vRowWidth;
if ([vPara hasFrame]) {
vRect.origin.y = vHeight + 23;
vRect.size.height = vDH;
vRect.size.width = vCellWidth;
EVDRenderedFrame * vFrame = [[EVDRenderedFrame alloc] initWithRect: vRect andPara: vPara];
@try{
if (vIsFirst) {
vIsFirst = NO;
vFrame->myIsFirst = YES;
}
if (!aCtx.rWasTableRow) {
vFrame->myIsFirstRow = YES;
}
[vRowFrame addRendered: vFrame];
}
@finally {
DESTROY(vFrame);
}
}
vRect.origin.x += vCellWidth;
}];
if ([vRowFrame hasRendered])
aDoRendered(vRowFrame);
}
@finally {
DESTROY(vRowFrame);
}
if (vPageEnded) {
aCtx.rCursor.rInnerCursors = vInner;
aCtx.rCursor.rPara--;
aPageEnded();
}
else {
aCtx.rCursor.rInnerCursors.clear();
aCtx.rRect.size.height = vHeight;
}
aCtx.rWasTableRow = YES;
}
- (BOOL) canBreak
{
return NO;
}
@end
- (void) draw: (CGContextRef) aContext forDoc: (id<IevdDocument>) aDoc
{
EVDSelection * vSelection = [aDoc selection];
if (vSelection) {
NodeKey vNodeKey = [myPara NodeKey];
EVDParaCursorLite vCursor(vNodeKey, [myPara indexInParent], 0, [[aDoc blockByKey: vNodeKey] ZOrder]);
if (vSelection->Has(vCursor))
[self fillPara: aContext withBackColor: [UIColor colorWithRed: 0.0627451 green: 0.419608 blue: 0.745098 alpha: 0.3] : NO];
}
[self fillPara: aContext withBackColor: [myPara backColor] : YES];
const EVDImage &vImage = [myPara headerImage: aDoc];
if (vImage.Image())
{
CTFrameRef vFrame = myFrame;
CGPathRef vFramePath = CTFrameGetPath(vFrame);
CGRect vFrameRect = CGPathGetBoundingBox(vFramePath);
NSArray *vLines = (NSArray *)CTFrameGetLines(vFrame);
int vLineCount = [vLines count];
if (vLineCount > 0) {
CGPoint vLineOrigin;
CTFrameGetLineOrigins(vFrame, CFRangeMake(0, 1), &vLineOrigin);
// CTFrameGetLineOrigins(aFrame, CFRangeMake(vLineCount - 1, 1), &vLineOrigin);
vLineOrigin.y -= 6;
// vLineOrigin.y -= 5;
// vFrameRect.size.height -= vLineOrigin.y;
vFrameRect.size.width = vImage.Width();
vFrameRect.size.height = vImage.Height();
vFrameRect.origin.y += vLineOrigin.y;
vFrameRect.origin.x += 10;
CGContextDrawImage(aContext, vFrameRect, vImage.Image().CGImage);
}
}
[aDoc fillStringToSearch: ^(const NSRange & aRange){
[self fillSelected: aContext range: aRange];
} forPara: myPara];
CTFrameDraw(myFrame, aContext);
CFAttributedStringRef vText = myPara.Text;
if (vText) {
[self checkSelected: NSMakeRange(0, CFAttributedStringGetLength(vText)) do: ^(const GlyphData & aData)
{
CFTypeRef vAttr = CFAttributedStringGetAttribute(vText, aData.rGlyphIndex, kCTRunDelegateAttributeName, NULL);
if (vAttr) {
CTRunDelegateRef delegate = (CTRunDelegateRef)vAttr;
NSDictionary *vDict = (NSDictionary*)CTRunDelegateGetRefCon(delegate);
if (vDict) {
CGRect vContextRect = CGContextGetClipBoundingBox(aContext);
UIImage *vGlyphImage = [vDict objectForKey:@"image"];
CGFloat vWidth = MIN([(NSString*)[vDict objectForKey:@"width"] floatValue], vContextRect.size.width - 40);
CGFloat vHeight = [(NSString*)[vDict objectForKey:@"height"] floatValue];
CGFloat vGap = [(NSString*)[vDict objectForKey:@"gap"] floatValue];
vWidth -= vGap;
if (vGlyphImage) {
CGContextDrawImage(aContext, CGRectMake(aData.rGlyphOrigin.x/* - vBox[0].origin.x*/, aData.rGlyphOrigin.y - 5/*- vBox[0].origin.y*/, vWidth, vHeight), vGlyphImage.CGImage);
}
}
}
}]; // [self checkSelected
} // vText
} // vNeedDrawPara
- (void) draw: (CGContextRef) aContext forDoc: (id<IevdDocument>) aDoc
{
int vCount = [myFrames count];
for (int i = 0; i < vCount; i++) {
[(EVDRenderedPara *)[myFrames objectAtIndex: i] draw: aContext forDoc: aDoc];
}
}
- (void) draw: (CGContextRef) aContext forDoc: (id<IevdDocument>) aDoc
{
/* Stroke a sequence of line segments one after another in `context'. The
line segments are specified by `points', an array of `count' CGPoints.
This function is equivalent to
CGContextBeginPath(context);
for (k = 0; k < count; k += 2) {
CGContextMoveToPoint(context, s[k].x, s[k].y);
CGContextAddLineToPoint(context, s[k+1].x, s[k+1].y);
}
CGContextStrokePath(context); */
id<IevdPara> vPara = [self para];
if (vPara) {
CGContextSetLineWidth(aContext, 1.0);
CGContextBeginPath(aContext);
if ([vPara prev] == nil) {
// левая рамка
CGContextMoveToPoint(aContext, myRect.origin.x, myRect.origin.y);
CGContextAddLineToPoint(aContext, myRect.origin.x, myRect.origin.y + myRect.size.height);
}
// правая рамка
CGContextMoveToPoint(aContext, myRect.origin.x + myRect.size.width, myRect.origin.y);
CGContextAddLineToPoint(aContext, myRect.origin.x + myRect.size.width, myRect.origin.y + myRect.size.height);
if (([vPara mergeStatus] != EVD::ms_Head) || ([[myRow para] next] == nil)) {
// нижняя рамка
CGContextMoveToPoint(aContext, myRect.origin.x, myRect.origin.y);
CGContextAddLineToPoint(aContext, myRect.origin.x + myRect.size.width, myRect.origin.y);
}
if (myIsFirstRow) {
// верхняя рамка
CGContextMoveToPoint(aContext, myRect.origin.x, myRect.origin.y + myRect.size.height);
CGContextAddLineToPoint(aContext, myRect.origin.x + myRect.size.width, myRect.origin.y + myRect.size.height);
}
CGContextStrokePath(aContext);
}
// CGContextStrokeRect(aContext, myRect);
}
Почти дельфийский код. Многое знакомо...
ОтветитьУдалить"Почти дельфийский код."
Удалить-- я старался "сохранять стиль".