import "HTMLView" import "tables" Block GetNextBlock(Block block) { // Do we have children? if(block.subBlocks.first) block = block.subBlocks.first; else { for(;block;) { // Do we have younger siblings? if(block.next) { block = block.next; break; } block = block.parent; } } return block; } /*static */Block NextBlockUp(Surface surface, Block block, int * centered, RenderFlags flags) { for(;block;) { // Do we have younger siblings? if(block.next) { if(block.type == FONT || block.type == ANCHOR) { surface.TextFont(block.parent.font.font); if(flags.render) surface.SetForeground(block.parent.textColor); } block = block.next; break; } //if(block) { if(block.type == FONT || block.type == ANCHOR) { surface.TextFont(block.parent.font.font); if(flags.render) surface.SetForeground(block.parent.textColor); } } block = block.parent; // Getting out of a block if(block) { /*if(block.type == FONT || block.type == ANCHOR) { surface.TextFont(block.prevFont.font.font); if(flags.render) surface.SetForeground(block.prevFont.textColor); } else */if(block.type == CENTER) { if(centered) (*centered)--; } } } return block; } /*static */Block NextBlock(Surface surface, Block block, int * centered, uint flags) { // Do we have children? if(block.subBlocks.first) block = block.subBlocks.first; else { block = NextBlockUp(surface, block, centered, flags); } return block; } int ComputeLine(Surface surface, Block startBlock, int startTextPos, Block * nextBlock, int * nextTextPos, int * centered, int * w, int maxW, int maxH, uint flags, int y, OldList leftObjects, OldList rightObjects, bool * changeLine, bool computeStartY, int sy, int sx) { int h = 0; int x = 0; bool lineComplete = false; AlignedObject object; Block block = startBlock; int textPos = startTextPos; int width = 0, height = 0; int centeredBefore = *centered; if(changeLine) *changeLine = true; *nextBlock = block; *nextTextPos = textPos; for(;!lineComplete && block;) { if(computeStartY && startTextPos == 0) { block.startX = x + sx; block.startY = y + sy; } switch(block.type) { case INPUT: { if(block.window) { width += block.window.size.w; height = Max(height, Max(26, block.window.size.h)); } break; } case IMAGE: { int bw = block.pWidth ? (maxW * block.pWidth / 100) : block.w; int bh = block.pHeight ? (maxH * block.pHeight / 100) : block.h; if(block.halign == left || block.halign == right) { height = Max(height, bh); h = Max(h, height); if(changeLine) *changeLine = false; if(leftObjects && rightObjects) { object = AlignedObject { w = bw, untilY = y + bh }; if(block.halign == left) leftObjects.Add(object); else rightObjects.Add(object); } lineComplete = true; *nextBlock = NextBlockUp(surface, block, centered, flags); *nextTextPos = 0; } else { *nextBlock = block; *nextTextPos = 0; h = Max(h, height); x += width; width = 0; if(x + width + bw > maxW && x > 0) { lineComplete = true; } else { width += bw; height = Max(height, bh); } } break; } case TEXT: { char * text = block.text; int th; // TO FIX: THIS USED TO BE COMMENTED... PUT IT BACK FOR DOCUMENTOR surface.TextExtent(" ", 1, null, &th); height = Max(height, th); for(; textPos maxW && x > 0) { lineComplete = true; break; } textPos += len; width += w; height = Max(height, th); if(nextSpace) { *nextTextPos = textPos; *nextBlock = block; h = Max(h, height); x += width; width = 0; } } block.height += height; break; } case FONT: case ANCHOR: surface.TextFont(block.font.font); break; case BR: { int th; surface.TextExtent(" ", 1, null, &th); lineComplete = true; *nextBlock = NextBlock(surface, block, null, flags); *nextTextPos = 0; height = Max(height, th); h = Max(h, height); x += width; width = 0; break; } case CENTER: (*centered)++; break; case TABLE: if(width || x) { lineComplete = true; *nextBlock = block; *nextTextPos = 0; h = Max(h, height); x += width; width = 0; } else if(block.halign == left || block.halign == right) { Font font = surface.font; ComputeTable(surface, block, textPos, &width, &height, maxW, maxH, flags, y + sy, x + sx); surface.font = font; x += width; *nextBlock = NextBlockUp(surface, block, centered, flags); *nextTextPos = 0; h = Max(h, height); if(changeLine) *changeLine = false; if(leftObjects && rightObjects) { object = AlignedObject { w = block.w, untilY = y + block.h }; if(block.halign == left) leftObjects.Add(object); else rightObjects.Add(object); } lineComplete = true; } else { Font font = surface.font; ComputeTable(surface, block, textPos, &width, &height, maxW, maxH, flags, y + sy, x + sx); surface.font = font; lineComplete = true; *nextBlock = NextBlockUp(surface, block, centered, flags); *nextTextPos = 0; h = Max(h, height); x += width; width = 0; } break; } if(lineComplete || !block) break; if(textPos >= block.textLen) { textPos = 0; block = NextBlock(surface, block, centered, flags); if(block && block.type == TEXT) block.height = 0; // Break line after if(centeredBefore != *centered) { lineComplete = true; *nextBlock = block; *nextTextPos = 0; h = Max(h, height); x += width; width = 0; } } } if(!lineComplete) { *nextBlock = null; *nextTextPos = 0; h = Max(h, height); x += width; width = 0; } *w = x; if(x > 1000000) { printf("bug"); } return h; } void RenderLine(HTMLView browser, Surface surface, int x, int y, int w, int h, Block startBlock, int startTextPos, Block endBlock, int endTextPos, int left, int right) { int textPos = startTextPos; Block block = startBlock; int startSel, endSel; Block startSelBlock = null, endSelBlock = null; int prevGlyph = 0; if(browser.textBlock != browser.selBlock || browser.curPosition != browser.selPosition) browser.NormalizeSelection(&startSelBlock, &startSel, &endSelBlock, &endSel); for(;;) { Color fore = surface.foreground, back = surface.background; if(block == endBlock && textPos >= endTextPos) break; switch(block.type) { case INPUT: { if(block.window) { x += block.window.size.w; } break; } case BODY: surface.SetForeground(block.textColor); break; case IMAGE: { int bw = block.pWidth ? (w * block.pWidth / 100) : block.w; int bh = block.pHeight ? (h * block.pHeight / 100) : block.h; int dx, dy; ColorAlpha fg = surface.GetForeground(); surface.SetForeground(white); switch(block.halign) { case HorizontalAlignment::left: block.valign = top; dx = x; break; case HorizontalAlignment::right: block.valign = top; dx = x + w - bw; dx = Max(x, dx); break; case middle: dx = x; break; } switch(block.valign) { case bottom: dy = y + h - bh; break; case top: dy = y; break; case middle: dy = y + (h - bh) / 2; break; } if(block.bitmap) { if(bw == block.bitmap.width && bh == block.bitmap.height) surface.Blit(block.bitmap, dx,dy,0,0,bw,bh); else surface.Stretch(block.bitmap, dx,dy,0,0,bw,bh,block.bitmap.width, block.bitmap.height); } else if(block.imageEntry && block.imageEntry.missing) { surface.Bevel(false, dx, dy, bw, bh); if(browser.missing.bitmap) surface.Blit(browser.missing.bitmap, dx + 5, dy + 5, 0,0, browser.missing.bitmap.width, browser.missing.bitmap.height); } surface.SetForeground(fg); x += bw; break; } case TEXT: { int tw, th; int endPos = (block == endBlock) ? endTextPos : block.textLen; int len = endPos - textPos; if(startSelBlock && block == startSelBlock && startSel >= textPos && startSel <= textPos + len) { int l = startSel - textPos; if(block.text) { surface.TextExtent2(block.text + textPos, l, &tw, &th, prevGlyph, &prevGlyph, null); surface.WriteText(x, y + h - th, block.text + textPos, l); x += tw; } textPos += l; browser.isSelected = true; len -= l; } if(endSelBlock && block == endSelBlock && endPos > textPos && endSel >= textPos && endSel < textPos + len) len = endSel - textPos; if(block.text) { if(browser.isSelected) { surface.background = Color { 10, 36, 106 }; surface.foreground = white; surface.textOpacity = true; } surface.TextExtent2(block.text + textPos, len, &tw, &th, prevGlyph, &prevGlyph, null); surface.WriteText(x, y + h - th, block.text + textPos, len); x += tw; if(browser.isSelected) { surface.background = back; surface.foreground = fore; surface.textOpacity = false; } } textPos += len; if(block == endSelBlock && textPos >= endSel) browser.isSelected = false; if(endPos > textPos) { int l = endPos - textPos; if(block.text) { surface.TextExtent2(block.text + textPos, l, &tw, &th, prevGlyph, &prevGlyph, null); surface.WriteText(x, y + h - th, block.text + textPos, l); x += tw; } textPos += l; } break; } case FONT: case ANCHOR: surface.TextFont(block.font.font); surface.SetForeground(block.textColor); break; case TABLE: RenderTable(browser, surface, x, y, w, h, left, right, block); block = NextBlockUp(surface, block, null, RenderFlags { render = true }); textPos = 0; break; } if(block == endBlock && textPos >= endTextPos) break; if(textPos >= block.textLen) { block = NextBlock(surface, block, null, RenderFlags { render = true }); textPos = 0; } } } bool PickLine(HTMLView browser, Surface surface, int x, int y, int w, int h, Block startBlock, int startTextPos, Block endBlock, int endTextPos, int left, int right, int pickX, int pickY, Block* pickBlock, int * pickTextPos) { bool result = false; int textPos = startTextPos; Block block = startBlock; for(;!result;) { if(block == endBlock && textPos >= endTextPos) break; switch(block.type) { case INPUT: { if(block.window) { x += block.window.size.w; } break; } case IMAGE: { int bw = block.pWidth ? (w * block.pWidth / 100) : block.w; int bh = block.pHeight ? (h * block.pHeight / 100) : block.h; int dx, dy; switch(block.halign) { case HorizontalAlignment::left: block.valign = top; dx = x; break; case HorizontalAlignment::right: block.valign = top; dx = x + w - bw; dx = Max(x, dx); break; case middle: dx = x; break; } switch(block.valign) { case bottom: dy = y + h - bh; break; case top: dy = y; break; case middle: dy = y + (h - bh) / 2; break; } if(block.bitmap || block.src) { if(pickX >= dx && pickY >= dy && pickX < dx + bw && pickY < dy + bh) { *pickBlock = block; *pickTextPos = 0; result = true; } } x += bw; break; } case TEXT: { int len, tw, th; if(block == endBlock) len = endTextPos - textPos; else len = block.textLen - textPos; surface.TextExtent(block.text + textPos, len, &tw, &th); // eSurface_WriteText(surface, x, y + h - th, block.text + textPos, len); if(block.text[0] == ' ' && block.text[1] == 0) pickX += tw; else if(pickX >= x && pickY >= y+h-th && pickX < x + tw + 2 && pickY < y+h) { result = true; *pickBlock = block; // Have to properly compute this *pickTextPos = 0; } textPos += len; x += tw; break; } case FONT: case ANCHOR: surface.TextFont(block.font.font); break; case TABLE: result = PickTable(browser, surface, x, y, w, h, left, right, block, pickX, pickY, pickBlock, pickTextPos); block = NextBlockUp(surface, block, null, RenderFlags { render = true }); textPos = 0; break; } if(block == endBlock && textPos >= endTextPos) break; if(textPos >= block.textLen) { block = NextBlock(surface, block, null, RenderFlags { render = true }); textPos = 0; } } return result; } void PositionLine(HTMLView browser, Surface surface, int x, int y, int w, int h, Block startBlock, int startTextPos, Block endBlock, int endTextPos, int left, int right) { int textPos = startTextPos; Block block = startBlock; for(;;) { if(block == endBlock && textPos >= endTextPos) break; switch(block.type) { case INPUT: { if(block.window) { Window parent = block.window.parent; block.window.Move( x + parent.scroll.x, y + parent.scroll.y, block.window.size.w, block.window.size.h); //block.window.visible = false; x += block.window.size.w; } break; } case IMAGE: { int bw = block.pWidth ? (w * block.pWidth / 100) : block.w; //int bh = block.pHeight ? (h * block.pHeight / 100) : block.h; int dx;//, dy; switch(block.halign) { case HorizontalAlignment::left: block.valign = top; dx = x; break; case HorizontalAlignment::right: block.valign = top; dx = x + w - bw; dx = Max(x, dx); break; case middle: dx = x; break; } /* switch(block.valign) { case bottom: dy = y + h - bh; break; case top: dy = y; break; case middle: dy = y + (h - bh) / 2; break; } */ x += bw; break; } case TEXT: { int len, tw, th; if(block == endBlock) len = endTextPos - textPos; else len = block.textLen - textPos; surface.TextExtent(block.text + textPos, len, &tw, &th); // eSurface_WriteText(surface, x, y + h - th, block.text + textPos, len); textPos += len; x += tw; break; } case FONT: case ANCHOR: surface.TextFont(block.font.font); break; case TABLE: PositionTable(browser, surface, x, y, w, h, left, right, block); block = NextBlockUp(surface, block, null, RenderFlags { render = true }); textPos = 0; break; } if(block == endBlock && textPos >= endTextPos) break; if(textPos >= block.textLen) { block = NextBlock(surface, block, null, RenderFlags { render = true }); textPos = 0; } } }