tiary::XMLNode *tiary::xml_parse (const char *str, size_t len) { xmlDocPtr doc; xmlNodePtr iptr; libxml2_init (); if (!(doc = xmlReadMemory (str, len, 0, 0, 0))) { return 0; } if (!(iptr = xmlDocGetRootElement (doc))) { xmlFreeDoc (doc); return 0; } // Successfully parsed. Now we need to construct our own XML tree // "(a,b) in stk" means "b's children should be copied as a's children" std::stack<std::pair<XMLNodeTree *, xmlNodePtr>, std::vector<std::pair<XMLNodeTree *, xmlNodePtr> > > stk; XMLNode *root = shallow_copy (iptr); XMLNodeTree *optr = dynamic_cast<XMLNodeTree *>(root); // Current working output node // Current working input node is iptr if (!optr) { // Root is a text node. Error. delete root; return 0; } XMLNode virtual_node; for (;;) { // Shallow copy all children of current node virtual_node.next = 0; XMLNode *last = &virtual_node; for (xmlNodePtr child_ptr = iptr->xmlChildrenNode; child_ptr; child_ptr = child_ptr->next) { if (XMLNode *newnode = shallow_copy (child_ptr)) { last = last->next = newnode; if (child_ptr->xmlChildrenNode) { stk.push (std::make_pair (static_cast<XMLNodeTree *>(newnode), child_ptr)); } } } optr->children = virtual_node.next; if (stk.empty ()) { break; } optr = stk.top().first; iptr = stk.top().second; stk.pop (); } xmlFreeDoc (doc); return root; }
Statement* Cssize::bubble(Media_Block* m) { Ruleset* parent = static_cast<Ruleset*>(shallow_copy(this->parent())); Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, parent->block()->pstate()); Ruleset* new_rule = SASS_MEMORY_NEW(ctx.mem, Ruleset, parent->pstate(), parent->selector(), bb); new_rule->tabs(parent->tabs()); for (size_t i = 0, L = m->block()->length(); i < L; ++i) { *new_rule->block() << (*m->block())[i]; } Block* wrapper_block = SASS_MEMORY_NEW(ctx.mem, Block, m->block()->pstate()); *wrapper_block << new_rule; Media_Block* mm = SASS_MEMORY_NEW(ctx.mem, Media_Block, m->pstate(), m->media_queries(), wrapper_block, 0); mm->tabs(m->tabs()); Bubble* bubble = SASS_MEMORY_NEW(ctx.mem, Bubble, mm->pstate(), mm); return bubble; }
/** * Description not yet available. * \param */ ivector& ivector::operator=(const ivector& t) { // disconnect ivector pointer from old array if (::allocated(*this)) { if (v != t.v) { if (indexmin() != t.indexmin() || indexmax() != t.indexmax()) { cerr << " Array sizes do not match in ivector operator" " =(const ivector&)" << endl; ad_exit(1); } for ( int i=indexmin(); i<=indexmax(); i++) { elem(i) = t.elem(i); } } } else { shallow_copy(t); } return (*this); }
/// Copy constructor dvar_vector::dvar_vector(const dvar_vector& other) { shallow_copy(other); #ifdef DEBUG cout << " Making copy for dvar_vector with ptr_address\n " << &va << " pointing at " << (va+indexmin()) << "\n"; #endif }
/*! zhematrix=_zhematrix operator */ inline zhematrix& zhematrix::operator=(const _zhematrix& mat) { #ifdef CPPL_VERBOSE std::cerr << "# [MARK] zhematrix::operator=(const _zhematrix&)" << std::endl; #endif//CPPL_VERBOSE shallow_copy(mat); return *this; }
/*! zcovector=_zcovector operator */ inline zcovector& zcovector::operator=(const _zcovector& vec) { #ifdef CPPL_VERBOSE std::cerr << "# [MARK] zcovector::operator=(const _zcovector&)" << std::endl; #endif//CPPL_VERBOSE shallow_copy(vec); return *this; }
std::string tiary::xml_make (const XMLNode *root) { /** * I have considered directly generating the XML text, which should * not be difficult to implement and obviously more efficient than * using libxml2. * * However, considering there are many details in XML that I may * easily forget, (say, always remember to replace special characters * with escape sequences starting with "&") * I decide to stick to libxml2. */ std::string ret; if (const XMLNodeTree *iroot = dynamic_cast <const XMLNodeTree *> (root)) { libxml2_init (); xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); // "1.0" - XML version xmlNodePtr oroot = xmlNewNode(0, BAD_CAST (iroot->name.c_str())); xmlDocSetRootElement(doc, oroot); // "(a,b) in stk" means "a's children should be copied as b's children" std::stack<std::pair<const XMLNodeTree *, xmlNodePtr>, std::vector<std::pair<const XMLNodeTree *, xmlNodePtr> > > stk; xmlNodePtr optr = oroot; // Current working output node const XMLNodeTree *iptr = iroot; // Current working input node for (;;) { // Shallow copy all children of current node for (XMLNode *child_ptr = iptr->children; child_ptr; child_ptr = child_ptr->next) { if (xmlNodePtr nptr = shallow_copy (child_ptr)) { xmlAddChild (optr, nptr); if (const XMLNodeTree *ip = dynamic_cast <const XMLNodeTree *> (child_ptr)) { stk.push (std::make_pair (ip, nptr)); } } } if (stk.empty ()) { break; } iptr = stk.top().first; optr = stk.top().second; stk.pop (); } xmlChar *str; int len; xmlDocDumpMemoryEnc (doc, &str, &len, "UTF-8"); xmlFreeDoc (doc); ret.assign ((const char*)str, len); xmlFree (str); } return ret; }
void Model::clear() { cleared(); auto segs = shallow_copy(m_segments); m_segments.clear(); for (auto seg : segs) seg->deleteLater(); auto pts = m_points; m_points.clear(); for (auto pt : pts) pt->deleteLater(); }
Statement* Cssize::bubble(At_Root_Block* m) { Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, this->parent()->pstate()); Has_Block* new_rule = static_cast<Has_Block*>(shallow_copy(this->parent())); new_rule->block(bb); new_rule->tabs(this->parent()->tabs()); for (size_t i = 0, L = m->block()->length(); i < L; ++i) { *new_rule->block() << (*m->block())[i]; } Block* wrapper_block = SASS_MEMORY_NEW(ctx.mem, Block, m->block()->pstate()); *wrapper_block << new_rule; At_Root_Block* mm = SASS_MEMORY_NEW(ctx.mem, At_Root_Block, m->pstate(), wrapper_block, m->expression()); Bubble* bubble = SASS_MEMORY_NEW(ctx.mem, Bubble, mm->pstate(), mm); return bubble; }
Statement* Cssize::bubble(At_Rule* m) { Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, this->parent()->pstate()); Has_Block* new_rule = static_cast<Has_Block*>(shallow_copy(this->parent())); new_rule->block(bb); new_rule->tabs(this->parent()->tabs()); size_t L = m->block() ? m->block()->length() : 0; for (size_t i = 0; i < L; ++i) { *new_rule->block() << (*m->block())[i]; } Block* wrapper_block = SASS_MEMORY_NEW(ctx.mem, Block, m->block() ? m->block()->pstate() : m->pstate()); *wrapper_block << new_rule; At_Rule* mm = SASS_MEMORY_NEW(ctx.mem, At_Rule, m->pstate(), m->keyword(), m->selector(), wrapper_block); if (m->value()) mm->value(m->value()); Bubble* bubble = SASS_MEMORY_NEW(ctx.mem, Bubble, mm->pstate(), mm); return bubble; }
void SkPicturePlayback::handleOp(SkReader32* reader, DrawType op, uint32_t size, SkCanvas* canvas, const SkMatrix& initialMatrix) { switch (op) { case NOOP: { SkASSERT(size >= 4); reader->skip(size - 4); } break; case CLIP_PATH: { const SkPath& path = fPictureData->getPath(reader); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipPath(path, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->setOffset(offsetToRestore); } } break; case CLIP_REGION: { SkRegion region; reader->readRegion(®ion); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRegion(region, regionOp); if (canvas->isClipEmpty() && offsetToRestore) { reader->setOffset(offsetToRestore); } } break; case CLIP_RECT: { const SkRect& rect = reader->skipT<SkRect>(); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRect(rect, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->setOffset(offsetToRestore); } } break; case CLIP_RRECT: { SkRRect rrect; reader->readRRect(&rrect); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRRect(rrect, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->setOffset(offsetToRestore); } } break; case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop. case POP_CULL: break; case CONCAT: { SkMatrix matrix; reader->readMatrix(&matrix); canvas->concat(matrix); break; } case DRAW_BITMAP: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); const SkPoint& loc = reader->skipT<SkPoint>(); canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint); } break; case DRAW_BITMAP_RECT_TO_RECT: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); const SkRect* src = get_rect_ptr(reader); // may be null const SkRect& dst = reader->skipT<SkRect>(); // required SkCanvas::DrawBitmapRectFlags flags; flags = (SkCanvas::DrawBitmapRectFlags) reader->readInt(); canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags); } break; case DRAW_BITMAP_MATRIX: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); SkMatrix matrix; reader->readMatrix(&matrix); SkAutoCanvasRestore acr(canvas, true); canvas->concat(matrix); canvas->drawBitmap(bitmap, 0, 0, paint); } break; case DRAW_BITMAP_NINE: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); const SkIRect& src = reader->skipT<SkIRect>(); const SkRect& dst = reader->skipT<SkRect>(); canvas->drawBitmapNine(bitmap, src, dst, paint); } break; case DRAW_CLEAR: canvas->clear(reader->readInt()); break; case DRAW_DATA: { size_t length = reader->readInt(); canvas->drawData(reader->skip(length), length); // skip handles padding the read out to a multiple of 4 } break; case DRAW_DRRECT: { const SkPaint& paint = *fPictureData->getPaint(reader); SkRRect outer, inner; reader->readRRect(&outer); reader->readRRect(&inner); canvas->drawDRRect(outer, inner, paint); } break; case BEGIN_COMMENT_GROUP: { const char* desc = reader->readString(); canvas->beginCommentGroup(desc); } break; case COMMENT: { const char* kywd = reader->readString(); const char* value = reader->readString(); canvas->addComment(kywd, value); } break; case END_COMMENT_GROUP: { canvas->endCommentGroup(); } break; case DRAW_OVAL: { const SkPaint& paint = *fPictureData->getPaint(reader); canvas->drawOval(reader->skipT<SkRect>(), paint); } break; case DRAW_PAINT: canvas->drawPaint(*fPictureData->getPaint(reader)); break; case DRAW_PATCH: { const SkPaint& paint = *fPictureData->getPaint(reader); const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); uint32_t flag = reader->readInt(); const SkColor* colors = NULL; if (flag & DRAW_VERTICES_HAS_COLORS) { colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor)); } const SkPoint* texCoords = NULL; if (flag & DRAW_VERTICES_HAS_TEXS) { texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkPoint)); } SkAutoTUnref<SkXfermode> xfer; if (flag & DRAW_VERTICES_HAS_XFER) { int mode = reader->readInt(); if (mode < 0 || mode > SkXfermode::kLastMode) { mode = SkXfermode::kModulate_Mode; } xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode)); } canvas->drawPatch(cubics, colors, texCoords, xfer, paint); } break; case DRAW_PATH: { const SkPaint& paint = *fPictureData->getPaint(reader); canvas->drawPath(fPictureData->getPath(reader), paint); } break; case DRAW_PICTURE: canvas->drawPicture(fPictureData->getPicture(reader)); break; case DRAW_PICTURE_MATRIX_PAINT: { const SkPaint* paint = fPictureData->getPaint(reader); SkMatrix matrix; reader->readMatrix(&matrix); const SkPicture* pic = fPictureData->getPicture(reader); canvas->drawPicture(pic, &matrix, paint); } break; case DRAW_POINTS: { const SkPaint& paint = *fPictureData->getPaint(reader); SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt(); size_t count = reader->readInt(); const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count); canvas->drawPoints(mode, count, pts, paint); } break; case DRAW_POS_TEXT: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t points = reader->readInt(); const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); canvas->drawPosText(text.text(), text.length(), pos, paint); } break; case DRAW_POS_TEXT_TOP_BOTTOM: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t points = reader->readInt(); const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); const SkScalar top = reader->readScalar(); const SkScalar bottom = reader->readScalar(); if (!canvas->quickRejectY(top, bottom)) { canvas->drawPosText(text.text(), text.length(), pos, paint); } } break; case DRAW_POS_TEXT_H: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t xCount = reader->readInt(); const SkScalar constY = reader->readScalar(); const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar)); canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint); } break; case DRAW_POS_TEXT_H_TOP_BOTTOM: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t xCount = reader->readInt(); const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar)); const SkScalar top = *xpos++; const SkScalar bottom = *xpos++; const SkScalar constY = *xpos++; if (!canvas->quickRejectY(top, bottom)) { canvas->drawPosTextH(text.text(), text.length(), xpos, constY, paint); } } break; case DRAW_RECT: { const SkPaint& paint = *fPictureData->getPaint(reader); canvas->drawRect(reader->skipT<SkRect>(), paint); } break; case DRAW_RRECT: { const SkPaint& paint = *fPictureData->getPaint(reader); SkRRect rrect; reader->readRRect(&rrect); canvas->drawRRect(rrect, paint); } break; case DRAW_SPRITE: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); int left = reader->readInt(); int top = reader->readInt(); canvas->drawSprite(bitmap, left, top, paint); } break; case DRAW_TEXT: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); SkScalar x = reader->readScalar(); SkScalar y = reader->readScalar(); canvas->drawText(text.text(), text.length(), x, y, paint); } break; case DRAW_TEXT_BLOB: { const SkPaint& paint = *fPictureData->getPaint(reader); const SkTextBlob* blob = fPictureData->getTextBlob(reader); SkScalar x = reader->readScalar(); SkScalar y = reader->readScalar(); canvas->drawTextBlob(blob, x, y, paint); } break; case DRAW_TEXT_TOP_BOTTOM: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar)); // ptr[0] == x // ptr[1] == y // ptr[2] == top // ptr[3] == bottom if (!canvas->quickRejectY(ptr[2], ptr[3])) { canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], paint); } } break; case DRAW_TEXT_ON_PATH: { const SkPaint& paint = *fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); const SkPath& path = fPictureData->getPath(reader); SkMatrix matrix; reader->readMatrix(&matrix); canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, paint); } break; case DRAW_VERTICES: { SkAutoTUnref<SkXfermode> xfer; const SkPaint& paint = *fPictureData->getPaint(reader); DrawVertexFlags flags = (DrawVertexFlags)reader->readInt(); SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt(); int vCount = reader->readInt(); const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); const SkPoint* texs = NULL; const SkColor* colors = NULL; const uint16_t* indices = NULL; int iCount = 0; if (flags & DRAW_VERTICES_HAS_TEXS) { texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); } if (flags & DRAW_VERTICES_HAS_COLORS) { colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor)); } if (flags & DRAW_VERTICES_HAS_INDICES) { iCount = reader->readInt(); indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t)); } if (flags & DRAW_VERTICES_HAS_XFER) { int mode = reader->readInt(); if (mode < 0 || mode > SkXfermode::kLastMode) { mode = SkXfermode::kModulate_Mode; } xfer.reset(SkXfermode::Create((SkXfermode::Mode)mode)); } canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, paint); } break; case RESTORE: canvas->restore(); break; case ROTATE: canvas->rotate(reader->readScalar()); break; case SAVE: // SKPs with version < 29 also store a SaveFlags param. if (size > 4) { SkASSERT(8 == size); reader->readInt(); } canvas->save(); break; case SAVE_LAYER: { const SkRect* boundsPtr = get_rect_ptr(reader); const SkPaint* paint = fPictureData->getPaint(reader); canvas->saveLayer(boundsPtr, paint, (SkCanvas::SaveFlags) reader->readInt()); } break; case SCALE: { SkScalar sx = reader->readScalar(); SkScalar sy = reader->readScalar(); canvas->scale(sx, sy); } break; case SET_MATRIX: { SkMatrix matrix; reader->readMatrix(&matrix); matrix.postConcat(initialMatrix); canvas->setMatrix(matrix); } break; case SKEW: { SkScalar sx = reader->readScalar(); SkScalar sy = reader->readScalar(); canvas->skew(sx, sy); } break; case TRANSLATE: { SkScalar dx = reader->readScalar(); SkScalar dy = reader->readScalar(); canvas->translate(dx, dy); } break; default: SkASSERTF(false, "Unknown draw type: %d", op); } }
/*! zgematrix=_zgematrix operator */ inline zgematrix& zgematrix::operator=(const _zgematrix& mat) {VERBOSE_REPORT; shallow_copy(mat); return *this; }
struct llist *get_selected_nodes (struct rooted_tree *tree, int selection) { struct llist *result; struct list_elem *el; struct rnode *node; switch (selection) { case ALL_NODES: result = shallow_copy(tree->nodes_in_order); if (NULL == result) {perror(NULL); exit(EXIT_FAILURE);} break; case ALL_LABELS: result = create_llist(); if (NULL == result) {perror(NULL); exit(EXIT_FAILURE);} for (el = tree->nodes_in_order->head; NULL != el; el = el->next) { node = el->data; if (0 != strcmp(node->label, "")) if (! append_element(result, node)) { perror(NULL); exit(EXIT_FAILURE); } } break; case ALL_LEAF_LABELS: result = create_llist(); if (NULL == result) {perror(NULL); exit(EXIT_FAILURE);} for (el = tree->nodes_in_order->head; NULL != el; el = el->next) { node = el->data; if (is_leaf(node) && (0 != strcmp(node->label, ""))) if (! append_element(result, node)) { perror(NULL); exit(EXIT_FAILURE); } } break; case ALL_LEAVES: result = create_llist(); if (NULL == result) {perror(NULL); exit(EXIT_FAILURE);} for (el = tree->nodes_in_order->head; NULL != el; el = el->next) { node = el->data; if (is_leaf(node)) if (! append_element(result, node)) { perror(NULL); exit(EXIT_FAILURE); } } break; case ALL_INNER_NODES: result = create_llist(); if (NULL == result) {perror(NULL); exit(EXIT_FAILURE);} for (el = tree->nodes_in_order->head; NULL != el; el = el->next) { node = el->data; if (is_inner_node(node)) if (! append_element(result, node)) { perror(NULL); exit(EXIT_FAILURE); } } break; default: fprintf (stderr, "ERROR: no selection code '%d'\n", selection); exit (EXIT_FAILURE); } return result; }
namespace SkRecords { // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads. static SkBitmap shallow_copy(const SkBitmap& bitmap) { return bitmap; } // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags)); DRAW(PopCull, popCull()); DRAW(PushCull, pushCull(r.rect)); DRAW(Clear, clear(r.color)); DRAW(Concat, concat(r.matrix)); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(ClipPath, clipPath(r.path, r.op, r.doAA)); DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA)); DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA)); DRAW(ClipRegion, clipRegion(r.region, r.op)); DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint)); DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint)); DRAW(DrawBitmapRectToRect, drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode.get(), r.paint)); DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint)); DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode.get(), r.indices, r.indexCount, r.paint)); #undef DRAW // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.count()) { // Calculate bounds for all ops. This won't go quite in order, so we'll need // to store the bounds separately then feed them in to the BBH later in order. fCTM.setIdentity(); for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { record.visit<void>(fCurrentOp, *this); } // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(SkIRect::MakeLargest()); } // Finally feed all stored bounds into the BBH. They'll be returned in this order. SkASSERT(NULL != bbh); for (uintptr_t i = 0; i < record.count(); i++) { if (!fBounds[i].isEmpty()) { bbh->insert((void*)i, fBounds[i], true/*ok to defer*/); } } bbh->flushDeferredInserts(); } template <typename T> void operator()(const T& r) { this->updateCTM(r); this->trackBounds(r); } private: struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. SkIRect bounds; // Bounds of everything in the block. }; template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ } void updateCTM(const Restore& r) { fCTM = r.matrix; } void updateCTM(const SetMatrix& r) { fCTM = r.matrix; } void updateCTM(const Concat& r) { fCTM.preConcat(r.matrix); } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(); } // TODO: bounds of SaveLayer may be more complicated? void trackBounds(const SaveLayer&) { this->pushSaveBlock(); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const Concat&) { this->pushControl(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } // TODO: remove this trivially-safe default when done bounding all ops template <typename T> SkIRect bounds(const T&) { return SkIRect::MakeLargest(); } void pushSaveBlock() { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb = { 0, SkIRect::MakeEmpty() }; fSaveStack.push(sb); this->pushControl(); } SkIRect popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const SkIRect& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const SkIRect& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps don't draw anywhere. SkAutoTMalloc<SkIRect> fBounds; // One for each op in the record. SkMatrix fCTM; unsigned fCurrentOp; SkTDArray<SaveBounds> fSaveStack; SkTDArray<unsigned> fControlIndices; }; } // namespace SkRecords
int test_shallow_copy() { char *test_name = "test_shallow_copy"; struct llist *list_p, *list_copy_p; struct list_elem *elem; char label_two[] = {'t', 'w', 'o', '\0'}; list_p = create_llist(); append_element(list_p, "one"); append_element(list_p, label_two); /* see below */ append_element(list_p, "three"); append_element(list_p, "four"); append_element(list_p, "five"); list_copy_p = shallow_copy(list_p); /* test list membership and count */ elem = list_copy_p->head; if (strcmp(elem->data, "one") != 0) { printf ("%s: expected 'one', got %s.\n", test_name, (char *) elem->data); return 1; } elem = elem->next; if (strcmp(elem->data, "two") != 0) { printf ("%s: expected 'two', got %s.\n", test_name, (char *) elem->data); return 1; } elem = elem->next; if (strcmp(elem->data, "three") != 0) { printf ("%s: expected 'three', got %s.\n", test_name, (char *) elem->data); return 1; } elem = elem->next; if (strcmp(elem->data, "four") != 0) { printf ("%s: expected 'four', got %s.\n", test_name, (char *) elem->data); return 1; } elem = elem->next; if (strcmp(elem->data, "five") != 0) { printf ("%s: expected 'five', got %s.\n", test_name, (char *) elem->data); return 1; } if(list_p->count != 5) { printf ("%s: count should be 5.\n", test_name); return 1; } /* Check that copy is shallow, i.e., original list members are the * same a s copy members */ /* String constants cannot be modified (SIGSEGV!), which is why we * used an array for label #2 */ elem = list_p->head->next; /* should work with any of them */ label_two[0] = 'z'; elem = list_copy_p->head->next; if (strcmp(elem->data, "zwo") != 0) { printf ("%s: expected element in copy to be 'zwo' (got '%s').\n", test_name, (char *) elem->data); return 1; } printf("%s ok.\n", test_name); return 0; }
void SkPicturePlayback::handleOp(SkReadBuffer* reader, DrawType op, uint32_t size, SkCanvas* canvas, const SkMatrix& initialMatrix) { switch (op) { case NOOP: { SkASSERT(size >= 4); reader->skip(size - 4); } break; case CLIP_PATH: { const SkPath& path = fPictureData->getPath(reader); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipPath(path, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->skip(offsetToRestore - reader->offset()); } } break; case CLIP_REGION: { SkRegion region; reader->readRegion(®ion); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRegion(region, regionOp); if (canvas->isClipEmpty() && offsetToRestore) { reader->skip(offsetToRestore - reader->offset()); } } break; case CLIP_RECT: { SkRect rect; reader->readRect(&rect); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRect(rect, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->skip(offsetToRestore - reader->offset()); } } break; case CLIP_RRECT: { SkRRect rrect; reader->readRRect(&rrect); uint32_t packed = reader->readInt(); SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); bool doAA = ClipParams_unpackDoAA(packed); size_t offsetToRestore = reader->readInt(); SkASSERT(!offsetToRestore || offsetToRestore >= reader->offset()); canvas->clipRRect(rrect, regionOp, doAA); if (canvas->isClipEmpty() && offsetToRestore) { reader->skip(offsetToRestore - reader->offset()); } } break; case PUSH_CULL: break; // Deprecated, safe to ignore both push and pop. case POP_CULL: break; case CONCAT: { SkMatrix matrix; reader->readMatrix(&matrix); canvas->concat(matrix); break; } case DRAW_ANNOTATION: { SkRect rect; reader->readRect(&rect); SkString key; reader->readString(&key); canvas->drawAnnotation(rect, key.c_str(), reader->readByteArrayAsData().get()); } break; case DRAW_ATLAS: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* atlas = fPictureData->getImage(reader); const uint32_t flags = reader->readUInt(); const int count = reader->readUInt(); const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform)); const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect)); const SkColor* colors = nullptr; SkXfermode::Mode mode = SkXfermode::kDst_Mode; if (flags & DRAW_ATLAS_HAS_COLORS) { colors = (const SkColor*)reader->skip(count * sizeof(SkColor)); mode = (SkXfermode::Mode)reader->readUInt(); } const SkRect* cull = nullptr; if (flags & DRAW_ATLAS_HAS_CULL) { cull = (const SkRect*)reader->skip(sizeof(SkRect)); } canvas->drawAtlas(atlas, xform, tex, colors, count, mode, cull, paint); } break; case DRAW_BITMAP: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); SkPoint loc; reader->readPoint(&loc); canvas->drawBitmap(bitmap, loc.fX, loc.fY, paint); } break; case DRAW_BITMAP_RECT: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); SkRect storage; const SkRect* src = get_rect_ptr(reader, &storage); // may be null SkRect dst; reader->readRect(&dst); // required SkCanvas::SrcRectConstraint constraint = (SkCanvas::SrcRectConstraint)reader->readInt(); canvas->legacy_drawBitmapRect(bitmap, src, dst, paint, constraint); } break; case DRAW_BITMAP_MATRIX: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); SkMatrix matrix; reader->readMatrix(&matrix); SkAutoCanvasRestore acr(canvas, true); canvas->concat(matrix); canvas->drawBitmap(bitmap, 0, 0, paint); } break; case DRAW_BITMAP_NINE: { const SkPaint* paint = fPictureData->getPaint(reader); const SkBitmap bitmap = shallow_copy(fPictureData->getBitmap(reader)); SkIRect src; reader->readIRect(&src); SkRect dst; reader->readRect(&dst); canvas->drawBitmapNine(bitmap, src, dst, paint); } break; case DRAW_CLEAR: canvas->clear(reader->readInt()); break; case DRAW_DATA: { // This opcode is now dead, just need to skip it for backwards compatibility size_t length = reader->readInt(); (void)reader->skip(length); // skip handles padding the read out to a multiple of 4 } break; case DRAW_DRAWABLE: canvas->drawDrawable(fPictureData->getDrawable(reader)); break; case DRAW_DRAWABLE_MATRIX: { SkMatrix matrix; reader->readMatrix(&matrix); SkDrawable* drawable = fPictureData->getDrawable(reader); canvas->drawDrawable(drawable, &matrix); } break; case DRAW_DRRECT: { const SkPaint* paint = fPictureData->getPaint(reader); SkRRect outer, inner; reader->readRRect(&outer); reader->readRRect(&inner); if (paint) { canvas->drawDRRect(outer, inner, *paint); } } break; case BEGIN_COMMENT_GROUP: { SkString tmp; reader->readString(&tmp); // deprecated (M44) break; } case COMMENT: { SkString tmp; reader->readString(&tmp); reader->readString(&tmp); // deprecated (M44) break; } case END_COMMENT_GROUP: // deprecated (M44) break; case DRAW_IMAGE: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* image = fPictureData->getImage(reader); SkPoint loc; reader->readPoint(&loc); canvas->drawImage(image, loc.fX, loc.fY, paint); } break; case DRAW_IMAGE_NINE: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* image = fPictureData->getImage(reader); SkIRect center; reader->readIRect(¢er); SkRect dst; reader->readRect(&dst); canvas->drawImageNine(image, center, dst, paint); } break; case DRAW_IMAGE_RECT_STRICT: case DRAW_IMAGE_RECT: { const SkPaint* paint = fPictureData->getPaint(reader); const SkImage* image = fPictureData->getImage(reader); SkRect storage; const SkRect* src = get_rect_ptr(reader, &storage); // may be null SkRect dst; reader->readRect(&dst); // required // DRAW_IMAGE_RECT_STRICT assumes this constraint, and doesn't store it SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint; if (DRAW_IMAGE_RECT == op) { // newer op-code stores the constraint explicitly constraint = (SkCanvas::SrcRectConstraint)reader->readInt(); } canvas->legacy_drawImageRect(image, src, dst, paint, constraint); } break; case DRAW_OVAL: { const SkPaint* paint = fPictureData->getPaint(reader); SkRect rect; reader->readRect(&rect); if (paint) { canvas->drawOval(rect, *paint); } } break; case DRAW_PAINT: { const SkPaint* paint = fPictureData->getPaint(reader); if (paint) { canvas->drawPaint(*paint); } } break; case DRAW_PATCH: { const SkPaint* paint = fPictureData->getPaint(reader); const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); uint32_t flag = reader->readInt(); const SkColor* colors = nullptr; if (flag & DRAW_VERTICES_HAS_COLORS) { colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor)); } const SkPoint* texCoords = nullptr; if (flag & DRAW_VERTICES_HAS_TEXS) { texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkPoint)); } sk_sp<SkXfermode> xfer; if (flag & DRAW_VERTICES_HAS_XFER) { int mode = reader->readInt(); if (mode < 0 || mode > SkXfermode::kLastMode) { mode = SkXfermode::kModulate_Mode; } xfer = SkXfermode::Make((SkXfermode::Mode)mode); } if (paint) { canvas->drawPatch(cubics, colors, texCoords, std::move(xfer), *paint); } } break; case DRAW_PATH: { const SkPaint* paint = fPictureData->getPaint(reader); if (paint) { canvas->drawPath(fPictureData->getPath(reader), *paint); } } break; case DRAW_PICTURE: canvas->drawPicture(fPictureData->getPicture(reader)); break; case DRAW_PICTURE_MATRIX_PAINT: { const SkPaint* paint = fPictureData->getPaint(reader); SkMatrix matrix; reader->readMatrix(&matrix); const SkPicture* pic = fPictureData->getPicture(reader); canvas->drawPicture(pic, &matrix, paint); } break; case DRAW_POINTS: { const SkPaint* paint = fPictureData->getPaint(reader); SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt(); size_t count = reader->readInt(); const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count); if (paint) { canvas->drawPoints(mode, count, pts, *paint); } } break; case DRAW_POS_TEXT: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t points = reader->readInt(); const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); if (paint) { canvas->drawPosText(text.text(), text.length(), pos, *paint); } } break; case DRAW_POS_TEXT_TOP_BOTTOM: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t points = reader->readInt(); const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint)); const SkScalar top = reader->readScalar(); const SkScalar bottom = reader->readScalar(); if (!canvas->quickRejectY(top, bottom) && paint) { canvas->drawPosText(text.text(), text.length(), pos, *paint); } } break; case DRAW_POS_TEXT_H: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t xCount = reader->readInt(); const SkScalar constY = reader->readScalar(); const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar)); if (paint) { canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint); } } break; case DRAW_POS_TEXT_H_TOP_BOTTOM: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); size_t xCount = reader->readInt(); const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar)); const SkScalar top = *xpos++; const SkScalar bottom = *xpos++; const SkScalar constY = *xpos++; if (!canvas->quickRejectY(top, bottom) && paint) { canvas->drawPosTextH(text.text(), text.length(), xpos, constY, *paint); } } break; case DRAW_RECT: { const SkPaint* paint = fPictureData->getPaint(reader); SkRect rect; reader->readRect(&rect); if (paint) { canvas->drawRect(rect, *paint); } } break; case DRAW_RRECT: { const SkPaint* paint = fPictureData->getPaint(reader); SkRRect rrect; reader->readRRect(&rrect); if (paint) { canvas->drawRRect(rrect, *paint); } } break; case DRAW_SPRITE: { /* const SkPaint* paint = */ fPictureData->getPaint(reader); /* const SkBitmap bitmap = */ shallow_copy(fPictureData->getBitmap(reader)); /* int left = */ reader->readInt(); /* int top = */ reader->readInt(); // drawSprite removed dec-2015 } break; case DRAW_TEXT: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); SkScalar x = reader->readScalar(); SkScalar y = reader->readScalar(); if (paint) { canvas->drawText(text.text(), text.length(), x, y, *paint); } } break; case DRAW_TEXT_BLOB: { const SkPaint* paint = fPictureData->getPaint(reader); const SkTextBlob* blob = fPictureData->getTextBlob(reader); SkScalar x = reader->readScalar(); SkScalar y = reader->readScalar(); if (paint) { canvas->drawTextBlob(blob, x, y, *paint); } } break; case DRAW_TEXT_TOP_BOTTOM: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); const SkScalar* ptr = (const SkScalar*)reader->skip(4 * sizeof(SkScalar)); // ptr[0] == x // ptr[1] == y // ptr[2] == top // ptr[3] == bottom if (!canvas->quickRejectY(ptr[2], ptr[3]) && paint) { canvas->drawText(text.text(), text.length(), ptr[0], ptr[1], *paint); } } break; case DRAW_TEXT_ON_PATH: { const SkPaint* paint = fPictureData->getPaint(reader); TextContainer text; get_text(reader, &text); const SkPath& path = fPictureData->getPath(reader); SkMatrix matrix; reader->readMatrix(&matrix); if (paint) { canvas->drawTextOnPath(text.text(), text.length(), path, &matrix, *paint); } } break; case DRAW_TEXT_RSXFORM: { const SkPaint* paint = fPictureData->getPaint(reader); int count = reader->readInt(); uint32_t flags = reader->read32(); TextContainer text; get_text(reader, &text); const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform)); const SkRect* cull = nullptr; if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) { cull = (const SkRect*)reader->skip(sizeof(SkRect)); } canvas->drawTextRSXform(text.text(), text.length(), xform, cull, *paint); } break; case DRAW_VERTICES: { sk_sp<SkXfermode> xfer; const SkPaint* paint = fPictureData->getPaint(reader); DrawVertexFlags flags = (DrawVertexFlags)reader->readInt(); SkCanvas::VertexMode vmode = (SkCanvas::VertexMode)reader->readInt(); int vCount = reader->readInt(); const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); const SkPoint* texs = nullptr; const SkColor* colors = nullptr; const uint16_t* indices = nullptr; int iCount = 0; if (flags & DRAW_VERTICES_HAS_TEXS) { texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint)); } if (flags & DRAW_VERTICES_HAS_COLORS) { colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor)); } if (flags & DRAW_VERTICES_HAS_INDICES) { iCount = reader->readInt(); indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t)); } if (flags & DRAW_VERTICES_HAS_XFER) { int mode = reader->readInt(); if (mode < 0 || mode > SkXfermode::kLastMode) { mode = SkXfermode::kModulate_Mode; } xfer = SkXfermode::Make((SkXfermode::Mode)mode); } if (paint) { canvas->drawVertices(vmode, vCount, verts, texs, colors, xfer, indices, iCount, *paint); } } break; case RESTORE: canvas->restore(); break; case ROTATE: canvas->rotate(reader->readScalar()); break; case SAVE: // SKPs with version < 29 also store a SaveFlags param. if (size > 4) { if (reader->validate(8 == size)) { reader->readInt(); } } canvas->save(); break; case SAVE_LAYER_SAVEFLAGS_DEPRECATED: { SkRect storage; const SkRect* boundsPtr = get_rect_ptr(reader, &storage); const SkPaint* paint = fPictureData->getPaint(reader); auto flags = SkCanvas::LegacySaveFlagsToSaveLayerFlags(reader->readInt()); canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, flags)); } break; case SAVE_LAYER_SAVELAYERFLAGS_DEPRECATED_JAN_2016: { SkRect storage; const SkRect* boundsPtr = get_rect_ptr(reader, &storage); const SkPaint* paint = fPictureData->getPaint(reader); canvas->saveLayer(SkCanvas::SaveLayerRec(boundsPtr, paint, reader->readInt())); } break; case SAVE_LAYER_SAVELAYERREC: { SkCanvas::SaveLayerRec rec(nullptr, nullptr, nullptr, 0); const uint32_t flatFlags = reader->readInt(); SkRect bounds; if (flatFlags & SAVELAYERREC_HAS_BOUNDS) { reader->readRect(&bounds); rec.fBounds = &bounds; } if (flatFlags & SAVELAYERREC_HAS_PAINT) { rec.fPaint = fPictureData->getPaint(reader); } if (flatFlags & SAVELAYERREC_HAS_BACKDROP) { const SkPaint* paint = fPictureData->getPaint(reader); rec.fBackdrop = paint->getImageFilter(); } if (flatFlags & SAVELAYERREC_HAS_FLAGS) { rec.fSaveLayerFlags = reader->readInt(); } canvas->saveLayer(rec); } break; case SCALE: { SkScalar sx = reader->readScalar(); SkScalar sy = reader->readScalar(); canvas->scale(sx, sy); } break; case SET_MATRIX: { SkMatrix matrix; reader->readMatrix(&matrix); matrix.postConcat(initialMatrix); canvas->setMatrix(matrix); } break; case SKEW: { SkScalar sx = reader->readScalar(); SkScalar sy = reader->readScalar(); canvas->skew(sx, sy); } break; case TRANSLATE: { SkScalar dx = reader->readScalar(); SkScalar dy = reader->readScalar(); canvas->translate(dx, dy); } break; default: SkASSERTF(false, "Unknown draw type: %d", op); } }
namespace SkRecords { // FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads. static SkBitmap shallow_copy(const SkBitmap& bitmap) { return bitmap; } // NoOps draw nothing. template <> void Draw::draw(const NoOp&) {} #define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; } DRAW(Restore, restore()); DRAW(Save, save()); DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags)); DRAW(PopCull, popCull()); DRAW(PushCull, pushCull(r.rect)); DRAW(Clear, clear(r.color)); DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix))); DRAW(ClipPath, clipPath(r.path, r.op, r.doAA)); DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA)); DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA)); DRAW(ClipRegion, clipRegion(r.region, r.op)); DRAW(BeginCommentGroup, beginCommentGroup(r.description)); DRAW(AddComment, addComment(r.key, r.value)); DRAW(EndCommentGroup, endCommentGroup()); DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint)); DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint)); DRAW(DrawBitmapRectToRect, drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags)); DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint)); DRAW(DrawImage, drawImage(r.image, r.left, r.top, r.paint)); DRAW(DrawImageRect, drawImageRect(r.image, r.src, r.dst, r.paint)); DRAW(DrawOval, drawOval(r.oval, r.paint)); DRAW(DrawPaint, drawPaint(r.paint)); DRAW(DrawPath, drawPath(r.path, r.paint)); DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint)); DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint)); DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint)); DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint)); DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint)); DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); DRAW(DrawRect, drawRect(r.rect, r.paint)); DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); DRAW(DrawTextBlob, drawTextBlob(r.blob, r.x, r.y, r.paint)); DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint)); DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors, r.xmode.get(), r.indices, r.indexCount, r.paint)); DRAW(DrawData, drawData(r.data, r.length)); #undef DRAW // This is an SkRecord visitor that fills an SkBBoxHierarchy. // // The interesting part here is how to calculate bounds for ops which don't // have intrinsic bounds. What is the bounds of a Save or a Translate? // // We answer this by thinking about a particular definition of bounds: if I // don't execute this op, pixels in this rectangle might draw incorrectly. So // the bounds of a Save, a Translate, a Restore, etc. are the union of the // bounds of Draw* ops that they might have an effect on. For any given // Save/Restore block, the bounds of the Save, the Restore, and any other // non-drawing ("control") ops inside are exactly the union of the bounds of // the drawing ops inside that block. // // To implement this, we keep a stack of active Save blocks. As we consume ops // inside the Save/Restore block, drawing ops are unioned with the bounds of // the block, and control ops are stashed away for later. When we finish the // block with a Restore, our bounds are complete, and we go back and fill them // in for all the control ops we stashed away. class FillBounds : SkNoncopyable { public: FillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHierarchy* bbh) : fCullRect(cullRect) , fBounds(record.count()) { // Calculate bounds for all ops. This won't go quite in order, so we'll need // to store the bounds separately then feed them in to the BBH later in order. fCTM = &SkMatrix::I(); fCurrentClipBounds = fCullRect; for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { record.visit<void>(fCurrentOp, *this); } // If we have any lingering unpaired Saves, simulate restores to make // sure all ops in those Save blocks have their bounds calculated. while (!fSaveStack.isEmpty()) { this->popSaveBlock(); } // Any control ops not part of any Save/Restore block draw everywhere. while (!fControlIndices.isEmpty()) { this->popControl(fCullRect); } // Finally feed all stored bounds into the BBH. They'll be returned in this order. SkASSERT(bbh); bbh->insert(&fBounds, record.count()); } template <typename T> void operator()(const T& op) { this->updateCTM(op); this->updateClipBounds(op); this->trackBounds(op); } private: // In this file, SkRect are in local coordinates, Bounds are translated back to identity space. typedef SkRect Bounds; struct SaveBounds { int controlOps; // Number of control ops in this Save block, including the Save. Bounds bounds; // Bounds of everything in the block. const SkPaint* paint; // Unowned. If set, adjusts the bounds of all ops in this block. }; // Only Restore and SetMatrix change the CTM. template <typename T> void updateCTM(const T&) {} void updateCTM(const Restore& op) { fCTM = &op.matrix; } void updateCTM(const SetMatrix& op) { fCTM = &op.matrix; } // Most ops don't change the clip. template <typename T> void updateClipBounds(const T&) {} // Clip{Path,RRect,Rect,Region} obviously change the clip. They all know their bounds already. void updateClipBounds(const ClipPath& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRect& op) { this->updateClipBoundsForClipOp(op.devBounds); } void updateClipBounds(const ClipRegion& op) { this->updateClipBoundsForClipOp(op.devBounds); } // The bounds of clip ops need to be adjusted for the paints of saveLayers they're inside. void updateClipBoundsForClipOp(const SkIRect& devBounds) { Bounds clip = SkRect::Make(devBounds); // We don't call adjustAndMap() because as its last step it would intersect the adjusted // clip bounds with the previous clip, exactly what we can't do when the clip grows. fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip) ? clip : fCullRect; } // Restore holds the devBounds for the clip after the {save,saveLayer}/restore block completes. void updateClipBounds(const Restore& op) { // This is just like the clip ops above, but we need to skip the effects (if any) of our // paired saveLayer (if it is one); it has not yet been popped off the save stack. Our // devBounds reflect the state of the world after the saveLayer/restore block is done, // so they are not affected by the saveLayer's paint. const int kSavesToIgnore = 1; Bounds clip = SkRect::Make(op.devBounds); fCurrentClipBounds = this->adjustForSaveLayerPaints(&clip, kSavesToIgnore) ? clip : fCullRect; } // We also take advantage of SaveLayer bounds when present to further cut the clip down. void updateClipBounds(const SaveLayer& op) { if (op.bounds) { // adjustAndMap() intersects these layer bounds with the previous clip for us. fCurrentClipBounds = this->adjustAndMap(*op.bounds, op.paint); } } // The bounds of these ops must be calculated when we hit the Restore // from the bounds of the ops in the same Save block. void trackBounds(const Save&) { this->pushSaveBlock(NULL); } void trackBounds(const SaveLayer& op) { this->pushSaveBlock(op.paint); } void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlock(); } void trackBounds(const SetMatrix&) { this->pushControl(); } void trackBounds(const ClipRect&) { this->pushControl(); } void trackBounds(const ClipRRect&) { this->pushControl(); } void trackBounds(const ClipPath&) { this->pushControl(); } void trackBounds(const ClipRegion&) { this->pushControl(); } void trackBounds(const PushCull&) { this->pushControl(); } void trackBounds(const PopCull&) { this->pushControl(); } void trackBounds(const BeginCommentGroup&) { this->pushControl(); } void trackBounds(const AddComment&) { this->pushControl(); } void trackBounds(const EndCommentGroup&) { this->pushControl(); } void trackBounds(const DrawData&) { this->pushControl(); } // For all other ops, we can calculate and store the bounds directly now. template <typename T> void trackBounds(const T& op) { fBounds[fCurrentOp] = this->bounds(op); this->updateSaveBounds(fBounds[fCurrentOp]); } void pushSaveBlock(const SkPaint* paint) { // Starting a new Save block. Push a new entry to represent that. SaveBounds sb; sb.controlOps = 0; // If the paint affects transparent black, the bound shouldn't be smaller // than the current clip bounds. sb.bounds = PaintMayAffectTransparentBlack(paint) ? fCurrentClipBounds : Bounds::MakeEmpty(); sb.paint = paint; fSaveStack.push(sb); this->pushControl(); } static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { if (paint) { // FIXME: this is very conservative if (paint->getImageFilter() || paint->getColorFilter()) { return true; } // Unusual Xfermodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 SkXfermode* xfermode = paint->getXfermode(); SkXfermode::Mode mode; // SrcOver is ok, and is also the common case with a NULL xfermode. // So we should make that the fast path and bypass the mode extraction // and test. if (xfermode && xfermode->asMode(&mode)) { switch (mode) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended alpha is not necessarily equal to the original // destination alpha. case SkXfermode::kClear_Mode: case SkXfermode::kSrc_Mode: case SkXfermode::kSrcIn_Mode: case SkXfermode::kDstIn_Mode: case SkXfermode::kSrcOut_Mode: case SkXfermode::kDstATop_Mode: case SkXfermode::kModulate_Mode: return true; break; default: break; } } } return false; } Bounds popSaveBlock() { // We're done the Save block. Apply the block's bounds to all control ops inside it. SaveBounds sb; fSaveStack.pop(&sb); while (sb.controlOps --> 0) { this->popControl(sb.bounds); } // This whole Save block may be part another Save block. this->updateSaveBounds(sb.bounds); // If called from a real Restore (not a phony one for balance), it'll need the bounds. return sb.bounds; } void pushControl() { fControlIndices.push(fCurrentOp); if (!fSaveStack.isEmpty()) { fSaveStack.top().controlOps++; } } void popControl(const Bounds& bounds) { fBounds[fControlIndices.top()] = bounds; fControlIndices.pop(); } void updateSaveBounds(const Bounds& bounds) { // If we're in a Save block, expand its bounds to cover these bounds too. if (!fSaveStack.isEmpty()) { fSaveStack.top().bounds.join(bounds); } } // FIXME: this method could use better bounds Bounds bounds(const DrawText&) const { return fCurrentClipBounds; } Bounds bounds(const Clear&) const { return fCullRect; } // Ignores the clip. Bounds bounds(const DrawPaint&) const { return fCurrentClipBounds; } Bounds bounds(const NoOp&) const { return Bounds::MakeEmpty(); } // NoOps don't draw. Bounds bounds(const DrawSprite& op) const { const SkBitmap& bm = op.bitmap; return Bounds::MakeXYWH(op.left, op.top, bm.width(), bm.height()); // Ignores the matrix. } Bounds bounds(const DrawRect& op) const { return this->adjustAndMap(op.rect, &op.paint); } Bounds bounds(const DrawOval& op) const { return this->adjustAndMap(op.oval, &op.paint); } Bounds bounds(const DrawRRect& op) const { return this->adjustAndMap(op.rrect.rect(), &op.paint); } Bounds bounds(const DrawDRRect& op) const { return this->adjustAndMap(op.outer.rect(), &op.paint); } Bounds bounds(const DrawImage& op) const { const SkImage* image = op.image; SkRect rect = SkRect::MakeXYWH(op.left, op.top, image->width(), image->height()); return this->adjustAndMap(rect, op.paint); } Bounds bounds(const DrawImageRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmapRectToRect& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmapNine& op) const { return this->adjustAndMap(op.dst, op.paint); } Bounds bounds(const DrawBitmap& op) const { const SkBitmap& bm = op.bitmap; return this->adjustAndMap(SkRect::MakeXYWH(op.left, op.top, bm.width(), bm.height()), op.paint); } Bounds bounds(const DrawBitmapMatrix& op) const { const SkBitmap& bm = op.bitmap; SkRect dst = SkRect::MakeWH(bm.width(), bm.height()); op.matrix.mapRect(&dst); return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPath& op) const { return op.path.isInverseFillType() ? fCurrentClipBounds : this->adjustAndMap(op.path.getBounds(), &op.paint); } Bounds bounds(const DrawPoints& op) const { SkRect dst; dst.set(op.pts, op.count); // Pad the bounding box a little to make sure hairline points' bounds aren't empty. SkScalar stroke = SkMaxScalar(op.paint.getStrokeWidth(), 0.01f); dst.outset(stroke/2, stroke/2); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPatch& op) const { SkRect dst; dst.set(op.cubics, SkPatchUtils::kNumCtrlPts); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawVertices& op) const { SkRect dst; dst.set(op.vertices, op.vertexCount); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPicture& op) const { SkRect dst = op.picture->cullRect(); if (op.matrix) { op.matrix->mapRect(&dst); } return this->adjustAndMap(dst, op.paint); } Bounds bounds(const DrawPosText& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkRect dst; dst.set(op.pos, N); AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawPosTextH& op) const { const int N = op.paint.countText(op.text, op.byteLength); if (N == 0) { return Bounds::MakeEmpty(); } SkScalar left = op.xpos[0], right = op.xpos[0]; for (int i = 1; i < N; i++) { left = SkMinScalar(left, op.xpos[i]); right = SkMaxScalar(right, op.xpos[i]); } SkRect dst = { left, op.y, right, op.y }; AdjustTextForFontMetrics(&dst, op.paint); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextOnPath& op) const { SkRect dst = op.path.getBounds(); // Pad all sides by the maximum padding in any direction we'd normally apply. SkRect pad = { 0, 0, 0, 0}; AdjustTextForFontMetrics(&pad, op.paint); // That maximum padding happens to always be the right pad today. SkASSERT(pad.fLeft == -pad.fRight); SkASSERT(pad.fTop == -pad.fBottom); SkASSERT(pad.fRight > pad.fBottom); dst.outset(pad.fRight, pad.fRight); return this->adjustAndMap(dst, &op.paint); } Bounds bounds(const DrawTextBlob& op) const { SkRect dst = op.blob->bounds(); dst.offset(op.x, op.y); return this->adjustAndMap(dst, &op.paint); } static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) { #ifdef SK_DEBUG SkRect correct = *rect; #endif // crbug.com/373785 ~~> xPad = 4x yPad // crbug.com/424824 ~~> bump yPad from 2x text size to 2.5x const SkScalar yPad = 2.5f * paint.getTextSize(), xPad = 4.0f * yPad; rect->outset(xPad, yPad); #ifdef SK_DEBUG SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); correct.fLeft += metrics.fXMin; correct.fTop += metrics.fTop; correct.fRight += metrics.fXMax; correct.fBottom += metrics.fBottom; // See skia:2862 for why we ignore small text sizes. SkASSERTF(paint.getTextSize() < 0.001f || rect->contains(correct), "%f %f %f %f vs. %f %f %f %f\n", -xPad, -yPad, +xPad, +yPad, metrics.fXMin, metrics.fTop, metrics.fXMax, metrics.fBottom); #endif } // Returns true if rect was meaningfully adjusted for the effects of paint, // false if the paint could affect the rect in unknown ways. static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) { if (paint) { if (paint->canComputeFastBounds()) { *rect = paint->computeFastBounds(*rect, rect); return true; } return false; } return true; } bool adjustForSaveLayerPaints(SkRect* rect, int savesToIgnore = 0) const { for (int i = fSaveStack.count() - 1 - savesToIgnore; i >= 0; i--) { if (!AdjustForPaint(fSaveStack[i].paint, rect)) { return false; } } return true; } // Adjust rect for all paints that may affect its geometry, then map it to identity space. Bounds adjustAndMap(SkRect rect, const SkPaint* paint) const { // Inverted rectangles really confuse our BBHs. rect.sort(); // Adjust the rect for its own paint. if (!AdjustForPaint(paint, &rect)) { // The paint could do anything to our bounds. The only safe answer is the current clip. return fCurrentClipBounds; } // Adjust rect for all the paints from the SaveLayers we're inside. if (!this->adjustForSaveLayerPaints(&rect)) { // Same deal as above. return fCurrentClipBounds; } // Map the rect back to identity space. fCTM->mapRect(&rect); // Nothing can draw outside the current clip. // (Only bounded ops call into this method, so oddballs like Clear don't matter here.) rect.intersect(fCurrentClipBounds); return rect; } // We do not guarantee anything for operations outside of the cull rect const SkRect fCullRect; // Conservative identity-space bounds for each op in the SkRecord. SkAutoTMalloc<Bounds> fBounds; // We walk fCurrentOp through the SkRecord, as we go using updateCTM() // and updateClipBounds() to maintain the exact CTM (fCTM) and conservative // identity-space bounds of the current clip (fCurrentClipBounds). unsigned fCurrentOp; const SkMatrix* fCTM; Bounds fCurrentClipBounds; // Used to track the bounds of Save/Restore blocks and the control ops inside them. SkTDArray<SaveBounds> fSaveStack; SkTDArray<unsigned> fControlIndices; }; } // namespace SkRecords
void process_tree(struct rooted_tree *tree, struct parameters params) { struct llist *descendants; switch (params.mode) { case EXACT: descendants = nodes_from_labels(tree, params.labels); if (NULL == descendants) { perror(NULL); exit(EXIT_FAILURE); } if (0 == descendants->count) { fprintf (stderr, "WARNING: no label matches.\n"); /* I don't consider this a failure: it is just the case * that the tree does not contain the specified labels. * */ exit(EXIT_SUCCESS); } break; case REGEXP: descendants = nodes_from_regexp(tree, params.regexp); if (NULL == descendants) { perror(NULL); exit(EXIT_FAILURE); } if (0 == descendants->count) { fprintf (stderr, "WARNING: no match for regexp /%s/\n", params.regexp_string); exit(EXIT_SUCCESS); /** see above */ } break; default: fprintf (stderr, "Unknown mode %d\n", params.mode); exit(EXIT_FAILURE); } /* We need a copy b/c lca() modifies its arg */ struct llist *desc_clone = shallow_copy(descendants); if (NULL == desc_clone) { perror(NULL); exit(EXIT_FAILURE); } struct rnode *subtree_root = lca(tree, desc_clone); if (NULL == subtree_root) { perror(NULL); exit(EXIT_FAILURE); } free(desc_clone); /* elems freed in lca() */ /* Jump up tree to get context, if any was required ('context' > 0) */ int context; for (context = params.context; context > 0; context--) if (! is_root(subtree_root)) subtree_root = subtree_root->parent; // TODO: could not replace to_newick() by dump_newick() due to side // effects. Investigate. if (NULL != subtree_root) { if ((! params.check_monophyly) || (is_monophyletic(descendants, subtree_root))) { /* monophyly of input labels is verified or not * requested */ char *newick; if (params.siblings) { struct llist *sibs = siblings(subtree_root); if (NULL == sibs) { perror(NULL); exit(EXIT_FAILURE); } struct list_elem *el; for (el=sibs->head;NULL!=el;el=el->next) { struct rnode *sib; sib = el->data; newick = to_newick(sib); printf ("%s\n", newick); free(newick); } destroy_llist(sibs); } else { /* normal operation: print clade defined by * labels. */ newick = to_newick(subtree_root); printf ("%s\n", newick); free(newick); } } } else { fprintf (stderr, "WARNING: LCA not found\n"); } destroy_llist(descendants); }
Statement* Cssize::debubble(Block* children, Statement* parent) { Has_Block* previous_parent = 0; std::vector<std::pair<bool, Block*>> baz = slice_by_bubble(children); Block* result = SASS_MEMORY_NEW(ctx.mem, Block, children->pstate()); for (size_t i = 0, L = baz.size(); i < L; ++i) { bool is_bubble = baz[i].first; Block* slice = baz[i].second; if (!is_bubble) { if (!parent) { *result << slice; } else if (previous_parent) { *previous_parent->block() += slice; } else { previous_parent = static_cast<Has_Block*>(shallow_copy(parent)); previous_parent->tabs(parent->tabs()); Has_Block* new_parent = static_cast<Has_Block*>(shallow_copy(parent)); new_parent->block(slice); new_parent->tabs(parent->tabs()); *result << new_parent; } continue; } Block* wrapper_block = SASS_MEMORY_NEW(ctx.mem, Block, children->block()->pstate(), children->block()->length(), children->block()->is_root()); for (size_t j = 0, K = slice->length(); j < K; ++j) { Statement* ss = 0; Bubble* b = static_cast<Bubble*>((*slice)[j]); if (!parent || parent->statement_type() != Statement::MEDIA || b->node()->statement_type() != Statement::MEDIA || static_cast<Media_Block*>(b->node())->media_queries() == static_cast<Media_Block*>(parent)->media_queries()) { ss = b->node(); } else { List* mq = merge_media_queries(static_cast<Media_Block*>(b->node()), static_cast<Media_Block*>(parent)); if (!mq->length()) continue; static_cast<Media_Block*>(b->node())->media_queries(mq); ss = b->node(); } if (!ss) continue; ss->tabs(ss->tabs() + b->tabs()); ss->group_end(b->group_end()); if (!ss) continue; Block* bb = SASS_MEMORY_NEW(ctx.mem, Block, children->block()->pstate(), children->block()->length(), children->block()->is_root()); *bb << ss->perform(this); Statement* wrapper = flatten(bb); *wrapper_block << wrapper; if (wrapper->block()->length()) { previous_parent = 0; } } if (wrapper_block) { *result << flatten(wrapper_block); } } return flatten(result); }
/*! zcovector=_zcovector operator */ inline zcovector& zcovector::operator=(const _zcovector& vec) {VERBOSE_REPORT; shallow_copy(vec); return *this; }